src/share/vm/c1/c1_GraphBuilder.cpp

Print this page
rev 4136 : 7153771: array bound check elimination for c1
Summary: when possible optimize out array bound checks, inserting predicates when needed.
Reviewed-by:

@@ -945,11 +945,13 @@
   state->store_local(index, round_fp(x));
 }
 
 
 void GraphBuilder::load_indexed(BasicType type) {
-  ValueStack* state_before = copy_state_for_exception();
+  // In case of in block code motion in range check elimination
+  ValueStack* state_before = compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception();
+  compilation()->set_has_access_indexed(true);
   Value index = ipop();
   Value array = apop();
   Value length = NULL;
   if (CSEArrayLength ||
       (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||

@@ -959,11 +961,13 @@
   push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before)));
 }
 
 
 void GraphBuilder::store_indexed(BasicType type) {
-  ValueStack* state_before = copy_state_for_exception();
+  // In case of in block code motion in range check elimination
+  ValueStack* state_before = compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception();
+  compilation()->set_has_access_indexed(true);
   Value value = pop(as_ValueType(type));
   Value index = ipop();
   Value array = apop();
   Value length = NULL;
   if (CSEArrayLength ||

@@ -1177,11 +1181,13 @@
 
 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) {
   BlockBegin* tsux = block_at(stream()->get_dest());
   BlockBegin* fsux = block_at(stream()->next_bci());
   bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
-  Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb));
+  // In case of loop invariant code motion or predicate insertion
+  // before the body of a loop the state is needed
+  Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : NULL, is_bb));
 
   assert(i->as_Goto() == NULL ||
          (i->as_Goto()->sux_at(0) == tsux  && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) ||
          (i->as_Goto()->sux_at(0) == fsux  && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()),
          "safepoint state of Goto returned by canonicalizer incorrect");

@@ -1292,11 +1298,13 @@
     //       can handle canonicalized forms that contain more than one node.
     Value key = append(new Constant(new IntConstant(sw.low_key())));
     BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
     BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
-    ValueStack* state_before = is_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
   } else {
     // collect successors
     BlockList* sux = new BlockList(l + 1, NULL);
     int i;

@@ -1306,11 +1314,13 @@
       if (sw.dest_offset_at(i) < 0) has_bb = true;
     }
     // add default successor
     if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
-    ValueStack* state_before = has_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = (has_bb || compilation()->is_optimistic())? copy_state_before() : NULL;
     Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
 #ifdef ASSERT
     if (res->as_Goto()) {
       for (i = 0; i < l; i++) {
         if (sux->at(i) == res->as_Goto()->sux_at(0)) {

@@ -1334,11 +1344,13 @@
     LookupswitchPair pair = sw.pair_at(0);
     Value key = append(new Constant(new IntConstant(pair.match())));
     BlockBegin* tsux = block_at(bci() + pair.offset());
     BlockBegin* fsux = block_at(bci() + sw.default_offset());
     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
-    ValueStack* state_before = is_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
   } else {
     // collect successors & keys
     BlockList* sux = new BlockList(l + 1, NULL);
     intArray* keys = new intArray(l, 0);

@@ -1351,11 +1363,13 @@
       keys->at_put(i, pair.match());
     }
     // add default successor
     if (sw.default_offset() < 0) has_bb = true;
     sux->at_put(i, block_at(bci() + sw.default_offset()));
-    ValueStack* state_before = has_bb ? copy_state_before() : NULL;
+    // In case of loop invariant code motion or predicate insertion
+    // before the body of a loop the state is needed
+    ValueStack* state_before = (has_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
     Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
 #ifdef ASSERT
     if (res->as_Goto()) {
       for (i = 0; i < l; i++) {
         if (sux->at(i) == res->as_Goto()->sux_at(0)) {