Mercurial > hg > truffle
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)) { |