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:


 930       // Also check parent jsrs (if any) at this time to see whether
 931       // they are using this local. We don't handle skipping over a
 932       // ret.
 933       for (ScopeData* cur_scope_data = scope_data()->parent();
 934            cur_scope_data != NULL && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope();
 935            cur_scope_data = cur_scope_data->parent()) {
 936         if (cur_scope_data->jsr_return_address_local() == index) {
 937           BAILOUT("subroutine overwrites return address from previous subroutine");
 938         }
 939       }
 940     } else if (index == scope_data()->jsr_return_address_local()) {
 941       scope_data()->set_jsr_return_address_local(-1);
 942     }
 943   }
 944 
 945   state->store_local(index, round_fp(x));
 946 }
 947 
 948 
 949 void GraphBuilder::load_indexed(BasicType type) {
 950   ValueStack* state_before = copy_state_for_exception();


 951   Value index = ipop();
 952   Value array = apop();
 953   Value length = NULL;
 954   if (CSEArrayLength ||
 955       (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
 956       (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
 957     length = append(new ArrayLength(array, state_before));
 958   }
 959   push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before)));
 960 }
 961 
 962 
 963 void GraphBuilder::store_indexed(BasicType type) {
 964   ValueStack* state_before = copy_state_for_exception();


 965   Value value = pop(as_ValueType(type));
 966   Value index = ipop();
 967   Value array = apop();
 968   Value length = NULL;
 969   if (CSEArrayLength ||
 970       (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
 971       (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
 972     length = append(new ArrayLength(array, state_before));
 973   }
 974   StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before);
 975   append(result);
 976   _memory->store_value(value);
 977 
 978   if (type == T_OBJECT && is_profiling()) {
 979     // Note that we'd collect profile data in this method if we wanted it.
 980     compilation()->set_would_profile(true);
 981 
 982     if (profile_checkcasts()) {
 983       result->set_profiled_method(method());
 984       result->set_profiled_bci(bci());


1162 
1163 
1164 void GraphBuilder::_goto(int from_bci, int to_bci) {
1165   Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci);
1166   if (is_profiling()) {
1167     compilation()->set_would_profile(true);
1168     x->set_profiled_bci(bci());
1169     if (profile_branches()) {
1170       x->set_profiled_method(method());
1171       x->set_should_profile(true);
1172     }
1173   }
1174   append(x);
1175 }
1176 
1177 
1178 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) {
1179   BlockBegin* tsux = block_at(stream()->get_dest());
1180   BlockBegin* fsux = block_at(stream()->next_bci());
1181   bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
1182   Instruction *i = append(new If(x, cond, false, y, tsux, fsux, is_bb ? state_before : NULL, is_bb));


1183 
1184   assert(i->as_Goto() == NULL ||
1185          (i->as_Goto()->sux_at(0) == tsux  && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) ||
1186          (i->as_Goto()->sux_at(0) == fsux  && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()),
1187          "safepoint state of Goto returned by canonicalizer incorrect");
1188 
1189   if (is_profiling()) {
1190     If* if_node = i->as_If();
1191     if (if_node != NULL) {
1192       // Note that we'd collect profile data in this method if we wanted it.
1193       compilation()->set_would_profile(true);
1194       // At level 2 we need the proper bci to count backedges
1195       if_node->set_profiled_bci(bci());
1196       if (profile_branches()) {
1197         // Successors can be rotated by the canonicalizer, check for this case.
1198         if_node->set_profiled_method(method());
1199         if_node->set_should_profile(true);
1200         if (if_node->tsux() == fsux) {
1201           if_node->set_swapped(true);
1202         }


1277   if (local_index != scope_data()->jsr_return_address_local()) {
1278     BAILOUT("can not handle complicated jsr/ret constructs");
1279   }
1280 
1281   // Rets simply become (NON-SAFEPOINT) gotos to the jsr continuation
1282   append(new Goto(scope_data()->jsr_continuation(), false));
1283 }
1284 
1285 
1286 void GraphBuilder::table_switch() {
1287   Bytecode_tableswitch sw(stream());
1288   const int l = sw.length();
1289   if (CanonicalizeNodes && l == 1) {
1290     // total of 2 successors => use If instead of switch
1291     // Note: This code should go into the canonicalizer as soon as it can
1292     //       can handle canonicalized forms that contain more than one node.
1293     Value key = append(new Constant(new IntConstant(sw.low_key())));
1294     BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
1295     BlockBegin* fsux = block_at(bci() + sw.default_offset());
1296     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1297     ValueStack* state_before = is_bb ? copy_state_before() : NULL;


1298     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1299   } else {
1300     // collect successors
1301     BlockList* sux = new BlockList(l + 1, NULL);
1302     int i;
1303     bool has_bb = false;
1304     for (i = 0; i < l; i++) {
1305       sux->at_put(i, block_at(bci() + sw.dest_offset_at(i)));
1306       if (sw.dest_offset_at(i) < 0) has_bb = true;
1307     }
1308     // add default successor
1309     if (sw.default_offset() < 0) has_bb = true;
1310     sux->at_put(i, block_at(bci() + sw.default_offset()));
1311     ValueStack* state_before = has_bb ? copy_state_before() : NULL;


1312     Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
1313 #ifdef ASSERT
1314     if (res->as_Goto()) {
1315       for (i = 0; i < l; i++) {
1316         if (sux->at(i) == res->as_Goto()->sux_at(0)) {
1317           assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect");
1318         }
1319       }
1320     }
1321 #endif
1322   }
1323 }
1324 
1325 
1326 void GraphBuilder::lookup_switch() {
1327   Bytecode_lookupswitch sw(stream());
1328   const int l = sw.number_of_pairs();
1329   if (CanonicalizeNodes && l == 1) {
1330     // total of 2 successors => use If instead of switch
1331     // Note: This code should go into the canonicalizer as soon as it can
1332     //       can handle canonicalized forms that contain more than one node.
1333     // simplify to If
1334     LookupswitchPair pair = sw.pair_at(0);
1335     Value key = append(new Constant(new IntConstant(pair.match())));
1336     BlockBegin* tsux = block_at(bci() + pair.offset());
1337     BlockBegin* fsux = block_at(bci() + sw.default_offset());
1338     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1339     ValueStack* state_before = is_bb ? copy_state_before() : NULL;


1340     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1341   } else {
1342     // collect successors & keys
1343     BlockList* sux = new BlockList(l + 1, NULL);
1344     intArray* keys = new intArray(l, 0);
1345     int i;
1346     bool has_bb = false;
1347     for (i = 0; i < l; i++) {
1348       LookupswitchPair pair = sw.pair_at(i);
1349       if (pair.offset() < 0) has_bb = true;
1350       sux->at_put(i, block_at(bci() + pair.offset()));
1351       keys->at_put(i, pair.match());
1352     }
1353     // add default successor
1354     if (sw.default_offset() < 0) has_bb = true;
1355     sux->at_put(i, block_at(bci() + sw.default_offset()));
1356     ValueStack* state_before = has_bb ? copy_state_before() : NULL;


1357     Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
1358 #ifdef ASSERT
1359     if (res->as_Goto()) {
1360       for (i = 0; i < l; i++) {
1361         if (sux->at(i) == res->as_Goto()->sux_at(0)) {
1362           assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect");
1363         }
1364       }
1365     }
1366 #endif
1367   }
1368 }
1369 
1370 void GraphBuilder::call_register_finalizer() {
1371   // If the receiver requires finalization then emit code to perform
1372   // the registration on return.
1373 
1374   // Gather some type information about the receiver
1375   Value receiver = state()->local_at(0);
1376   assert(receiver != NULL, "must have a receiver");




 930       // Also check parent jsrs (if any) at this time to see whether
 931       // they are using this local. We don't handle skipping over a
 932       // ret.
 933       for (ScopeData* cur_scope_data = scope_data()->parent();
 934            cur_scope_data != NULL && cur_scope_data->parsing_jsr() && cur_scope_data->scope() == scope();
 935            cur_scope_data = cur_scope_data->parent()) {
 936         if (cur_scope_data->jsr_return_address_local() == index) {
 937           BAILOUT("subroutine overwrites return address from previous subroutine");
 938         }
 939       }
 940     } else if (index == scope_data()->jsr_return_address_local()) {
 941       scope_data()->set_jsr_return_address_local(-1);
 942     }
 943   }
 944 
 945   state->store_local(index, round_fp(x));
 946 }
 947 
 948 
 949 void GraphBuilder::load_indexed(BasicType type) {
 950   // In case of in block code motion in range check elimination
 951   ValueStack* state_before = compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception();
 952   compilation()->set_has_access_indexed(true);
 953   Value index = ipop();
 954   Value array = apop();
 955   Value length = NULL;
 956   if (CSEArrayLength ||
 957       (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
 958       (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
 959     length = append(new ArrayLength(array, state_before));
 960   }
 961   push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before)));
 962 }
 963 
 964 
 965 void GraphBuilder::store_indexed(BasicType type) {
 966   // In case of in block code motion in range check elimination
 967   ValueStack* state_before = compilation()->is_optimistic() ? copy_state_before() : copy_state_for_exception();
 968   compilation()->set_has_access_indexed(true);
 969   Value value = pop(as_ValueType(type));
 970   Value index = ipop();
 971   Value array = apop();
 972   Value length = NULL;
 973   if (CSEArrayLength ||
 974       (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
 975       (array->as_NewArray() && array->as_NewArray()->length() && array->as_NewArray()->length()->type()->is_constant())) {
 976     length = append(new ArrayLength(array, state_before));
 977   }
 978   StoreIndexed* result = new StoreIndexed(array, index, length, type, value, state_before);
 979   append(result);
 980   _memory->store_value(value);
 981 
 982   if (type == T_OBJECT && is_profiling()) {
 983     // Note that we'd collect profile data in this method if we wanted it.
 984     compilation()->set_would_profile(true);
 985 
 986     if (profile_checkcasts()) {
 987       result->set_profiled_method(method());
 988       result->set_profiled_bci(bci());


1166 
1167 
1168 void GraphBuilder::_goto(int from_bci, int to_bci) {
1169   Goto *x = new Goto(block_at(to_bci), to_bci <= from_bci);
1170   if (is_profiling()) {
1171     compilation()->set_would_profile(true);
1172     x->set_profiled_bci(bci());
1173     if (profile_branches()) {
1174       x->set_profiled_method(method());
1175       x->set_should_profile(true);
1176     }
1177   }
1178   append(x);
1179 }
1180 
1181 
1182 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) {
1183   BlockBegin* tsux = block_at(stream()->get_dest());
1184   BlockBegin* fsux = block_at(stream()->next_bci());
1185   bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci();
1186   // In case of loop invariant code motion or predicate insertion
1187   // before the body of a loop the state is needed
1188   Instruction *i = append(new If(x, cond, false, y, tsux, fsux, (is_bb || compilation()->is_optimistic()) ? state_before : NULL, is_bb));
1189 
1190   assert(i->as_Goto() == NULL ||
1191          (i->as_Goto()->sux_at(0) == tsux  && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) ||
1192          (i->as_Goto()->sux_at(0) == fsux  && i->as_Goto()->is_safepoint() == fsux->bci() < stream()->cur_bci()),
1193          "safepoint state of Goto returned by canonicalizer incorrect");
1194 
1195   if (is_profiling()) {
1196     If* if_node = i->as_If();
1197     if (if_node != NULL) {
1198       // Note that we'd collect profile data in this method if we wanted it.
1199       compilation()->set_would_profile(true);
1200       // At level 2 we need the proper bci to count backedges
1201       if_node->set_profiled_bci(bci());
1202       if (profile_branches()) {
1203         // Successors can be rotated by the canonicalizer, check for this case.
1204         if_node->set_profiled_method(method());
1205         if_node->set_should_profile(true);
1206         if (if_node->tsux() == fsux) {
1207           if_node->set_swapped(true);
1208         }


1283   if (local_index != scope_data()->jsr_return_address_local()) {
1284     BAILOUT("can not handle complicated jsr/ret constructs");
1285   }
1286 
1287   // Rets simply become (NON-SAFEPOINT) gotos to the jsr continuation
1288   append(new Goto(scope_data()->jsr_continuation(), false));
1289 }
1290 
1291 
1292 void GraphBuilder::table_switch() {
1293   Bytecode_tableswitch sw(stream());
1294   const int l = sw.length();
1295   if (CanonicalizeNodes && l == 1) {
1296     // total of 2 successors => use If instead of switch
1297     // Note: This code should go into the canonicalizer as soon as it can
1298     //       can handle canonicalized forms that contain more than one node.
1299     Value key = append(new Constant(new IntConstant(sw.low_key())));
1300     BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
1301     BlockBegin* fsux = block_at(bci() + sw.default_offset());
1302     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1303     // In case of loop invariant code motion or predicate insertion
1304     // before the body of a loop the state is needed
1305     ValueStack* state_before = (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
1306     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1307   } else {
1308     // collect successors
1309     BlockList* sux = new BlockList(l + 1, NULL);
1310     int i;
1311     bool has_bb = false;
1312     for (i = 0; i < l; i++) {
1313       sux->at_put(i, block_at(bci() + sw.dest_offset_at(i)));
1314       if (sw.dest_offset_at(i) < 0) has_bb = true;
1315     }
1316     // add default successor
1317     if (sw.default_offset() < 0) has_bb = true;
1318     sux->at_put(i, block_at(bci() + sw.default_offset()));
1319     // In case of loop invariant code motion or predicate insertion
1320     // before the body of a loop the state is needed
1321     ValueStack* state_before = (has_bb || compilation()->is_optimistic())? copy_state_before() : NULL;
1322     Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
1323 #ifdef ASSERT
1324     if (res->as_Goto()) {
1325       for (i = 0; i < l; i++) {
1326         if (sux->at(i) == res->as_Goto()->sux_at(0)) {
1327           assert(res->as_Goto()->is_safepoint() == sw.dest_offset_at(i) < 0, "safepoint state of Goto returned by canonicalizer incorrect");
1328         }
1329       }
1330     }
1331 #endif
1332   }
1333 }
1334 
1335 
1336 void GraphBuilder::lookup_switch() {
1337   Bytecode_lookupswitch sw(stream());
1338   const int l = sw.number_of_pairs();
1339   if (CanonicalizeNodes && l == 1) {
1340     // total of 2 successors => use If instead of switch
1341     // Note: This code should go into the canonicalizer as soon as it can
1342     //       can handle canonicalized forms that contain more than one node.
1343     // simplify to If
1344     LookupswitchPair pair = sw.pair_at(0);
1345     Value key = append(new Constant(new IntConstant(pair.match())));
1346     BlockBegin* tsux = block_at(bci() + pair.offset());
1347     BlockBegin* fsux = block_at(bci() + sw.default_offset());
1348     bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1349     // In case of loop invariant code motion or predicate insertion
1350     // before the body of a loop the state is needed
1351     ValueStack* state_before = (is_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
1352     append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1353   } else {
1354     // collect successors & keys
1355     BlockList* sux = new BlockList(l + 1, NULL);
1356     intArray* keys = new intArray(l, 0);
1357     int i;
1358     bool has_bb = false;
1359     for (i = 0; i < l; i++) {
1360       LookupswitchPair pair = sw.pair_at(i);
1361       if (pair.offset() < 0) has_bb = true;
1362       sux->at_put(i, block_at(bci() + pair.offset()));
1363       keys->at_put(i, pair.match());
1364     }
1365     // add default successor
1366     if (sw.default_offset() < 0) has_bb = true;
1367     sux->at_put(i, block_at(bci() + sw.default_offset()));
1368     // In case of loop invariant code motion or predicate insertion
1369     // before the body of a loop the state is needed
1370     ValueStack* state_before = (has_bb || compilation()->is_optimistic()) ? copy_state_before() : NULL;
1371     Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
1372 #ifdef ASSERT
1373     if (res->as_Goto()) {
1374       for (i = 0; i < l; i++) {
1375         if (sux->at(i) == res->as_Goto()->sux_at(0)) {
1376           assert(res->as_Goto()->is_safepoint() == sw.pair_at(i).offset() < 0, "safepoint state of Goto returned by canonicalizer incorrect");
1377         }
1378       }
1379     }
1380 #endif
1381   }
1382 }
1383 
1384 void GraphBuilder::call_register_finalizer() {
1385   // If the receiver requires finalization then emit code to perform
1386   // the registration on return.
1387 
1388   // Gather some type information about the receiver
1389   Value receiver = state()->local_at(0);
1390   assert(receiver != NULL, "must have a receiver");