comparison src/share/vm/c1/c1_GraphBuilder.cpp @ 8860:46f6f063b272

7153771: array bound check elimination for c1 Summary: when possible optimize out array bound checks, inserting predicates when needed. Reviewed-by: never, kvn, twisti Contributed-by: thomaswue <thomas.wuerthinger@oracle.com>
author roland
date Thu, 21 Mar 2013 09:27:54 +0100
parents 60bba1398c51
children b800986664f4
comparison
equal deleted inserted replaced
8780:98f3af397705 8860:46f6f063b272
945 state->store_local(index, round_fp(x)); 945 state->store_local(index, round_fp(x));
946 } 946 }
947 947
948 948
949 void GraphBuilder::load_indexed(BasicType type) { 949 void GraphBuilder::load_indexed(BasicType type) {
950 ValueStack* state_before = copy_state_for_exception(); 950 // In case of in block code motion in range check elimination
951 ValueStack* state_before = copy_state_indexed_access();
952 compilation()->set_has_access_indexed(true);
951 Value index = ipop(); 953 Value index = ipop();
952 Value array = apop(); 954 Value array = apop();
953 Value length = NULL; 955 Value length = NULL;
954 if (CSEArrayLength || 956 if (CSEArrayLength ||
955 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || 957 (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) ||
959 push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before))); 961 push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before)));
960 } 962 }
961 963
962 964
963 void GraphBuilder::store_indexed(BasicType type) { 965 void GraphBuilder::store_indexed(BasicType type) {
964 ValueStack* state_before = copy_state_for_exception(); 966 // In case of in block code motion in range check elimination
967 ValueStack* state_before = copy_state_indexed_access();
968 compilation()->set_has_access_indexed(true);
965 Value value = pop(as_ValueType(type)); 969 Value value = pop(as_ValueType(type));
966 Value index = ipop(); 970 Value index = ipop();
967 Value array = apop(); 971 Value array = apop();
968 Value length = NULL; 972 Value length = NULL;
969 if (CSEArrayLength || 973 if (CSEArrayLength ||
1177 1181
1178 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) { 1182 void GraphBuilder::if_node(Value x, If::Condition cond, Value y, ValueStack* state_before) {
1179 BlockBegin* tsux = block_at(stream()->get_dest()); 1183 BlockBegin* tsux = block_at(stream()->get_dest());
1180 BlockBegin* fsux = block_at(stream()->next_bci()); 1184 BlockBegin* fsux = block_at(stream()->next_bci());
1181 bool is_bb = tsux->bci() < stream()->cur_bci() || fsux->bci() < stream()->cur_bci(); 1185 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)); 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));
1183 1189
1184 assert(i->as_Goto() == NULL || 1190 assert(i->as_Goto() == NULL ||
1185 (i->as_Goto()->sux_at(0) == tsux && i->as_Goto()->is_safepoint() == tsux->bci() < stream()->cur_bci()) || 1191 (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()), 1192 (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"); 1193 "safepoint state of Goto returned by canonicalizer incorrect");
1292 // can handle canonicalized forms that contain more than one node. 1298 // can handle canonicalized forms that contain more than one node.
1293 Value key = append(new Constant(new IntConstant(sw.low_key()))); 1299 Value key = append(new Constant(new IntConstant(sw.low_key())));
1294 BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0)); 1300 BlockBegin* tsux = block_at(bci() + sw.dest_offset_at(0));
1295 BlockBegin* fsux = block_at(bci() + sw.default_offset()); 1301 BlockBegin* fsux = block_at(bci() + sw.default_offset());
1296 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); 1302 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1297 ValueStack* state_before = is_bb ? copy_state_before() : NULL; 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 = copy_state_if_bb(is_bb);
1298 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); 1306 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1299 } else { 1307 } else {
1300 // collect successors 1308 // collect successors
1301 BlockList* sux = new BlockList(l + 1, NULL); 1309 BlockList* sux = new BlockList(l + 1, NULL);
1302 int i; 1310 int i;
1306 if (sw.dest_offset_at(i) < 0) has_bb = true; 1314 if (sw.dest_offset_at(i) < 0) has_bb = true;
1307 } 1315 }
1308 // add default successor 1316 // add default successor
1309 if (sw.default_offset() < 0) has_bb = true; 1317 if (sw.default_offset() < 0) has_bb = true;
1310 sux->at_put(i, block_at(bci() + sw.default_offset())); 1318 sux->at_put(i, block_at(bci() + sw.default_offset()));
1311 ValueStack* state_before = has_bb ? copy_state_before() : NULL; 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 = copy_state_if_bb(has_bb);
1312 Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb)); 1322 Instruction* res = append(new TableSwitch(ipop(), sux, sw.low_key(), state_before, has_bb));
1313 #ifdef ASSERT 1323 #ifdef ASSERT
1314 if (res->as_Goto()) { 1324 if (res->as_Goto()) {
1315 for (i = 0; i < l; i++) { 1325 for (i = 0; i < l; i++) {
1316 if (sux->at(i) == res->as_Goto()->sux_at(0)) { 1326 if (sux->at(i) == res->as_Goto()->sux_at(0)) {
1334 LookupswitchPair pair = sw.pair_at(0); 1344 LookupswitchPair pair = sw.pair_at(0);
1335 Value key = append(new Constant(new IntConstant(pair.match()))); 1345 Value key = append(new Constant(new IntConstant(pair.match())));
1336 BlockBegin* tsux = block_at(bci() + pair.offset()); 1346 BlockBegin* tsux = block_at(bci() + pair.offset());
1337 BlockBegin* fsux = block_at(bci() + sw.default_offset()); 1347 BlockBegin* fsux = block_at(bci() + sw.default_offset());
1338 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci(); 1348 bool is_bb = tsux->bci() < bci() || fsux->bci() < bci();
1339 ValueStack* state_before = is_bb ? copy_state_before() : NULL; 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 = copy_state_if_bb(is_bb);;
1340 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb)); 1352 append(new If(ipop(), If::eql, true, key, tsux, fsux, state_before, is_bb));
1341 } else { 1353 } else {
1342 // collect successors & keys 1354 // collect successors & keys
1343 BlockList* sux = new BlockList(l + 1, NULL); 1355 BlockList* sux = new BlockList(l + 1, NULL);
1344 intArray* keys = new intArray(l, 0); 1356 intArray* keys = new intArray(l, 0);
1351 keys->at_put(i, pair.match()); 1363 keys->at_put(i, pair.match());
1352 } 1364 }
1353 // add default successor 1365 // add default successor
1354 if (sw.default_offset() < 0) has_bb = true; 1366 if (sw.default_offset() < 0) has_bb = true;
1355 sux->at_put(i, block_at(bci() + sw.default_offset())); 1367 sux->at_put(i, block_at(bci() + sw.default_offset()));
1356 ValueStack* state_before = has_bb ? copy_state_before() : NULL; 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 = copy_state_if_bb(has_bb);
1357 Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb)); 1371 Instruction* res = append(new LookupSwitch(ipop(), sux, keys, state_before, has_bb));
1358 #ifdef ASSERT 1372 #ifdef ASSERT
1359 if (res->as_Goto()) { 1373 if (res->as_Goto()) {
1360 for (i = 0; i < l; i++) { 1374 for (i = 0; i < l; i++) {
1361 if (sux->at(i) == res->as_Goto()->sux_at(0)) { 1375 if (sux->at(i) == res->as_Goto()->sux_at(0)) {