diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index b0ed29d856730..47f7974e03d50 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -310,7 +310,7 @@ IdealLoopTree* PhaseIdealLoop::insert_outer_loop(IdealLoopTree* loop, LoopNode* // clone the outer loop as well as the inner, unrolling needs to only // clone the inner loop etc. No optimizations need to change the outer // strip mined loop as it is only a skeleton. -IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, +IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(Node* init_control, IdealLoopTree* loop, float cl_prob, float le_fcnt, Node*& entry_control, Node*& iffalse) { Node* outer_test = intcon(0); @@ -342,17 +342,19 @@ IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(BoolNode *test, Nod return outer_ilt; } -void PhaseIdealLoop::insert_loop_limit_check_predicate(ParsePredicateSuccessProj* loop_limit_check_parse_proj, +void CountedLoopConverter::insert_loop_limit_check_predicate(const ParsePredicateSuccessProj* loop_limit_check_parse_proj, Node* cmp_limit, Node* bol) { assert(loop_limit_check_parse_proj->in(0)->is_ParsePredicate(), "must be parse predicate"); - Node* new_predicate_proj = create_new_if_for_predicate(loop_limit_check_parse_proj, nullptr, - Deoptimization::Reason_loop_limit_check, - Op_If); + Node* new_predicate_proj = _phase->create_new_if_for_predicate(loop_limit_check_parse_proj, nullptr, + Deoptimization::Reason_loop_limit_check, + Op_If); + + PhaseIterGVN& igvn = _phase->igvn(); Node* iff = new_predicate_proj->in(0); - cmp_limit = _igvn.register_new_node_with_optimizer(cmp_limit); - bol = _igvn.register_new_node_with_optimizer(bol); - set_subtree_ctrl(bol, false); - _igvn.replace_input_of(iff, 1, bol); + cmp_limit = igvn.register_new_node_with_optimizer(cmp_limit); + bol = igvn.register_new_node_with_optimizer(bol); + _phase->set_subtree_ctrl(bol, false); + igvn.replace_input_of(iff, 1, bol); #ifndef PRODUCT // report that the loop predication has been actually performed @@ -364,14 +366,14 @@ void PhaseIdealLoop::insert_loop_limit_check_predicate(ParsePredicateSuccessProj #endif } -Node* PhaseIdealLoop::loop_exit_control(Node* x, IdealLoopTree* loop) { +Node* PhaseIdealLoop::loop_exit_control(const Node* head, const IdealLoopTree* loop) const { // Counted loop head must be a good RegionNode with only 3 not null // control input edges: Self, Entry, LoopBack. - if (x->in(LoopNode::Self) == nullptr || x->req() != 3 || loop->_irreducible) { + if (head->in(LoopNode::Self) == nullptr || head->req() != 3 || loop->_irreducible) { return nullptr; } - Node *init_control = x->in(LoopNode::EntryControl); - Node *back_control = x->in(LoopNode::LoopBackControl); + Node* init_control = head->in(LoopNode::EntryControl); + Node* back_control = head->in(LoopNode::LoopBackControl); if (init_control == nullptr || back_control == nullptr) { // Partially dead return nullptr; } @@ -404,77 +406,71 @@ Node* PhaseIdealLoop::loop_exit_control(Node* x, IdealLoopTree* loop) { return iftrue; } -Node* PhaseIdealLoop::loop_exit_test(Node* back_control, IdealLoopTree* loop, Node*& incr, Node*& limit, BoolTest::mask& bt, float& cl_prob) { - Node* iftrue = back_control; +PhaseIdealLoop::LoopExitTest PhaseIdealLoop::loop_exit_test(const Node* back_control, const IdealLoopTree* loop) { + const Node* iftrue = back_control; uint iftrue_op = iftrue->Opcode(); Node* iff = iftrue->in(0); BoolNode* test = iff->in(1)->as_Bool(); - bt = test->_test._test; - cl_prob = iff->as_If()->_prob; + BoolTest::mask bt = test->_test._test; + float cl_prob = iff->as_If()->_prob; if (iftrue_op == Op_IfFalse) { bt = BoolTest(bt).negate(); - cl_prob = 1.0 - cl_prob; + cl_prob = 1.0f - cl_prob; } // Get backedge compare Node* cmp = test->in(1); if (!cmp->is_Cmp()) { - return nullptr; + return {}; } // Find the trip-counter increment & limit. Limit must be loop invariant. - incr = cmp->in(1); - limit = cmp->in(2); + Node* incr = cmp->in(1); + Node* limit = cmp->in(2); // --------- // need 'loop()' test to tell if limit is loop invariant // --------- if (!is_member(loop, get_ctrl(incr))) { // Swapped trip counter and limit? - Node* tmp = incr; // Then reverse order into the CmpI - incr = limit; - limit = tmp; + swap(incr, limit); // Then reverse order into the CmpI bt = BoolTest(bt).commute(); // And commute the exit test } if (is_member(loop, get_ctrl(limit))) { // Limit must be loop-invariant - return nullptr; + return {}; } if (!is_member(loop, get_ctrl(incr))) { // Trip counter must be loop-variant - return nullptr; + return {}; } - return cmp; + return {cmp->as_Cmp(), incr, limit, bt, cl_prob}; } -Node* PhaseIdealLoop::loop_iv_incr(Node* incr, Node* x, IdealLoopTree* loop, Node*& phi_incr) { - if (incr->is_Phi()) { - if (incr->as_Phi()->region() != x || incr->req() != 3) { - return nullptr; // Not simple trip counter expression - } - phi_incr = incr; - incr = phi_incr->in(LoopNode::LoopBackControl); // Assume incr is on backedge of Phi - if (!is_member(loop, get_ctrl(incr))) { // Trip counter must be loop-variant - return nullptr; +PhaseIdealLoop::LoopIVIncr PhaseIdealLoop::loop_iv_incr(Node* incr, const Node* head, const IdealLoopTree* loop) { + if (incr->is_Phi() && incr->as_Phi()->region() == head && incr->req() == 3) { // Requires simple trip counter expression + Node* phi_incr = incr; + Node* back_control = phi_incr->in(LoopNode::LoopBackControl); // Assume incr is on backedge of Phi + if (loop->_phase->is_member(loop, loop->_phase->get_ctrl(back_control))) { // Trip counter must be loop-variant + return {back_control, phi_incr}; } } - return incr; + return {incr, nullptr}; } -Node* PhaseIdealLoop::loop_iv_stride(Node* incr, IdealLoopTree* loop, Node*& xphi) { +PhaseIdealLoop::LoopIvStride PhaseIdealLoop::loop_iv_stride(const Node* incr) { assert(incr->Opcode() == Op_AddI || incr->Opcode() == Op_AddL, "caller resp."); // Get merge point - xphi = incr->in(1); + Node* xphi = incr->in(1); Node *stride = incr->in(2); if (!stride->is_Con()) { // Oops, swap these if (!xphi->is_Con()) { // Is the other guy a constant? - return nullptr; // Nope, unknown stride, bail out + return {}; // Nope, unknown stride, bail out } - Node *tmp = xphi; // 'incr' is commutative, so ok to swap - xphi = stride; - stride = tmp; + + swap(xphi, stride); // 'incr' is commutative, so ok to swap } - return stride; + return {stride, xphi}; } -PhiNode* PhaseIdealLoop::loop_iv_phi(Node* xphi, Node* phi_incr, Node* x, IdealLoopTree* loop) { +PhiNode* PhaseIdealLoop::loop_iv_phi(const Node* xphi, const Node* phi_incr, const Node* head) { if (!xphi->is_Phi()) { return nullptr; // Too much math on the trip counter } @@ -484,7 +480,7 @@ PhiNode* PhaseIdealLoop::loop_iv_phi(Node* xphi, Node* phi_incr, Node* x, IdealL PhiNode *phi = xphi->as_Phi(); // Phi must be of loop header; backedge must wrap to increment - if (phi->region() != x) { + if (phi->region() != head) { return nullptr; } return phi; @@ -615,10 +611,10 @@ void PhaseIdealLoop::add_parse_predicate(Deoptimization::DeoptReason reason, Nod // Find a safepoint node that dominates the back edge. We need a // SafePointNode so we can use its jvm state to create empty // predicates. -static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, MergeMemNode* mm, PhaseIdealLoop* phase) { +static bool no_side_effect_since_safepoint(Compile* C, const Node* head, const Node* mem, MergeMemNode* mm, const PhaseIdealLoop* phase) { SafePointNode* safepoint = nullptr; - for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) { - Node* u = x->fast_out(i); + for (DUIterator_Fast imax, i = head->fast_outs(imax); i < imax; i++) { + Node* u = head->fast_out(i); if (u->is_memory_phi()) { Node* m = u->in(LoopNode::LoopBackControl); if (u->adr_type() == TypePtr::BOTTOM) { @@ -668,14 +664,14 @@ static bool no_side_effect_since_safepoint(Compile* C, Node* x, Node* mem, Merge return true; } -SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, IdealLoopTree* loop) { +SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, const Node* head, const IdealLoopTree* loop) { IfNode* exit_test = back_control->in(0)->as_If(); SafePointNode* safepoint = nullptr; if (exit_test->in(0)->is_SafePoint() && exit_test->in(0)->outcnt() == 1) { safepoint = exit_test->in(0)->as_SafePoint(); } else { Node* c = back_control; - while (c != x && c->Opcode() != Op_SafePoint) { + while (c != head && c->Opcode() != Op_SafePoint) { c = idom(c); } @@ -714,7 +710,7 @@ SafePointNode* PhaseIdealLoop::find_safepoint(Node* back_control, Node* x, Ideal } } #endif - if (!no_side_effect_since_safepoint(C, x, mem, mm, this)) { + if (!no_side_effect_since_safepoint(C, head, mem, mm, this)) { safepoint = nullptr; } else { assert(mm == nullptr|| _igvn.transform(mm) == mem->as_MergeMem()->base_memory(), "all memory state should have been processed"); @@ -1468,47 +1464,49 @@ void PhaseIdealLoop::check_counted_loop_shape(IdealLoopTree* loop, Node* x, Basi Node* back_control = loop_exit_control(x, loop); assert(back_control != nullptr, "no back control"); - BoolTest::mask mask = BoolTest::illegal; - float cl_prob = 0; - Node* incr = nullptr; - Node* limit = nullptr; - - Node* cmp = loop_exit_test(back_control, loop, incr, limit, mask, cl_prob); - assert(cmp != nullptr && cmp->Opcode() == Op_Cmp(bt), "no exit test"); + LoopExitTest exit_test = loop_exit_test(back_control, loop); + assert(exit_test.cmp != nullptr && exit_test.cmp->Opcode() == Op_Cmp(bt), "no exit test"); - Node* phi_incr = nullptr; - incr = loop_iv_incr(incr, x, loop, phi_incr); - assert(incr != nullptr && incr->Opcode() == Op_Add(bt), "no incr"); + const LoopIVIncr iv_incr = loop_iv_incr(exit_test.incr, x, loop); + assert(iv_incr.incr != nullptr && iv_incr.incr->Opcode() == Op_Add(bt), "no incr"); - Node* xphi = nullptr; - Node* stride = loop_iv_stride(incr, loop, xphi); + LoopIvStride stride = loop_iv_stride(iv_incr.incr); + assert(stride.stride != nullptr, "no stride"); - assert(stride != nullptr, "no stride"); + PhiNode* phi = loop_iv_phi(stride.xphi, iv_incr.phi_incr, x); + assert(phi != nullptr && phi->in(LoopNode::LoopBackControl) == iv_incr.incr, "No phi"); - PhiNode* phi = loop_iv_phi(xphi, phi_incr, x, loop); + jlong stride_con = stride.stride->get_integer_as_long(bt); + assert(condition_stride_ok(exit_test.mask, stride_con), "illegal condition"); - assert(phi != nullptr && phi->in(LoopNode::LoopBackControl) == incr, "No phi"); - - jlong stride_con = stride->get_integer_as_long(bt); - - assert(condition_stride_ok(mask, stride_con), "illegal condition"); - - assert(mask != BoolTest::ne, "unexpected condition"); - assert(phi_incr == nullptr, "bad loop shape"); - assert(cmp->in(1) == incr, "bad exit test shape"); + assert(exit_test.mask != BoolTest::ne, "unexpected condition"); + assert(iv_incr.phi_incr == nullptr, "bad loop shape"); + assert(exit_test.cmp->in(1) == iv_incr.incr, "bad exit test shape"); // Safepoint on backedge not supported assert(x->in(LoopNode::LoopBackControl)->Opcode() != Op_SafePoint, "no safepoint on backedge"); } #endif +//------------------------------CountedLoopConverter-------------------------------- #ifdef ASSERT -// convert an int counted loop to a long counted to stress handling of -// long counted loops -bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* loop) { +bool CountedLoopConverter::should_stress_long_counted_loop() const { + assert(_checked_for_counted_loop, "must check for counted loop before stressing"); + + return StressLongCountedLoop > 0 && + _iv_bt == T_INT && + !_head->as_Loop()->is_loop_nest_inner_loop() && + _increment_truncation_type == TypeInt::INT; // Only stress an int loop (i.e., not char, byte or short) +} + +// Convert an int counted loop to a long counted to stress handling of long counted loops. Returns true upon success. +bool CountedLoopConverter::stress_long_counted_loop() const { + assert(should_stress_long_counted_loop(), "stress condition not satisfied"); + + PhaseIterGVN* igvn = &_phase->igvn(); Unique_Node_List iv_nodes; Node_List old_new; - iv_nodes.push(cmp); + iv_nodes.push(_cmp); bool failed = false; for (uint i = 0; i < iv_nodes.size() && !failed; i++) { @@ -1538,12 +1536,12 @@ bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* l fatal("unexpected"); } - for (uint i = 1; i < n->req(); i++) { - Node* in = n->in(i); + for (uint j = 1; j < n->req(); j++) { + Node* in = n->in(j); if (in == nullptr) { continue; } - if (loop->is_member(get_loop(get_ctrl(in)))) { + if (_loop->is_member(_phase->get_loop(_phase->get_ctrl(in)))) { iv_nodes.push(in); } } @@ -1554,7 +1552,7 @@ bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* l Node* n = iv_nodes.at(i); Node* clone = old_new[n->_idx]; if (clone != nullptr) { - _igvn.remove_dead_node(clone); + igvn->remove_dead_node(clone); } } return false; @@ -1563,122 +1561,131 @@ bool PhaseIdealLoop::convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* l for (uint i = 0; i < iv_nodes.size(); i++) { Node* n = iv_nodes.at(i); Node* clone = old_new[n->_idx]; - for (uint i = 1; i < n->req(); i++) { - Node* in = n->in(i); + for (uint j = 1; j < n->req(); j++) { + Node* in = n->in(j); if (in == nullptr) { continue; } Node* in_clone = old_new[in->_idx]; if (in_clone == nullptr) { - assert(_igvn.type(in)->isa_int(), ""); + assert(igvn->type(in)->isa_int(), ""); in_clone = new ConvI2LNode(in); - _igvn.register_new_node_with_optimizer(in_clone); - set_subtree_ctrl(in_clone, false); + igvn->register_new_node_with_optimizer(in_clone); + _phase->set_subtree_ctrl(in_clone, false); } if (in_clone->in(0) == nullptr) { - in_clone->set_req(0, C->top()); - clone->set_req(i, in_clone); + in_clone->set_req(0, _phase->C->top()); + clone->set_req(j, in_clone); in_clone->set_req(0, nullptr); } else { - clone->set_req(i, in_clone); + clone->set_req(j, in_clone); } } - _igvn.register_new_node_with_optimizer(clone); + igvn->register_new_node_with_optimizer(clone); } - set_ctrl(old_new[phi->_idx], phi->in(0)); + _phase->set_ctrl(old_new[_phi->_idx], _phi->in(0)); for (uint i = 0; i < iv_nodes.size(); i++) { Node* n = iv_nodes.at(i); Node* clone = old_new[n->_idx]; - set_subtree_ctrl(clone, false); + _phase->set_subtree_ctrl(clone, false); Node* m = n->Opcode() == Op_CmpI ? clone : nullptr; - for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { - Node* u = n->fast_out(i); + for (DUIterator_Fast imax, j = n->fast_outs(imax); j < imax; j++) { + Node* u = n->fast_out(j); if (iv_nodes.member(u)) { continue; } if (m == nullptr) { m = new ConvL2INode(clone); - _igvn.register_new_node_with_optimizer(m); - set_subtree_ctrl(m, false); + igvn->register_new_node_with_optimizer(m); + _phase->set_subtree_ctrl(m, false); } - _igvn.rehash_node_delayed(u); - int nb = u->replace_edge(n, m, &_igvn); - --i, imax -= nb; + igvn->rehash_node_delayed(u); + int nb = u->replace_edge(n, m, igvn); + --j, imax -= nb; } } return true; } #endif -//------------------------------is_counted_loop-------------------------------- -bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_bt) { - PhaseGVN *gvn = &_igvn; +bool PhaseIdealLoop::try_convert_to_counted_loop(Node* head, IdealLoopTree*& loop, const BasicType iv_bt) { + CountedLoopConverter converter(this, head, loop, iv_bt); + if (converter.is_counted_loop()) { +#ifdef ASSERT + // Stress by converting int counted loops to long counted loops + if (converter.should_stress_long_counted_loop() && converter.stress_long_counted_loop()) { + return false; + } +#endif + + loop = converter.convert(); + return true; + } - Node* back_control = loop_exit_control(x, loop); + return false; +} + +bool CountedLoopConverter::is_counted_loop() { + PhaseIterGVN* igvn = &_phase->igvn(); + + Node* back_control = _phase->loop_exit_control(_head, _loop); if (back_control == nullptr) { return false; } - BoolTest::mask bt = BoolTest::illegal; - float cl_prob = 0; - Node* incr = nullptr; - Node* limit = nullptr; - Node* cmp = loop_exit_test(back_control, loop, incr, limit, bt, cl_prob); - if (cmp == nullptr || cmp->Opcode() != Op_Cmp(iv_bt)) { + PhaseIdealLoop::LoopExitTest exit_test = _phase->loop_exit_test(back_control, _loop); + if (exit_test.cmp == nullptr || exit_test.cmp->Opcode() != Op_Cmp(_iv_bt)) { return false; // Avoid pointer & float & 64-bit compares } // Trip-counter increment must be commutative & associative. - if (incr->Opcode() == Op_Cast(iv_bt)) { + Node* incr = exit_test.incr; + if (exit_test.incr->Opcode() == Op_Cast(_iv_bt)) { incr = incr->in(1); } - Node* phi_incr = nullptr; - incr = loop_iv_incr(incr, x, loop, phi_incr); - if (incr == nullptr) { + const PhaseIdealLoop::LoopIVIncr iv_incr = PhaseIdealLoop::loop_iv_incr(incr, _head, _loop); + if (iv_incr.incr == nullptr) { return false; } - Node* trunc1 = nullptr; - Node* trunc2 = nullptr; - const TypeInteger* iv_trunc_t = nullptr; - Node* orig_incr = incr; - if (!(incr = CountedLoopNode::match_incr_with_optional_truncation(incr, &trunc1, &trunc2, &iv_trunc_t, iv_bt))) { + CountedLoopNode::TruncatedIncrement increment = CountedLoopNode::match_incr_with_optional_truncation(iv_incr.incr, _iv_bt); + if (increment.incr == nullptr) { return false; // Funny increment opcode } - assert(incr->Opcode() == Op_Add(iv_bt), "wrong increment code"); - Node* xphi = nullptr; - Node* stride = loop_iv_stride(incr, loop, xphi); + assert(increment.incr->Opcode() == Op_Add(_iv_bt), "wrong increment code"); - if (stride == nullptr) { + const PhaseIdealLoop::LoopIvStride stride = PhaseIdealLoop::loop_iv_stride(increment.incr); + if (stride.stride == nullptr) { return false; } - if (xphi->Opcode() == Op_Cast(iv_bt)) { + Node* xphi = stride.xphi; + if (xphi->Opcode() == Op_Cast(_iv_bt)) { xphi = xphi->in(1); } // Stride must be constant - jlong stride_con = stride->get_integer_as_long(iv_bt); + jlong stride_con = stride.stride->get_integer_as_long(_iv_bt); assert(stride_con != 0, "missed some peephole opt"); - PhiNode* phi = loop_iv_phi(xphi, phi_incr, x, loop); + PhiNode* phi = PhaseIdealLoop::loop_iv_phi(xphi, iv_incr.phi_incr, _head); if (phi == nullptr || - (trunc1 == nullptr && phi->in(LoopNode::LoopBackControl) != incr) || - (trunc1 != nullptr && phi->in(LoopNode::LoopBackControl) != trunc1)) { + (increment.trunc1 == nullptr && phi->in(LoopNode::LoopBackControl) != increment.incr) || + (increment.trunc1 != nullptr && phi->in(LoopNode::LoopBackControl) != increment.trunc1)) { return false; } - Node* iftrue = back_control; + const Node* iftrue = back_control; uint iftrue_op = iftrue->Opcode(); Node* iff = iftrue->in(0); BoolNode* test = iff->in(1)->as_Bool(); - const TypeInteger* limit_t = gvn->type(limit)->is_integer(iv_bt); - if (trunc1 != nullptr) { + const TypeInteger* limit_t = igvn->type(exit_test.limit)->is_integer(_iv_bt); + if (increment.trunc1 != nullptr) { // When there is a truncation, we must be sure that after the truncation // the trip counter will end up higher than the limit, otherwise we are looking // at an endless loop. Can happen with range checks. @@ -1696,18 +1703,18 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // If the array is longer then this is an endless loop // - No transformation can be done. - const TypeInteger* incr_t = gvn->type(orig_incr)->is_integer(iv_bt); + const TypeInteger* incr_t = igvn->type(iv_incr.incr)->is_integer(_iv_bt); if (limit_t->hi_as_long() > incr_t->hi_as_long()) { - // if the limit can have a higher value than the increment (before the phi) + // if the limit can have a higher value than the increment (before the0 phi) return false; } } - Node *init_trip = phi->in(LoopNode::EntryControl); + Node* init_trip = phi->in(LoopNode::EntryControl); // If iv trunc type is smaller than int, check for possible wrap. - if (!TypeInteger::bottom(iv_bt)->higher_equal(iv_trunc_t)) { - assert(trunc1 != nullptr, "must have found some truncation"); + if (!TypeInteger::bottom(_iv_bt)->higher_equal(increment.trunc_type)) { + assert(increment.trunc1 != nullptr, "must have found some truncation"); // Get a better type for the phi (filtered thru if's) const TypeInteger* phi_ft = filtered_type(phi); @@ -1724,46 +1731,45 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // ensure no truncation occurs after the increment. if (stride_con > 0) { - if (iv_trunc_t->hi_as_long() - phi_ft->hi_as_long() < stride_con || - iv_trunc_t->lo_as_long() > phi_ft->lo_as_long()) { + if (increment.trunc_type->hi_as_long() - phi_ft->hi_as_long() < stride_con || + increment.trunc_type->lo_as_long() > phi_ft->lo_as_long()) { return false; // truncation may occur } } else if (stride_con < 0) { - if (iv_trunc_t->lo_as_long() - phi_ft->lo_as_long() > stride_con || - iv_trunc_t->hi_as_long() < phi_ft->hi_as_long()) { + if (increment.trunc_type->lo_as_long() - phi_ft->lo_as_long() > stride_con || + increment.trunc_type->hi_as_long() < phi_ft->hi_as_long()) { return false; // truncation may occur } } // No possibility of wrap so truncation can be discarded // Promote iv type to Int } else { - assert(trunc1 == nullptr && trunc2 == nullptr, "no truncation for int"); + assert(increment.trunc1 == nullptr && increment.trunc2 == nullptr, "no truncation for int"); } - if (!condition_stride_ok(bt, stride_con)) { + if (!condition_stride_ok(exit_test.mask, stride_con)) { return false; } - const TypeInteger* init_t = gvn->type(init_trip)->is_integer(iv_bt); - + const TypeInteger* init_t = igvn->type(init_trip)->is_integer(_iv_bt); if (stride_con > 0) { - if (init_t->lo_as_long() > max_signed_integer(iv_bt) - stride_con) { + if (init_t->lo_as_long() > max_signed_integer(_iv_bt) - stride_con) { return false; // cyclic loop } } else { - if (init_t->hi_as_long() < min_signed_integer(iv_bt) - stride_con) { + if (init_t->hi_as_long() < min_signed_integer(_iv_bt) - stride_con) { return false; // cyclic loop } } - if (phi_incr != nullptr && bt != BoolTest::ne) { + if (iv_incr.phi_incr != nullptr && exit_test.mask != BoolTest::ne) { // check if there is a possibility of IV overflowing after the first increment if (stride_con > 0) { - if (init_t->hi_as_long() > max_signed_integer(iv_bt) - stride_con) { + if (init_t->hi_as_long() > max_signed_integer(_iv_bt) - stride_con) { return false; } } else { - if (init_t->lo_as_long() < min_signed_integer(iv_bt) - stride_con) { + if (init_t->lo_as_long() < min_signed_integer(_iv_bt) - stride_con) { return false; } } @@ -1773,22 +1779,22 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // ---- SUCCESS! Found A Trip-Counted Loop! ----- // - if (x->Opcode() == Op_Region) { - // x has not yet been transformed to Loop or LongCountedLoop. + if (_head->Opcode() == Op_Region) { + // head has not yet been transformed to Loop or LongCountedLoop. // This should only happen if we are inside an infinite loop. // It happens like this: // build_loop_tree -> do not attach infinite loop and nested loops // beautify_loops -> does not transform the infinite and nested loops to LoopNode, because not attached yet // build_loop_tree -> find and attach infinite and nested loops // counted_loop -> nested Regions are not yet transformed to LoopNodes, we land here - assert(x->as_Region()->is_in_infinite_subgraph(), - "x can only be a Region and not Loop if inside infinite loop"); + assert(_head->as_Region()->is_in_infinite_subgraph(), + "head can only be a Region and not Loop if inside infinite loop"); // Come back later when Region is transformed to LoopNode return false; } - assert(x->Opcode() == Op_Loop || x->Opcode() == Op_LongCountedLoop, "regular loops only"); - C->print_method(PHASE_BEFORE_CLOOPS, 3, x); + assert(_head->Opcode() == Op_Loop || _head->Opcode() == Op_LongCountedLoop, "regular loops only"); + _phase->C->print_method(PHASE_BEFORE_CLOOPS, 3, _head); // =================================================== // We can only convert this loop to a counted loop if we can guarantee that the iv phi will never overflow at runtime. @@ -1978,77 +1984,75 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // again and can skip the predicate. // Check (vi) and bail out if the stride is too big. - if (stride_con == min_signed_integer(iv_bt) || (ABS(stride_con) > max_signed_integer(iv_bt) / 2)) { + if (stride_con == min_signed_integer(_iv_bt) || (ABS(stride_con) > max_signed_integer(_iv_bt) / 2)) { return false; } // Accounting for (LE3) and (LE4) where we use pre-incremented phis in the loop exit check. - const jlong limit_correction_for_pre_iv_exit_check = (phi_incr != nullptr) ? stride_con : 0; + const jlong limit_correction_for_pre_iv_exit_check = (iv_incr.phi_incr != nullptr) ? stride_con : 0; // Accounting for (LE2) and (LE4) where we use <= or >= in the loop exit check. - const bool includes_limit = (bt == BoolTest::le || bt == BoolTest::ge); + const bool includes_limit = (exit_test.mask == BoolTest::le || exit_test.mask == BoolTest::ge); const jlong limit_correction_for_le_ge_exit_check = (includes_limit ? (stride_con > 0 ? 1 : -1) : 0); const jlong limit_correction = limit_correction_for_pre_iv_exit_check + limit_correction_for_le_ge_exit_check; const jlong canonicalized_correction = stride_con + (stride_con > 0 ? -1 : 1); const jlong final_correction = canonicalized_correction + limit_correction; - int sov = check_stride_overflow(final_correction, limit_t, iv_bt); - Node* init_control = x->in(LoopNode::EntryControl); + int sov = check_stride_overflow(final_correction, limit_t, _iv_bt); + Node* init_control = _head->in(LoopNode::EntryControl); + + const Predicates predicates(init_control); + const PredicateBlock* loop_limit_check_predicate_block = predicates.loop_limit_check_predicate_block(); + + if (sov < 0) { + return false; // Bailout: integer overflow is certain. + } - // If sov==0, limit's type always satisfies the condition, for + // If sov == 0, limit's type always satisfies the condition, for // example, when it is an array length. - if (sov != 0) { - if (sov < 0) { - return false; // Bailout: integer overflow is certain. - } + + bool insert_stride_overflow_limit_check = false; + if (sov > 0) { // (1) Loop Limit Check Predicate is required because we could not statically prove that // limit + final_correction = adjusted_limit - 1 + stride <= max_int - assert(!x->as_Loop()->is_loop_nest_inner_loop(), "loop was transformed"); - const Predicates predicates(init_control); - const PredicateBlock* loop_limit_check_predicate_block = predicates.loop_limit_check_predicate_block(); + assert(!_head->as_Loop()->is_loop_nest_inner_loop(), "loop was transformed"); if (!loop_limit_check_predicate_block->has_parse_predicate()) { // The Loop Limit Check Parse Predicate is not generated if this method trapped here before. #ifdef ASSERT if (TraceLoopLimitCheck) { tty->print("Missing Loop Limit Check Parse Predicate:"); - loop->dump_head(); - x->dump(1); + _loop->dump_head(); + _head->dump(1); } #endif return false; } ParsePredicateNode* loop_limit_check_parse_predicate = loop_limit_check_predicate_block->parse_predicate(); - if (!is_dominator(get_ctrl(limit), loop_limit_check_parse_predicate->in(0))) { + if (!_phase->is_dominator(_phase->get_ctrl(exit_test.limit), loop_limit_check_parse_predicate->in(0))) { return false; } - Node* cmp_limit; - Node* bol; - - if (stride_con > 0) { - cmp_limit = CmpNode::make(limit, _igvn.integercon(max_signed_integer(iv_bt) - final_correction, iv_bt), iv_bt); - bol = new BoolNode(cmp_limit, BoolTest::le); - } else { - cmp_limit = CmpNode::make(limit, _igvn.integercon(min_signed_integer(iv_bt) - final_correction, iv_bt), iv_bt); - bol = new BoolNode(cmp_limit, BoolTest::ge); - } - - insert_loop_limit_check_predicate(init_control->as_IfTrue(), cmp_limit, bol); + insert_stride_overflow_limit_check = true; } // (2.3) const bool init_plus_stride_could_overflow = - (stride_con > 0 && init_t->hi_as_long() > max_signed_integer(iv_bt) - stride_con) || - (stride_con < 0 && init_t->lo_as_long() < min_signed_integer(iv_bt) - stride_con); + (stride_con > 0 && init_t->hi_as_long() > max_signed_integer(_iv_bt) - stride_con) || + (stride_con < 0 && init_t->lo_as_long() < min_signed_integer(_iv_bt) - stride_con); // (2.1) const bool init_gte_limit = (stride_con > 0 && init_t->hi_as_long() >= limit_t->lo_as_long()) || - (stride_con < 0 && init_t->lo_as_long() <= limit_t->hi_as_long()); + (stride_con < 0 && init_t->lo_as_long() <= limit_t->hi_as_long()); + bool insert_init_trip_limit_check = false; if (init_gte_limit && // (2.1) - ((bt == BoolTest::ne || init_plus_stride_could_overflow) && // (2.3) - !has_dominating_loop_limit_check(init_trip, limit, stride_con, iv_bt, init_control))) { // (2.2) + ((exit_test.mask == BoolTest::ne || init_plus_stride_could_overflow) && // (2.3) + !has_dominating_loop_limit_check(init_trip, + exit_test.limit, + stride_con, + _iv_bt, + init_control))) { // (2.2) // (2) Iteration Loop Limit Check Predicate is required because neither (2.1), (2.2), nor (2.3) holds. // We use the following condition: // - stride > 0: init < limit @@ -2058,15 +2062,13 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // a requirement). We transform the loop exit check by using a less-than-operator. By doing so, we must always // check that init < limit. Otherwise, we could have a different number of iterations at runtime. - const Predicates predicates(init_control); - const PredicateBlock* loop_limit_check_predicate_block = predicates.loop_limit_check_predicate_block(); if (!loop_limit_check_predicate_block->has_parse_predicate()) { // The Loop Limit Check Parse Predicate is not generated if this method trapped here before. #ifdef ASSERT if (TraceLoopLimitCheck) { tty->print("Missing Loop Limit Check Parse Predicate:"); - loop->dump_head(); - x->dump(1); + _loop->dump_head(); + _head->dump(1); } #endif return false; @@ -2074,41 +2076,31 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ ParsePredicateNode* loop_limit_check_parse_predicate = loop_limit_check_predicate_block->parse_predicate(); Node* parse_predicate_entry = loop_limit_check_parse_predicate->in(0); - if (!is_dominator(get_ctrl(limit), parse_predicate_entry) || - !is_dominator(get_ctrl(init_trip), parse_predicate_entry)) { + if (!_phase->is_dominator(_phase->get_ctrl(exit_test.limit), parse_predicate_entry) || + !_phase->is_dominator(_phase->get_ctrl(init_trip), parse_predicate_entry)) { return false; } - Node* cmp_limit; - Node* bol; - - if (stride_con > 0) { - cmp_limit = CmpNode::make(init_trip, limit, iv_bt); - bol = new BoolNode(cmp_limit, BoolTest::lt); - } else { - cmp_limit = CmpNode::make(init_trip, limit, iv_bt); - bol = new BoolNode(cmp_limit, BoolTest::gt); - } - - insert_loop_limit_check_predicate(init_control->as_IfTrue(), cmp_limit, bol); + insert_init_trip_limit_check = true; } - if (bt == BoolTest::ne) { + BoolTest::mask mask = exit_test.mask; + if (mask == BoolTest::ne) { // Now we need to canonicalize the loop condition if it is 'ne'. assert(stride_con == 1 || stride_con == -1, "simple increment only - checked before"); if (stride_con > 0) { // 'ne' can be replaced with 'lt' only when init < limit. This is ensured by the inserted predicate above. - bt = BoolTest::lt; + mask = BoolTest::lt; } else { assert(stride_con < 0, "must be"); // 'ne' can be replaced with 'gt' only when init > limit. This is ensured by the inserted predicate above. - bt = BoolTest::gt; + mask = BoolTest::gt; } } Node* sfpt = nullptr; - if (loop->_child == nullptr) { - sfpt = find_safepoint(back_control, x, loop); + if (_loop->_child == nullptr) { + sfpt = _phase->find_safepoint(back_control, _head, _loop); } else { sfpt = iff->in(0); if (sfpt->Opcode() != Op_SafePoint) { @@ -2116,10 +2108,9 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } } - if (x->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint) { - Node* backedge_sfpt = x->in(LoopNode::LoopBackControl); - if (((iv_bt == T_INT && LoopStripMiningIter != 0) || - iv_bt == T_LONG) && + if (_head->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint) { + if (((_iv_bt == T_INT && LoopStripMiningIter != 0) || + _iv_bt == T_LONG) && sfpt == nullptr) { // Leaving the safepoint on the backedge and creating a // CountedLoop will confuse optimizations. We can't move the @@ -2127,28 +2118,72 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // location. Give up on that loop. return false; } - if (is_deleteable_safept(backedge_sfpt)) { - lazy_replace(backedge_sfpt, iftrue); - if (loop->_safepts != nullptr) { - loop->_safepts->yank(backedge_sfpt); - } - loop->_tail = iftrue; - } } + // Variables needed by convert() to do the actual conversion. We set these fields iff a counted loop is confirmed. + // This way the is_counted_loop() can run multiple times with possibly different configurations. + _limit = exit_test.limit; + _stride_con = stride_con; + _final_correction = final_correction; + _phi = phi; + _phi_increment = iv_incr.phi_incr; + _stride = stride.stride; + _includes_limit = includes_limit; + _mask = mask; + _increment = increment.incr; + _cmp = exit_test.cmp; + _cl_prob = exit_test.cl_prob; + _sfpt = sfpt; + _increment_truncation_type = increment.trunc_type; + + _insert_stride_overflow_limit_check = insert_stride_overflow_limit_check; + _insert_init_trip_limit_check = insert_init_trip_limit_check; #ifdef ASSERT - if (iv_bt == T_INT && - !x->as_Loop()->is_loop_nest_inner_loop() && - StressLongCountedLoop > 0 && - trunc1 == nullptr && - convert_to_long_loop(cmp, phi, loop)) { - return false; - } + _checked_for_counted_loop = true; +#endif + + return true; +} + +IdealLoopTree* CountedLoopConverter::convert() { +#ifdef ASSERT + assert(_checked_for_counted_loop, "must check for counted loop before conversion"); #endif - Node* adjusted_limit = limit; - if (phi_incr != nullptr) { + PhaseIterGVN* igvn = &_phase->igvn(); + Node* init_control = _head->in(LoopNode::EntryControl); + + if (_insert_stride_overflow_limit_check) { + Node* cmp_limit = CmpNode::make(_limit, igvn->integercon((_stride_con > 0 + ? max_signed_integer(_iv_bt) + : min_signed_integer(_iv_bt)) + - _final_correction, _iv_bt), _iv_bt); + Node* bol = new BoolNode(cmp_limit, _stride_con > 0 ? BoolTest::le : BoolTest::ge); + insert_loop_limit_check_predicate(init_control->as_IfTrue(), cmp_limit, bol); + } + + Node* init_trip = _phi->in(LoopNode::EntryControl); + if (_insert_init_trip_limit_check) { + Node* cmp_limit = CmpNode::make(init_trip, _limit, _iv_bt); + Node* bol = new BoolNode(cmp_limit, _stride_con > 0 ? BoolTest::lt : BoolTest::gt); + insert_loop_limit_check_predicate(init_control->as_IfTrue(), cmp_limit, bol); + } + + Node* back_control = _phase->loop_exit_control(_head, _loop); + if (_head->in(LoopNode::LoopBackControl)->Opcode() == Op_SafePoint) { + Node* backedge_sfpt = _head->in(LoopNode::LoopBackControl); + if (_phase->is_deleteable_safept(backedge_sfpt)) { + _phase->lazy_replace(backedge_sfpt, back_control); + if (_loop->_safepts != nullptr) { + _loop->_safepts->yank(backedge_sfpt); + } + _loop->_tail = back_control; + } + } + + Node* adjusted_limit = _limit; + if (_phi_increment != nullptr) { // If compare points directly to the phi we need to adjust // the compare so that it points to the incr. Limit have // to be adjusted to keep trip count the same and we @@ -2158,129 +2193,138 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // is converted to // i = init; do {} while(++i < limit+1); // - adjusted_limit = gvn->transform(AddNode::make(limit, stride, iv_bt)); + adjusted_limit = igvn->transform(AddNode::make(_limit, _stride, _iv_bt)); } - if (includes_limit) { + BoolTest::mask mask = _mask; + if (_includes_limit) { // The limit check guaranties that 'limit <= (max_jint - stride)' so // we can convert 'i <= limit' to 'i < limit+1' since stride != 0. // - Node* one = (stride_con > 0) ? gvn->integercon( 1, iv_bt) : gvn->integercon(-1, iv_bt); - adjusted_limit = gvn->transform(AddNode::make(adjusted_limit, one, iv_bt)); - if (bt == BoolTest::le) - bt = BoolTest::lt; - else if (bt == BoolTest::ge) - bt = BoolTest::gt; + Node* one = (_stride_con > 0) ? igvn->integercon(1, _iv_bt) : igvn->integercon(-1, _iv_bt); + adjusted_limit = igvn->transform(AddNode::make(adjusted_limit, one, _iv_bt)); + if (mask == BoolTest::le) + mask = BoolTest::lt; + else if (mask == BoolTest::ge) + mask = BoolTest::gt; else ShouldNotReachHere(); } - set_subtree_ctrl(adjusted_limit, false); + _phase->set_subtree_ctrl(adjusted_limit, false); // Build a canonical trip test. // Clone code, as old values may be in use. - incr = incr->clone(); - incr->set_req(1,phi); - incr->set_req(2,stride); - incr = _igvn.register_new_node_with_optimizer(incr); - set_early_ctrl(incr, false); - _igvn.rehash_node_delayed(phi); - phi->set_req_X( LoopNode::LoopBackControl, incr, &_igvn ); + Node* incr = _increment->clone(); + incr->set_req(1, _phi); + incr->set_req(2, _stride); + incr = igvn->register_new_node_with_optimizer(incr); + _phase->set_early_ctrl(incr, false); + igvn->rehash_node_delayed(_phi); + _phi->set_req_X(LoopNode::LoopBackControl, incr, igvn); // If phi type is more restrictive than Int, raise to // Int to prevent (almost) infinite recursion in igvn // which can only handle integer types for constants or minint..maxint. - if (!TypeInteger::bottom(iv_bt)->higher_equal(phi->bottom_type())) { - Node* nphi = PhiNode::make(phi->in(0), phi->in(LoopNode::EntryControl), TypeInteger::bottom(iv_bt)); - nphi->set_req(LoopNode::LoopBackControl, phi->in(LoopNode::LoopBackControl)); - nphi = _igvn.register_new_node_with_optimizer(nphi); - set_ctrl(nphi, get_ctrl(phi)); - _igvn.replace_node(phi, nphi); + Node* phi = _phi; + if (!TypeInteger::bottom(_iv_bt)->higher_equal(_phi->bottom_type())) { + Node* nphi = PhiNode::make(_phi->in(0), _phi->in(LoopNode::EntryControl), TypeInteger::bottom(_iv_bt)); + nphi->set_req(LoopNode::LoopBackControl, _phi->in(LoopNode::LoopBackControl)); + nphi = igvn->register_new_node_with_optimizer(nphi); + _phase->set_ctrl(nphi, _phase->get_ctrl(phi)); + igvn->replace_node(_phi, nphi); phi = nphi->as_Phi(); } - cmp = cmp->clone(); - cmp->set_req(1,incr); + + Node* iftrue = back_control; + const uint iftrue_op = iftrue->Opcode(); + Node* iff = iftrue->in(0); + Node* cmp = _cmp->clone(); + + cmp->set_req(1, incr); cmp->set_req(2, adjusted_limit); - cmp = _igvn.register_new_node_with_optimizer(cmp); - set_ctrl(cmp, iff->in(0)); + cmp = igvn->register_new_node_with_optimizer(cmp); + _phase->set_ctrl(cmp, iff->in(0)); - test = test->clone()->as_Bool(); - (*(BoolTest*)&test->_test)._test = bt; - test->set_req(1,cmp); - _igvn.register_new_node_with_optimizer(test); - set_ctrl(test, iff->in(0)); + BoolNode* test = iff->in(1)->clone()->as_Bool(); + const_cast<BoolTest*>(&test->_test)->_test = mask; // Yes, it's a const, but it's a newly cloned node so we should be fine. + test->set_req(1, cmp); + igvn->register_new_node_with_optimizer(test); + _phase->set_ctrl(test, iff->in(0)); // Replace the old IfNode with a new LoopEndNode - Node *lex = _igvn.register_new_node_with_optimizer(BaseCountedLoopEndNode::make(iff->in(0), test, cl_prob, iff->as_If()->_fcnt, iv_bt)); - IfNode *le = lex->as_If(); - uint dd = dom_depth(iff); - set_idom(le, le->in(0), dd); // Update dominance for loop exit - set_loop(le, loop); + Node* lex = igvn->register_new_node_with_optimizer(BaseCountedLoopEndNode::make(iff->in(0), + test, + _cl_prob, + iff->as_If()->_fcnt, + _iv_bt)); + IfNode* le = lex->as_If(); + const uint dd = _phase->dom_depth(iff); + _phase->set_idom(le, le->in(0), dd); // Update dominance for loop exit + _phase->set_loop(le, _loop); // Get the loop-exit control - Node *iffalse = iff->as_If()->proj_out(!(iftrue_op == Op_IfTrue)); + Node* iffalse = iff->as_If()->proj_out(!(iftrue_op == Op_IfTrue)); - // Need to swap loop-exit and loop-back control? +// Need to swap loop-exit and loop-back control? if (iftrue_op == Op_IfFalse) { - Node *ift2=_igvn.register_new_node_with_optimizer(new IfTrueNode (le)); - Node *iff2=_igvn.register_new_node_with_optimizer(new IfFalseNode(le)); + Node* ift2 = igvn->register_new_node_with_optimizer(new IfTrueNode(le)); + Node* iff2 = igvn->register_new_node_with_optimizer(new IfFalseNode(le)); - loop->_tail = back_control = ift2; - set_loop(ift2, loop); - set_loop(iff2, get_loop(iffalse)); + _loop->_tail = back_control = ift2; + _phase->set_loop(ift2, _loop); + _phase->set_loop(iff2, _phase->get_loop(iffalse)); // Lazy update of 'get_ctrl' mechanism. - lazy_replace(iffalse, iff2); - lazy_replace(iftrue, ift2); + _phase->lazy_replace(iffalse, iff2); + _phase->lazy_replace(iftrue, ift2); // Swap names iffalse = iff2; - iftrue = ift2; + iftrue = ift2; } else { - _igvn.rehash_node_delayed(iffalse); - _igvn.rehash_node_delayed(iftrue); - iffalse->set_req_X( 0, le, &_igvn ); - iftrue ->set_req_X( 0, le, &_igvn ); + igvn->rehash_node_delayed(iffalse); + igvn->rehash_node_delayed(iftrue); + iffalse->set_req_X(0, le, igvn); + iftrue->set_req_X(0, le, igvn); } - set_idom(iftrue, le, dd+1); - set_idom(iffalse, le, dd+1); + _phase->set_idom(iftrue, le, dd + 1); + _phase->set_idom(iffalse, le, dd + 1); assert(iff->outcnt() == 0, "should be dead now"); - lazy_replace( iff, le ); // fix 'get_ctrl' + _phase->lazy_replace(iff, le); // fix 'get_ctrl' Node* entry_control = init_control; - bool strip_mine_loop = iv_bt == T_INT && - loop->_child == nullptr && - sfpt != nullptr && - !loop->_has_call && - is_deleteable_safept(sfpt); + bool strip_mine_loop = _iv_bt == T_INT && + _loop->_child == nullptr && + _sfpt != nullptr && + !_loop->_has_call && + _phase->is_deleteable_safept(_sfpt); IdealLoopTree* outer_ilt = nullptr; if (strip_mine_loop) { - outer_ilt = create_outer_strip_mined_loop(test, cmp, init_control, loop, - cl_prob, le->_fcnt, entry_control, - iffalse); + outer_ilt = _phase->create_outer_strip_mined_loop(init_control, _loop, _cl_prob, le->_fcnt, entry_control, iffalse); } // Now setup a new CountedLoopNode to replace the existing LoopNode - BaseCountedLoopNode *l = BaseCountedLoopNode::make(entry_control, back_control, iv_bt); - l->set_unswitch_count(x->as_Loop()->unswitch_count()); // Preserve + BaseCountedLoopNode* l = BaseCountedLoopNode::make(entry_control, back_control, _iv_bt); + l->set_unswitch_count(_head->as_Loop()->unswitch_count()); // Preserve // The following assert is approximately true, and defines the intention // of can_be_counted_loop. It fails, however, because phase->type // is not yet initialized for this loop and its parts. //assert(l->can_be_counted_loop(this), "sanity"); - _igvn.register_new_node_with_optimizer(l); - set_loop(l, loop); - loop->_head = l; + igvn->register_new_node_with_optimizer(l); + _phase->set_loop(l, _loop); + _loop->_head = l; // Fix all data nodes placed at the old loop head. // Uses the lazy-update mechanism of 'get_ctrl'. - lazy_replace( x, l ); - set_idom(l, entry_control, dom_depth(entry_control) + 1); + _phase->lazy_replace(_head, l); + _phase->set_idom(l, entry_control, _phase->dom_depth(entry_control) + 1); - if (iv_bt == T_INT && (LoopStripMiningIter == 0 || strip_mine_loop)) { + if (_iv_bt == T_INT && (LoopStripMiningIter == 0 || strip_mine_loop)) { // Check for immediately preceding SafePoint and remove - if (sfpt != nullptr && (strip_mine_loop || is_deleteable_safept(sfpt))) { + if (_sfpt != nullptr && (strip_mine_loop || _phase->is_deleteable_safept(_sfpt))) { if (strip_mine_loop) { Node* outer_le = outer_ilt->_tail->in(0); - Node* sfpt_clone = sfpt->clone(); + Node* sfpt_clone = _sfpt->clone(); sfpt_clone->set_req(0, iffalse); outer_le->set_req(0, sfpt_clone); @@ -2289,40 +2333,42 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ // Polling load should be pinned outside inner loop. Node* new_polladdr = polladdr->clone(); new_polladdr->set_req(0, iffalse); - _igvn.register_new_node_with_optimizer(new_polladdr, polladdr); - set_ctrl(new_polladdr, iffalse); + igvn->register_new_node_with_optimizer(new_polladdr, polladdr); + _phase->set_ctrl(new_polladdr, iffalse); sfpt_clone->set_req(TypeFunc::Parms, new_polladdr); } // When this code runs, loop bodies have not yet been populated. const bool body_populated = false; - register_control(sfpt_clone, outer_ilt, iffalse, body_populated); - set_idom(outer_le, sfpt_clone, dom_depth(sfpt_clone)); + _phase->register_control(sfpt_clone, outer_ilt, iffalse, body_populated); + _phase->set_idom(outer_le, sfpt_clone, _phase->dom_depth(sfpt_clone)); } - lazy_replace(sfpt, sfpt->in(TypeFunc::Control)); - if (loop->_safepts != nullptr) { - loop->_safepts->yank(sfpt); + _phase->lazy_replace(_sfpt, _sfpt->in(TypeFunc::Control)); + if (_loop->_safepts != nullptr) { + _loop->_safepts->yank(_sfpt); } } } #ifdef ASSERT - assert(l->is_valid_counted_loop(iv_bt), "counted loop shape is messed up"); - assert(l == loop->_head && l->phi() == phi && l->loopexit_or_null() == lex, "" ); + assert(l->is_valid_counted_loop(_iv_bt), "counted loop shape is messed up"); + assert(l == _loop->_head && l->phi() == phi && l->loopexit_or_null() == lex, "" ); #endif + #ifndef PRODUCT if (TraceLoopOpts) { tty->print("Counted "); - loop->dump_head(); + _loop->dump_head(); } #endif - C->print_method(PHASE_AFTER_CLOOPS, 3, l); + _phase->C->print_method(PHASE_AFTER_CLOOPS, 3, l); // Capture bounds of the loop in the induction variable Phi before // subsequent transformation (iteration splitting) obscures the // bounds - l->phi()->as_Phi()->set_type(l->phi()->Value(&_igvn)); + l->phi()->as_Phi()->set_type(l->phi()->Value(igvn)); + IdealLoopTree* loop = _loop; if (strip_mine_loop) { l->mark_strip_mined(); l->verify_strip_mined(1); @@ -2331,21 +2377,24 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ } #ifndef PRODUCT - if (x->as_Loop()->is_loop_nest_inner_loop() && iv_bt == T_LONG) { + if (_head->as_Loop()->is_loop_nest_inner_loop() && _iv_bt == T_LONG) { Atomic::inc(&_long_loop_counted_loops); } #endif - if (iv_bt == T_LONG && x->as_Loop()->is_loop_nest_outer_loop()) { + + if (_iv_bt == T_LONG && _head->as_Loop()->is_loop_nest_outer_loop()) { l->mark_loop_nest_outer_loop(); } - return true; + return loop; } // Check if there is a dominating loop limit check of the form 'init < limit' starting at the loop entry. // If there is one, then we do not need to create an additional Loop Limit Check Predicate. -bool PhaseIdealLoop::has_dominating_loop_limit_check(Node* init_trip, Node* limit, const jlong stride_con, +bool CountedLoopConverter::has_dominating_loop_limit_check(Node* init_trip, Node* limit, const jlong stride_con, const BasicType iv_bt, Node* loop_entry) { + PhaseIterGVN& _igvn = _phase->igvn(); + // Eagerly call transform() on the Cmp and Bool node to common them up if possible. This is required in order to // successfully find a dominated test with the If node below. Node* cmp_limit; @@ -2368,8 +2417,8 @@ bool PhaseIdealLoop::has_dominating_loop_limit_check(Node* init_trip, Node* limi const bool found_dominating_test = dominated_iff != nullptr && dominated_iff->is_ConI(); // Kill the If with its projections again in the next IGVN round by cutting it off from the graph. - _igvn.replace_input_of(iff, 0, C->top()); - _igvn.replace_input_of(iff, 1, C->top()); + _igvn.replace_input_of(iff, 0, _phase->C->top()); + _igvn.replace_input_of(iff, 1, _phase->C->top()); return found_dominating_test; } @@ -2677,11 +2726,9 @@ Node* LoopLimitNode::Identity(PhaseGVN* phase) { // Match increment with optional truncation: // CHAR: (i+1)&0x7fff, BYTE: ((i+1)<<8)>>8, or SHORT: ((i+1)<<16)>>16 // Return null for failure. Success returns the increment node. -Node* CountedLoopNode::match_incr_with_optional_truncation(Node* expr, Node** trunc1, Node** trunc2, - const TypeInteger** trunc_type, - BasicType bt) { +CountedLoopNode::TruncatedIncrement CountedLoopNode::match_incr_with_optional_truncation(Node* expr, BasicType bt) { // Quick cutouts: - if (expr == nullptr || expr->req() != 3) return nullptr; + if (expr == nullptr || expr->req() != 3) return TruncatedIncrement{}; Node *t1 = nullptr; Node *t2 = nullptr; @@ -2722,14 +2769,11 @@ Node* CountedLoopNode::match_incr_with_optional_truncation(Node* expr, Node** tr // If (maybe after stripping) it is an AddI, we won: if (n1op == Op_Add(bt)) { - *trunc1 = t1; - *trunc2 = t2; - *trunc_type = trunc_t; - return n1; + return TruncatedIncrement{n1, t1, t2, trunc_t}; } // failed - return nullptr; + return TruncatedIncrement{}; } IfNode* CountedLoopNode::find_multiversion_if_from_multiversion_fast_main_loop() { @@ -3299,18 +3343,18 @@ Node *OuterStripMinedLoopEndNode::Ideal(PhaseGVN *phase, bool can_reshape) { // i = ? // } while ( i < 10) // -const TypeInt* PhaseIdealLoop::filtered_type( Node *n, Node* n_ctrl) { +const TypeInt* CountedLoopConverter::filtered_type(Node* n, Node* n_ctrl) { assert(n && n->bottom_type()->is_int(), "must be int"); const TypeInt* filtered_t = nullptr; if (!n->is_Phi()) { - assert(n_ctrl != nullptr || n_ctrl == C->top(), "valid control"); + assert(n_ctrl != nullptr || n_ctrl == _phase->C->top(), "valid control"); filtered_t = filtered_type_from_dominators(n, n_ctrl); } else { Node* phi = n->as_Phi(); Node* region = phi->in(0); assert(n_ctrl == nullptr || n_ctrl == region, "ctrl parameter must be region"); - if (region && region != C->top()) { + if (region && region != _phase->C->top()) { for (uint i = 1; i < phi->req(); i++) { Node* val = phi->in(i); Node* use_c = region->in(i); @@ -3325,7 +3369,7 @@ const TypeInt* PhaseIdealLoop::filtered_type( Node *n, Node* n_ctrl) { } } } - const TypeInt* n_t = _igvn.type(n)->is_int(); + const TypeInt* n_t = _phase->igvn().type(n)->is_int(); if (filtered_t != nullptr) { n_t = n_t->join(filtered_t)->is_int(); } @@ -3335,22 +3379,22 @@ const TypeInt* PhaseIdealLoop::filtered_type( Node *n, Node* n_ctrl) { //------------------------------filtered_type_from_dominators-------------------------------- // Return a possibly more restrictive type for val based on condition control flow of dominators -const TypeInt* PhaseIdealLoop::filtered_type_from_dominators( Node* val, Node *use_ctrl) { +const TypeInt* CountedLoopConverter::filtered_type_from_dominators(Node* val, Node* use_ctrl) { if (val->is_Con()) { return val->bottom_type()->is_int(); } uint if_limit = 10; // Max number of dominating if's visited const TypeInt* rtn_t = nullptr; - if (use_ctrl && use_ctrl != C->top()) { - Node* val_ctrl = get_ctrl(val); - uint val_dom_depth = dom_depth(val_ctrl); + if (use_ctrl && use_ctrl != _phase->C->top()) { + Node* val_ctrl = _phase->get_ctrl(val); + uint val_dom_depth = _phase->dom_depth(val_ctrl); Node* pred = use_ctrl; uint if_cnt = 0; while (if_cnt < if_limit) { if ((pred->Opcode() == Op_IfTrue || pred->Opcode() == Op_IfFalse)) { if_cnt++; - const TypeInt* if_t = IfNode::filtered_int_type(&_igvn, val, pred); + const TypeInt* if_t = IfNode::filtered_int_type(&_phase->igvn(), val, pred); if (if_t != nullptr) { if (rtn_t == nullptr) { rtn_t = if_t; @@ -3359,12 +3403,12 @@ const TypeInt* PhaseIdealLoop::filtered_type_from_dominators( Node* val, Node *u } } } - pred = idom(pred); - if (pred == nullptr || pred == C->top()) { + pred = _phase->idom(pred); + if (pred == nullptr || pred == _phase->C->top()) { break; } // Stop if going beyond definition block of val - if (dom_depth(pred) < val_dom_depth) { + if (_phase->dom_depth(pred) < val_dom_depth) { break; } } @@ -3949,7 +3993,7 @@ void IdealLoopTree::check_safepts(VectorSet &visited, Node_List &stack) { //---------------------------is_deleteable_safept---------------------------- // Is safept not required by an outer loop? -bool PhaseIdealLoop::is_deleteable_safept(Node* sfpt) { +bool PhaseIdealLoop::is_deleteable_safept(Node* sfpt) const { assert(sfpt->Opcode() == Op_SafePoint, ""); IdealLoopTree* lp = get_loop(sfpt)->_parent; while (lp != nullptr) { @@ -4168,7 +4212,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { IdealLoopTree* loop = this; if (_head->is_CountedLoop() || - phase->is_counted_loop(_head, loop, T_INT)) { + phase->try_convert_to_counted_loop(_head, loop, T_INT)) { if (LoopStripMiningIter == 0 || _head->as_CountedLoop()->is_strip_mined()) { // Indicate we do not need a safepoint here @@ -4182,7 +4226,7 @@ void IdealLoopTree::counted_loop( PhaseIdealLoop *phase ) { // Look for induction variables phase->replace_parallel_iv(this); } else if (_head->is_LongCountedLoop() || - phase->is_counted_loop(_head, loop, T_LONG)) { + phase->try_convert_to_counted_loop(_head, loop, T_LONG)) { remove_safepoints(phase, true); } else { assert(!_head->is_Loop() || !_head->as_Loop()->is_loop_nest_inner_loop(), "transformation to counted loop should not fail"); @@ -4974,9 +5018,15 @@ int PhaseIdealLoop::_loop_invokes=0;// Count of PhaseIdealLoop invokes int PhaseIdealLoop::_loop_work=0; // Sum of PhaseIdealLoop x unique volatile int PhaseIdealLoop::_long_loop_candidates=0; // Number of long loops seen volatile int PhaseIdealLoop::_long_loop_nests=0; // Number of long loops successfully transformed to a nest -volatile int PhaseIdealLoop::_long_loop_counted_loops=0; // Number of long loops successfully transformed to a counted loop +volatile int CountedLoopConverter::_long_loop_counted_loops = 0; // Number of long loops successfully transformed to a + // counted loop void PhaseIdealLoop::print_statistics() { - tty->print_cr("PhaseIdealLoop=%d, sum _unique=%d, long loops=%d/%d/%d", _loop_invokes, _loop_work, _long_loop_counted_loops, _long_loop_nests, _long_loop_candidates); + tty->print_cr("PhaseIdealLoop=%d, sum _unique=%d, long loops=%d/%d/%d", + _loop_invokes, + _loop_work, + CountedLoopConverter::_long_loop_counted_loops, + _long_loop_nests, + _long_loop_candidates); } #endif diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index ef958ced8c333..0c08fdcacef62 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -258,9 +258,13 @@ class CountedLoopNode : public BaseCountedLoopNode { int stride_con() const; // Match increment with optional truncation - static Node* - match_incr_with_optional_truncation(Node* expr, Node** trunc1, Node** trunc2, const TypeInteger** trunc_type, - BasicType bt); + struct TruncatedIncrement { + Node* incr = nullptr; + Node* trunc1 = nullptr; + Node* trunc2 = nullptr; + const TypeInteger* trunc_type = nullptr; + }; + static TruncatedIncrement match_incr_with_optional_truncation(Node* expr, BasicType bt); // A 'main' loop has a pre-loop and a post-loop. The 'main' loop // can run short a few iterations and may start a few iterations in. @@ -1001,8 +1005,6 @@ class PhaseIdealLoop : public PhaseTransform { void rewire_old_target_loop_entry_dependency_to_new_entry(LoopNode* target_loop_head, const Node* old_target_loop_entry, uint node_index_before_new_assertion_predicate_nodes); - void insert_loop_limit_check_predicate(ParsePredicateSuccessProj* loop_limit_check_parse_proj, Node* cmp_limit, - Node* bol); void log_loop_tree(); public: @@ -1215,7 +1217,7 @@ class PhaseIdealLoop : public PhaseTransform { void recompute_dom_depth(); // Is safept not required by an outer loop? - bool is_deleteable_safept(Node* sfpt); + bool is_deleteable_safept(Node* sfpt) const; // Replace parallel induction variable (parallel to trip counter) void replace_parallel_iv(IdealLoopTree *loop); @@ -1266,24 +1268,40 @@ class PhaseIdealLoop : public PhaseTransform { // Per-Node transform virtual Node* transform(Node* n) { return nullptr; } - Node* loop_exit_control(Node* x, IdealLoopTree* loop); - Node* loop_exit_test(Node* back_control, IdealLoopTree* loop, Node*& incr, Node*& limit, BoolTest::mask& bt, float& cl_prob); - Node* loop_iv_incr(Node* incr, Node* x, IdealLoopTree* loop, Node*& phi_incr); - Node* loop_iv_stride(Node* incr, IdealLoopTree* loop, Node*& xphi); - PhiNode* loop_iv_phi(Node* xphi, Node* phi_incr, Node* x, IdealLoopTree* loop); + Node* loop_exit_control(const Node* head, const IdealLoopTree* loop) const; + + struct LoopExitTest { + CmpNode* cmp = nullptr; + Node* incr = nullptr; + Node* limit = nullptr; + const BoolTest::mask mask = BoolTest::illegal; + const float cl_prob = 0.0f; + }; + LoopExitTest loop_exit_test(const Node* back_control, const IdealLoopTree* loop); + + struct LoopIVIncr { + Node* incr = nullptr; + Node* phi_incr = nullptr; + }; + static LoopIVIncr loop_iv_incr(Node* old_incr, const Node* head, const IdealLoopTree* loop); + + struct LoopIvStride { + Node* stride = nullptr; + Node* xphi = nullptr; + }; + static LoopIvStride loop_iv_stride(const Node* incr); + + static PhiNode* loop_iv_phi(const Node* xphi, const Node* phi_incr, const Node* head); - bool is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_bt); + bool try_convert_to_counted_loop(Node* head, IdealLoopTree*&loop, const BasicType iv_bt); Node* loop_nest_replace_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head, BasicType bt); bool create_loop_nest(IdealLoopTree* loop, Node_List &old_new); -#ifdef ASSERT - bool convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* loop); -#endif + void add_parse_predicate(Deoptimization::DeoptReason reason, Node* inner_head, IdealLoopTree* loop, SafePointNode* sfpt); - SafePointNode* find_safepoint(Node* back_control, Node* x, IdealLoopTree* loop); + SafePointNode* find_safepoint(Node* back_control, const Node* head, const IdealLoopTree* loop); IdealLoopTree* insert_outer_loop(IdealLoopTree* loop, LoopNode* outer_l, Node* outer_ift); - IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, - IdealLoopTree* loop, float cl_prob, float le_fcnt, + IdealLoopTree* create_outer_strip_mined_loop(Node* init_control, IdealLoopTree* loop, float cl_prob, float le_fcnt, Node*& entry_control, Node*& iffalse); Node* exact_limit( IdealLoopTree *loop ); @@ -1405,8 +1423,6 @@ class PhaseIdealLoop : public PhaseTransform { Node* clone_nodes_with_same_ctrl(Node* start_node, ProjNode* old_uncommon_proj, Node* new_uncommon_proj); void fix_cloned_data_node_controls(const ProjNode* orig, Node* new_uncommon_proj, const OrigToNewHashtable& orig_to_clone); - bool has_dominating_loop_limit_check(Node* init_trip, Node* limit, jlong stride_con, BasicType iv_bt, - Node* loop_entry); public: void register_control(Node* n, IdealLoopTree *loop, Node* pred, bool update_body = true); @@ -1608,12 +1624,6 @@ class PhaseIdealLoop : public PhaseTransform { Node*& shift, Node*& offset); private: - // Return a type based on condition control flow - const TypeInt* filtered_type( Node *n, Node* n_ctrl); - const TypeInt* filtered_type( Node *n ) { return filtered_type(n, nullptr); } - // Helpers for filtered type - const TypeInt* filtered_type_from_dominators( Node* val, Node *val_ctrl); - // Helper functions Node *spinup( Node *iff, Node *new_false, Node *new_true, Node *region, Node *phi, small_cache *cache ); Node *find_use_block( Node *use, Node *def, Node *old_false, Node *new_false, Node *old_true, Node *new_true ); @@ -1742,7 +1752,6 @@ class PhaseIdealLoop : public PhaseTransform { static int _loop_work; // Sum of PhaseIdealLoop x _unique static volatile int _long_loop_candidates; static volatile int _long_loop_nests; - static volatile int _long_loop_counted_loops; #endif #ifdef ASSERT @@ -1826,6 +1835,69 @@ class PhaseIdealLoop : public PhaseTransform { ConNode* zerocon(BasicType bt); }; +class CountedLoopConverter { + friend class PhaseIdealLoop; + + PhaseIdealLoop* const _phase; + Node* const _head; // FIXME: type to LoopNode? + IdealLoopTree* const _loop; + const BasicType _iv_bt; + +#ifdef ASSERT + bool _checked_for_counted_loop = false; +#endif + + // stats for PhaseIdealLoop::print_statistics() + static volatile int _long_loop_counted_loops; + + // To be assigned once a counted loop is confirmed. + Node* _limit; + jlong _stride_con; + Node* _phi; + Node* _phi_increment; + Node* _stride; + bool _includes_limit; + BoolTest::mask _mask; + Node* _increment; + Node* _cmp; + float _cl_prob; + Node* _sfpt; + jlong _final_correction; + const TypeInteger* _increment_truncation_type; + bool _insert_stride_overflow_limit_check = false; + bool _insert_init_trip_limit_check = false; + + // Return a type based on condition control flow + const TypeInt* filtered_type( Node *n, Node* n_ctrl); + const TypeInt* filtered_type( Node *n ) { return filtered_type(n, nullptr); } + // Helpers for filtered type + const TypeInt* filtered_type_from_dominators( Node* val, Node *val_ctrl); + + void insert_loop_limit_check_predicate(const ParsePredicateSuccessProj* loop_limit_check_parse_proj, Node* cmp_limit, + Node* bol); + bool has_dominating_loop_limit_check(Node* init_trip, Node* limit, jlong stride_con, BasicType iv_bt, + Node* loop_entry); + + public: + CountedLoopConverter(PhaseIdealLoop* phase, Node* head, IdealLoopTree* loop, const BasicType iv_bt) + : _phase(phase), + _head(head), + _loop(loop), + _iv_bt(iv_bt) { + assert(phase != nullptr, ""); // Fail early if mandatory parameters are null. + assert(head != nullptr, ""); + assert(loop != nullptr, ""); + assert(iv_bt == T_INT || iv_bt == T_LONG, ""); // Loops can be either int or long. + } + + bool is_counted_loop(); + IdealLoopTree* convert(); + +#ifdef ASSERT + bool should_stress_long_counted_loop() const; + bool stress_long_counted_loop() const; +#endif +}; class AutoNodeBudget : public StackObj { diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index e896196c6cf1c..70e7710beaf08 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -2841,23 +2841,21 @@ int PhaseIdealLoop::stride_of_possible_iv(Node* iff) { Node* phi = cmp1; for (uint i = 1; i < phi->req(); i++) { Node* in = phi->in(i); - Node* add = CountedLoopNode::match_incr_with_optional_truncation(in, - &trunc1, &trunc2, &ttype, T_INT); - if (add && add->in(1) == phi) { - add2 = add->in(2); + CountedLoopNode::TruncatedIncrement add = CountedLoopNode::match_incr_with_optional_truncation(in, T_INT); + if (add.incr != nullptr && add.incr->in(1) == phi) { + add2 = add.incr->in(2); break; } } } else { // (If (Bool (CmpX addtrunc:(Optional-trunc((AddI (Phi ...addtrunc...) add2)) ))) Node* addtrunc = cmp1; - Node* add = CountedLoopNode::match_incr_with_optional_truncation(addtrunc, - &trunc1, &trunc2, &ttype, T_INT); - if (add && add->in(1)->is_Phi()) { - Node* phi = add->in(1); + CountedLoopNode::TruncatedIncrement add = CountedLoopNode::match_incr_with_optional_truncation(addtrunc, T_INT); + if (add.incr != nullptr && add.incr->in(1)->is_Phi()) { + Node* phi = add.incr->in(1); for (uint i = 1; i < phi->req(); i++) { if (phi->in(i) == addtrunc) { - add2 = add->in(2); + add2 = add.incr->in(2); break; } } @@ -4261,49 +4259,40 @@ bool PhaseIdealLoop::duplicate_loop_backedge(IdealLoopTree *loop, Node_List &old return false; } - BoolTest::mask bt = BoolTest::illegal; - float cl_prob = 0; - Node* incr = nullptr; - Node* limit = nullptr; - Node* cmp = loop_exit_test(back_control, loop, incr, limit, bt, cl_prob); - if (cmp == nullptr || cmp->Opcode() != Op_CmpI) { + LoopExitTest loop_exit = loop_exit_test(back_control, loop); + if (loop_exit.cmp == nullptr || loop_exit.cmp->Opcode() != Op_CmpI) { return false; } // With an extra phi for the candidate iv? // Or the region node is the loop head - if (!incr->is_Phi() || incr->in(0) == head) { + if (!loop_exit.incr->is_Phi() || loop_exit.incr->in(0) == head) { return false; } PathFrequency pf(head, this); - region = incr->in(0); + region = loop_exit.incr->in(0); // Go over all paths for the extra phi's region and see if that // path is frequent enough and would match the expected iv shape // if the extra phi is removed inner = 0; - for (uint i = 1; i < incr->req(); ++i) { - Node* in = incr->in(i); - Node* trunc1 = nullptr; - Node* trunc2 = nullptr; - const TypeInteger* iv_trunc_t = nullptr; - Node* orig_in = in; - if (!(in = CountedLoopNode::match_incr_with_optional_truncation(in, &trunc1, &trunc2, &iv_trunc_t, T_INT))) { + for (uint i = 1; i < loop_exit.incr->req(); ++i) { + CountedLoopNode::TruncatedIncrement increment = CountedLoopNode::match_incr_with_optional_truncation(loop_exit.incr->in(i), T_INT); + if (increment.incr == nullptr) { continue; } - assert(in->Opcode() == Op_AddI, "wrong increment code"); - Node* xphi = nullptr; - Node* stride = loop_iv_stride(in, loop, xphi); + assert(increment.incr->Opcode() == Op_AddI, "wrong increment code"); + LoopIvStride stride = loop_iv_stride(increment.incr); - if (stride == nullptr) { + if (stride.stride == nullptr) { continue; } - PhiNode* phi = loop_iv_phi(xphi, nullptr, head, loop); + PhiNode* phi = loop_iv_phi(stride.xphi, nullptr, head); if (phi == nullptr || - (trunc1 == nullptr && phi->in(LoopNode::LoopBackControl) != incr) || - (trunc1 != nullptr && phi->in(LoopNode::LoopBackControl) != trunc1)) { + (increment.trunc1 == nullptr && phi->in(LoopNode::LoopBackControl) != loop_exit.incr) || + (increment.trunc1 != nullptr && phi->in(LoopNode::LoopBackControl) != increment.trunc1)) { return false; }