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,955 **** state->store_local(index, round_fp(x)); } void GraphBuilder::load_indexed(BasicType type) { ! ValueStack* state_before = copy_state_for_exception(); Value index = ipop(); Value array = apop(); Value length = NULL; if (CSEArrayLength || (array->as_AccessField() && array->as_AccessField()->field()->is_constant()) || --- 945,957 ---- state->store_local(index, round_fp(x)); } void GraphBuilder::load_indexed(BasicType type) { ! // 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,969 **** 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(); Value value = pop(as_ValueType(type)); Value index = ipop(); Value array = apop(); Value length = NULL; if (CSEArrayLength || --- 961,973 ---- push(as_ValueType(type), append(new LoadIndexed(array, index, length, type, state_before))); } void GraphBuilder::store_indexed(BasicType type) { ! // 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,1187 **** 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)); 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"); --- 1181,1193 ---- 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(); ! // 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,1302 **** // 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; 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; --- 1298,1310 ---- // 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(); ! // 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,1316 **** 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; 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)) { --- 1314,1326 ---- 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())); ! // 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,1344 **** 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; 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); --- 1344,1356 ---- 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(); ! // 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,1361 **** 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; 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)) { --- 1363,1375 ---- 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())); ! // 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)) {