src/share/vm/c1/c1_Instruction.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:

*** 32,49 **** --- 32,60 ---- // Implementation of Instruction + int Instruction::dominator_depth() { + int result = -1; + if (block()) { + result = block()->dominator_depth(); + } + assert(result != -1 || this->as_Local(), "Only locals have dominator depth -1"); + return result; + } + Instruction::Condition Instruction::mirror(Condition cond) { switch (cond) { case eql: return eql; case neq: return neq; case lss: return gtr; case leq: return geq; case gtr: return lss; case geq: return leq; + case aeq: return beq; + case beq: return aeq; } ShouldNotReachHere(); return eql; }
*** 54,63 **** --- 65,76 ---- case neq: return eql; case lss: return geq; case leq: return gtr; case gtr: return leq; case geq: return lss; + case aeq: assert(false, "Above equal cannot be negated"); + case beq: assert(false, "Below equal cannot be negated"); } ShouldNotReachHere(); return eql; }
*** 68,81 **** } else { _exception_state = NULL; } } ! ! Instruction* Instruction::prev(BlockBegin* block) { Instruction* p = NULL; ! Instruction* q = block; while (q != this) { assert(q != NULL, "this is not in the block's instruction list"); p = q; q = q->next(); } return p; --- 81,94 ---- } else { _exception_state = NULL; } } ! // Prev without need to have BlockBegin ! Instruction* Instruction::prev() { Instruction* p = NULL; ! Instruction* q = block(); while (q != this) { assert(q != NULL, "this is not in the block's instruction list"); p = q; q = q->next(); } return p;
*** 120,138 **** --- 133,160 ---- #endif // PRODUCT // perform constant and interval tests on index value bool AccessIndexed::compute_needs_range_check() { + + if (length()) { + Constant* clength = length()->as_Constant(); Constant* cindex = index()->as_Constant(); if (clength && cindex) { IntConstant* l = clength->type()->as_IntConstant(); IntConstant* i = cindex->type()->as_IntConstant(); if (l && i && i->value() < l->value() && i->value() >= 0) { return false; } } + } + + if (!this->check_flag(NeedsRangeCheckFlag)) { + return false; + } + return true; } ciType* Local::exact_type() const {
*** 629,651 **** // In general it is not possible to calculate a value for the field "depth_first_number" // of the inserted block, without recomputing the values of the other blocks // in the CFG. Therefore the value of "depth_first_number" in BlockBegin becomes meaningless. BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) { ! BlockBegin* new_sux = new BlockBegin(end()->state()->bci()); // mark this block (special treatment when block order is computed) new_sux->set(critical_edge_split_flag); // This goto is not a safepoint. Goto* e = new Goto(sux, false); ! new_sux->set_next(e, end()->state()->bci()); new_sux->set_end(e); // setup states ValueStack* s = end()->state(); ! new_sux->set_state(s->copy()); ! e->set_state(s->copy()); assert(new_sux->state()->locals_size() == s->locals_size(), "local size mismatch!"); assert(new_sux->state()->stack_size() == s->stack_size(), "stack size mismatch!"); assert(new_sux->state()->locks_size() == s->locks_size(), "locks size mismatch!"); // link predecessor to new block --- 651,679 ---- // In general it is not possible to calculate a value for the field "depth_first_number" // of the inserted block, without recomputing the values of the other blocks // in the CFG. Therefore the value of "depth_first_number" in BlockBegin becomes meaningless. BlockBegin* BlockBegin::insert_block_between(BlockBegin* sux) { ! int bci = sux->bci(); ! // critical edge splitting may introduce a goto after a if and array ! // bound check elimination may insert a predicate between the if and ! // goto. The bci of the goto can't be the one of the if otherwise ! // the state and bci are inconsistent and a deoptimization triggered ! // by the predicate would lead to incorrect execution/a crash. ! BlockBegin* new_sux = new BlockBegin(bci); // mark this block (special treatment when block order is computed) new_sux->set(critical_edge_split_flag); // This goto is not a safepoint. Goto* e = new Goto(sux, false); ! new_sux->set_next(e, bci); new_sux->set_end(e); // setup states ValueStack* s = end()->state(); ! new_sux->set_state(s->copy(s->kind(), bci)); ! e->set_state(s->copy(s->kind(), bci)); assert(new_sux->state()->locals_size() == s->locals_size(), "local size mismatch!"); assert(new_sux->state()->stack_size() == s->stack_size(), "stack size mismatch!"); assert(new_sux->state()->locks_size() == s->locks_size(), "locks size mismatch!"); // link predecessor to new block
*** 958,976 **** void BlockEnd::set_begin(BlockBegin* begin) { BlockList* sux = NULL; if (begin != NULL) { sux = begin->successors(); ! } else if (_begin != NULL) { // copy our sux list ! BlockList* sux = new BlockList(_begin->number_of_sux()); ! for (int i = 0; i < _begin->number_of_sux(); i++) { ! sux->append(_begin->sux_at(i)); } } _sux = sux; - _begin = begin; } void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) { substitute(*_sux, old_sux, new_sux); --- 986,1003 ---- void BlockEnd::set_begin(BlockBegin* begin) { BlockList* sux = NULL; if (begin != NULL) { sux = begin->successors(); ! } else if (this->begin() != NULL) { // copy our sux list ! BlockList* sux = new BlockList(this->begin()->number_of_sux()); ! for (int i = 0; i < this->begin()->number_of_sux(); i++) { ! sux->append(this->begin()->sux_at(i)); } } _sux = sux; } void BlockEnd::substitute_sux(BlockBegin* old_sux, BlockBegin* new_sux) { substitute(*_sux, old_sux, new_sux);
*** 1006,1015 **** --- 1033,1073 ---- } else { return _block->number_of_preds(); } } + #ifndef PRODUCT + // Constructor of Assert + Assert::Assert(Value x, Condition cond, bool unordered_is_true, Value y) : Instruction(illegalType) + , _x(x) + , _cond(cond) + , _y(y) + { + set_flag(UnorderedIsTrueFlag, unordered_is_true); + assert(x->type()->tag() == y->type()->tag(), "types must match"); + pin(); + + stringStream strStream; + Compilation::current()->method()->print_name(&strStream); + + stringStream strStream1; + InstructionPrinter ip1(1, &strStream1); + ip1.print_instr(x); + + stringStream strStream2; + InstructionPrinter ip2(1, &strStream2); + ip2.print_instr(y); + + _message = new char[1024]; + snprintf(_message, 1024, "Assertion %s %s %s in method %s", strStream1.as_string(), ip2.cond_name(cond), strStream2.as_string(), strStream.as_string()); + } + + #endif + + void RangeCheckPredicate::check_state() { + assert(state()->kind() != ValueStack::EmptyExceptionState && state()->kind() != ValueStack::ExceptionState, "will deopt with empty state"); + } void ProfileInvoke::state_values_do(ValueVisitor* f) { if (state() != NULL) state()->values_do(f); }