Mercurial > hg > truffle
diff src/share/vm/opto/loopTransform.cpp @ 2383:9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
Summary: Add predicates when loop head bytecode is parsed instead of when back branch bytecode is parsed.
Reviewed-by: never
author | kvn |
---|---|
date | Mon, 21 Mar 2011 11:28:14 -0700 |
parents | f95d63e2154a |
children | 1927db75dd85 |
line wrap: on
line diff
--- a/src/share/vm/opto/loopTransform.cpp Mon Mar 21 02:30:49 2011 -0700 +++ b/src/share/vm/opto/loopTransform.cpp Mon Mar 21 11:28:14 2011 -0700 @@ -205,6 +205,8 @@ } phase->register_new_node(addx, phase->get_ctrl(x)); phase->_igvn.replace_node(n1, addx); + assert(phase->get_loop(phase->get_ctrl(n1)) == this, ""); + _body.yank(n1); return addx; } @@ -307,15 +309,21 @@ // iterations adjusted. Therefore, we need to declare this loop as // no longer a 'main' loop; it will need new pre and post loops before // we can do further RCE. +#ifndef PRODUCT + if (TraceLoopOpts) { + tty->print("Peel "); + loop->dump_head(); + } +#endif Node *h = loop->_head; - if( h->is_CountedLoop() ) { + if (h->is_CountedLoop()) { CountedLoopNode *cl = h->as_CountedLoop(); assert(cl->trip_count() > 0, "peeling a fully unrolled loop"); cl->set_trip_count(cl->trip_count() - 1); - if( cl->is_main_loop() ) { + if (cl->is_main_loop()) { cl->set_normal_loop(); #ifndef PRODUCT - if( PrintOpto && VerifyLoopOptimizations ) { + if (PrintOpto && VerifyLoopOptimizations) { tty->print("Peeling a 'main' loop; resetting to 'normal' "); loop->dump_head(); } @@ -645,6 +653,15 @@ // alignment. Useful to unroll loops that do no array accesses. void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ) { +#ifndef PRODUCT + if (TraceLoopOpts) { + if (peel_only) + tty->print("PeelMainPost "); + else + tty->print("PreMainPost "); + loop->dump_head(); + } +#endif C->set_major_progress(); // Find common pieces of the loop being guarded with pre & post loops @@ -897,16 +914,19 @@ //------------------------------do_unroll-------------------------------------- // Unroll the loop body one step - make each trip do 2 iterations. void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip ) { - assert( LoopUnrollLimit, "" ); + assert(LoopUnrollLimit, ""); + CountedLoopNode *loop_head = loop->_head->as_CountedLoop(); + CountedLoopEndNode *loop_end = loop_head->loopexit(); + assert(loop_end, ""); #ifndef PRODUCT - if( PrintOpto && VerifyLoopOptimizations ) { + if (PrintOpto && VerifyLoopOptimizations) { tty->print("Unrolling "); loop->dump_head(); + } else if (TraceLoopOpts) { + tty->print("Unroll %d ", loop_head->unrolled_count()*2); + loop->dump_head(); } #endif - CountedLoopNode *loop_head = loop->_head->as_CountedLoop(); - CountedLoopEndNode *loop_end = loop_head->loopexit(); - assert( loop_end, "" ); // Remember loop node count before unrolling to detect // if rounds of unroll,optimize are making progress @@ -915,7 +935,7 @@ Node *ctrl = loop_head->in(LoopNode::EntryControl); Node *limit = loop_head->limit(); Node *init = loop_head->init_trip(); - Node *strid = loop_head->stride(); + Node *stride = loop_head->stride(); Node *opaq = NULL; if( adjust_min_trip ) { // If not maximally unrolling, need adjustment @@ -955,13 +975,13 @@ // odd iteration: (trip_cnt & ~1). Then back compute a new limit. Node *span = new (C, 3) SubINode( limit, init ); register_new_node( span, ctrl ); - Node *trip = new (C, 3) DivINode( 0, span, strid ); + Node *trip = new (C, 3) DivINode( 0, span, stride ); register_new_node( trip, ctrl ); Node *mtwo = _igvn.intcon(-2); set_ctrl(mtwo, C->root()); Node *rond = new (C, 3) AndINode( trip, mtwo ); register_new_node( rond, ctrl ); - Node *spn2 = new (C, 3) MulINode( rond, strid ); + Node *spn2 = new (C, 3) MulINode( rond, stride ); register_new_node( spn2, ctrl ); Node *lim2 = new (C, 3) AddINode( spn2, init ); register_new_node( lim2, ctrl ); @@ -1040,17 +1060,23 @@ void PhaseIdealLoop::do_maximally_unroll( IdealLoopTree *loop, Node_List &old_new ) { CountedLoopNode *cl = loop->_head->as_CountedLoop(); - assert( cl->trip_count() > 0, ""); + assert(cl->trip_count() > 0, ""); +#ifndef PRODUCT + if (TraceLoopOpts) { + tty->print("MaxUnroll %d ", cl->trip_count()); + loop->dump_head(); + } +#endif // If loop is tripping an odd number of times, peel odd iteration - if( (cl->trip_count() & 1) == 1 ) { - do_peeling( loop, old_new ); + if ((cl->trip_count() & 1) == 1) { + do_peeling(loop, old_new); } // Now its tripping an even number of times remaining. Double loop body. // Do not adjust pre-guards; they are not needed and do not exist. - if( cl->trip_count() > 0 ) { - do_unroll( loop, old_new, false ); + if (cl->trip_count() > 0) { + do_unroll(loop, old_new, false); } } @@ -1227,35 +1253,55 @@ // Eliminate range-checks and other trip-counter vs loop-invariant tests. void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) { #ifndef PRODUCT - if( PrintOpto && VerifyLoopOptimizations ) { + if (PrintOpto && VerifyLoopOptimizations) { tty->print("Range Check Elimination "); loop->dump_head(); + } else if (TraceLoopOpts) { + tty->print("RangeCheck "); + loop->dump_head(); } #endif - assert( RangeCheckElimination, "" ); + assert(RangeCheckElimination, ""); CountedLoopNode *cl = loop->_head->as_CountedLoop(); - assert( cl->is_main_loop(), "" ); + assert(cl->is_main_loop(), ""); + + // protect against stride not being a constant + if (!cl->stride_is_con()) + return; // Find the trip counter; we are iteration splitting based on it Node *trip_counter = cl->phi(); // Find the main loop limit; we will trim it's iterations // to not ever trip end tests Node *main_limit = cl->limit(); + + // Need to find the main-loop zero-trip guard + Node *ctrl = cl->in(LoopNode::EntryControl); + assert(ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, ""); + Node *iffm = ctrl->in(0); + assert(iffm->Opcode() == Op_If, ""); + Node *bolzm = iffm->in(1); + assert(bolzm->Opcode() == Op_Bool, ""); + Node *cmpzm = bolzm->in(1); + assert(cmpzm->is_Cmp(), ""); + Node *opqzm = cmpzm->in(2); + // Can not optimize a loop if pre-loop Opaque1 node is optimized + // away and then another round of loop opts attempted. + if (opqzm->Opcode() != Op_Opaque1) + return; + assert(opqzm->in(1) == main_limit, "do not understand situation"); + // Find the pre-loop limit; we will expand it's iterations to // not ever trip low tests. - Node *ctrl = cl->in(LoopNode::EntryControl); - assert( ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "" ); - Node *iffm = ctrl->in(0); - assert( iffm->Opcode() == Op_If, "" ); Node *p_f = iffm->in(0); - assert( p_f->Opcode() == Op_IfFalse, "" ); + assert(p_f->Opcode() == Op_IfFalse, ""); CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd(); - assert( pre_end->loopnode()->is_pre_loop(), "" ); + assert(pre_end->loopnode()->is_pre_loop(), ""); Node *pre_opaq1 = pre_end->limit(); // Occasionally it's possible for a pre-loop Opaque1 node to be // optimized away and then another round of loop opts attempted. // We can not optimize this particular loop in that case. - if( pre_opaq1->Opcode() != Op_Opaque1 ) + if (pre_opaq1->Opcode() != Op_Opaque1) return; Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1; Node *pre_limit = pre_opaq->in(1); @@ -1266,25 +1312,11 @@ // Ensure the original loop limit is available from the // pre-loop Opaque1 node. Node *orig_limit = pre_opaq->original_loop_limit(); - if( orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP ) + if (orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP) return; - // Need to find the main-loop zero-trip guard - Node *bolzm = iffm->in(1); - assert( bolzm->Opcode() == Op_Bool, "" ); - Node *cmpzm = bolzm->in(1); - assert( cmpzm->is_Cmp(), "" ); - Node *opqzm = cmpzm->in(2); - if( opqzm->Opcode() != Op_Opaque1 ) - return; - assert( opqzm->in(1) == main_limit, "do not understand situation" ); - // Must know if its a count-up or count-down loop - // protect against stride not being a constant - if ( !cl->stride_is_con() ) { - return; - } int stride_con = cl->stride_con(); Node *zero = _igvn.intcon(0); Node *one = _igvn.intcon(1); @@ -1566,16 +1598,24 @@ // have on the last iteration. This will break the loop. bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) { // Minimum size must be empty loop - if( _body.size() > 7/*number of nodes in an empty loop*/ ) return false; + if (_body.size() > 7/*number of nodes in an empty loop*/) + return false; - if( !_head->is_CountedLoop() ) return false; // Dead loop + if (!_head->is_CountedLoop()) + return false; // Dead loop CountedLoopNode *cl = _head->as_CountedLoop(); - if( !cl->loopexit() ) return false; // Malformed loop - if( !phase->is_member(this,phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)) ) ) + if (!cl->loopexit()) + return false; // Malformed loop + if (!phase->is_member(this, phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)))) return false; // Infinite loop #ifndef PRODUCT - if( PrintOpto ) - tty->print_cr("Removing empty loop"); + if (PrintOpto) { + tty->print("Removing empty loop"); + this->dump_head(); + } else if (TraceLoopOpts) { + tty->print("Empty "); + this->dump_head(); + } #endif #ifdef ASSERT // Ensure only one phi which is the iv. @@ -1720,7 +1760,7 @@ //------------------------------iteration_split-------------------------------- bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) { // Recursively iteration split nested loops - if( _child && !_child->iteration_split( phase, old_new )) + if (_child && !_child->iteration_split(phase, old_new)) return false; // Clean out prior deadwood @@ -1729,21 +1769,20 @@ // Look for loop-exit tests with my 50/50 guesses from the Parsing stage. // Replace with a 1-in-10 exit guess. - if( _parent /*not the root loop*/ && + if (_parent /*not the root loop*/ && !_irreducible && // Also ignore the occasional dead backedge - !tail()->is_top() ) { + !tail()->is_top()) { adjust_loop_exit_prob(phase); } - // Gate unrolling, RCE and peeling efforts. - if( !_child && // If not an inner loop, do not split + if (!_child && // If not an inner loop, do not split !_irreducible && _allow_optimizations && - !tail()->is_top() ) { // Also ignore the occasional dead backedge + !tail()->is_top()) { // Also ignore the occasional dead backedge if (!_has_call) { - if (!iteration_split_impl( phase, old_new )) { + if (!iteration_split_impl(phase, old_new)) { return false; } } else if (policy_unswitching(phase)) { @@ -1752,16 +1791,17 @@ } // Minor offset re-organization to remove loop-fallout uses of - // trip counter. - if( _head->is_CountedLoop() ) phase->reorg_offsets( this ); - if( _next && !_next->iteration_split( phase, old_new )) + // trip counter when there was no major reshaping. + phase->reorg_offsets(this); + + if (_next && !_next->iteration_split(phase, old_new)) return false; return true; } //-------------------------------is_uncommon_trap_proj---------------------------- // Return true if proj is the form of "proj->[region->..]call_uct" -bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_predicate) { +bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, Deoptimization::DeoptReason reason) { int path_limit = 10; assert(proj, "invalid argument"); Node* out = proj; @@ -1772,8 +1812,8 @@ if (out->is_CallStaticJava()) { int req = out->as_CallStaticJava()->uncommon_trap_request(); if (req != 0) { - Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(req); - if (!must_reason_predicate || reason == Deoptimization::Reason_predicate){ + Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); + if (trap_reason == reason || reason == Deoptimization::Reason_none) { return true; } } @@ -1790,15 +1830,15 @@ // other_proj->[region->..]call_uct" // // "must_reason_predicate" means the uct reason must be Reason_predicate -bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reason_predicate) { +bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, Deoptimization::DeoptReason reason) { Node *in0 = proj->in(0); if (!in0->is_If()) return false; // Variation of a dead If node. if (in0->outcnt() < 2) return false; IfNode* iff = in0->as_If(); - // we need "If(Conv2B(Opaque1(...)))" pattern for must_reason_predicate - if (must_reason_predicate) { + // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate + if (reason != Deoptimization::Reason_none) { if (iff->in(1)->Opcode() != Op_Conv2B || iff->in(1)->in(1)->Opcode() != Op_Opaque1) { return false; @@ -1806,7 +1846,19 @@ } ProjNode* other_proj = iff->proj_out(1-proj->_con)->as_Proj(); - return is_uncommon_trap_proj(other_proj, must_reason_predicate); + return is_uncommon_trap_proj(other_proj, reason); +} + +//-------------------------------register_control------------------------- +void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred) { + assert(n->is_CFG(), "must be control node"); + _igvn.register_new_node_with_optimizer(n); + loop->_body.push(n); + set_loop(n, loop); + // When called from beautify_loops() idom is not constructed yet. + if (_idom != NULL) { + set_idom(n, pred, dom_depth(pred)); + } } //------------------------------create_new_if_for_predicate------------------------ @@ -1843,8 +1895,10 @@ // // We will create a region to guard the uct call if there is no one there. // The true projecttion (if_cont) of the new_iff is returned. -ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj) { - assert(is_uncommon_trap_if_pattern(cont_proj, true), "must be a uct if pattern!"); +// This code is also used to clone predicates to clonned loops. +ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, + Deoptimization::DeoptReason reason) { + assert(is_uncommon_trap_if_pattern(cont_proj, reason), "must be a uct if pattern!"); IfNode* iff = cont_proj->in(0)->as_If(); ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con); @@ -1854,57 +1908,84 @@ if (!rgn->is_Region()) { // create a region to guard the call assert(rgn->is_Call(), "must be call uct"); CallNode* call = rgn->as_Call(); + IdealLoopTree* loop = get_loop(call); rgn = new (C, 1) RegionNode(1); - _igvn.set_type(rgn, rgn->bottom_type()); rgn->add_req(uncommon_proj); - set_idom(rgn, idom(uncommon_proj), dom_depth(uncommon_proj)+1); + register_control(rgn, loop, uncommon_proj); _igvn.hash_delete(call); call->set_req(0, rgn); + // When called from beautify_loops() idom is not constructed yet. + if (_idom != NULL) { + set_idom(call, rgn, dom_depth(rgn)); + } } + Node* entry = iff->in(0); + if (new_entry != NULL) { + // Clonning the predicate to new location. + entry = new_entry; + } // Create new_iff - uint iffdd = dom_depth(iff); - IdealLoopTree* lp = get_loop(iff); - IfNode *new_iff = new (C, 2) IfNode(iff->in(0), NULL, iff->_prob, iff->_fcnt); - register_node(new_iff, lp, idom(iff), iffdd); + IdealLoopTree* lp = get_loop(entry); + IfNode *new_iff = new (C, 2) IfNode(entry, NULL, iff->_prob, iff->_fcnt); + register_control(new_iff, lp, entry); Node *if_cont = new (C, 1) IfTrueNode(new_iff); Node *if_uct = new (C, 1) IfFalseNode(new_iff); if (cont_proj->is_IfFalse()) { // Swap Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp; } - register_node(if_cont, lp, new_iff, iffdd); - register_node(if_uct, get_loop(rgn), new_iff, iffdd); - - // if_cont to iff - _igvn.hash_delete(iff); - iff->set_req(0, if_cont); - set_idom(iff, if_cont, dom_depth(iff)); + register_control(if_cont, lp, new_iff); + register_control(if_uct, get_loop(rgn), new_iff); // if_uct to rgn _igvn.hash_delete(rgn); rgn->add_req(if_uct); - Node* ridom = idom(rgn); - Node* nrdom = dom_lca(ridom, new_iff); - set_idom(rgn, nrdom, dom_depth(rgn)); - + // When called from beautify_loops() idom is not constructed yet. + if (_idom != NULL) { + Node* ridom = idom(rgn); + Node* nrdom = dom_lca(ridom, new_iff); + set_idom(rgn, nrdom, dom_depth(rgn)); + } // rgn must have no phis assert(!rgn->as_Region()->has_phi(), "region must have no phis"); + if (new_entry == NULL) { + // Attach if_cont to iff + _igvn.hash_delete(iff); + iff->set_req(0, if_cont); + if (_idom != NULL) { + set_idom(iff, if_cont, dom_depth(iff)); + } + } return if_cont->as_Proj(); } -//------------------------------find_predicate_insertion_point-------------------------- +//--------------------------find_predicate_insertion_point------------------- // Find a good location to insert a predicate -ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c) { - if (start_c == C->root() || !start_c->is_Proj()) +ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason) { + if (start_c == NULL || !start_c->is_Proj()) return NULL; - if (is_uncommon_trap_if_pattern(start_c->as_Proj(), true/*Reason_Predicate*/)) { + if (is_uncommon_trap_if_pattern(start_c->as_Proj(), reason)) { return start_c->as_Proj(); } return NULL; } +//--------------------------find_predicate------------------------------------ +// Find a predicate +Node* PhaseIdealLoop::find_predicate(Node* entry) { + Node* predicate = NULL; + if (UseLoopPredicate) { + predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); + if (predicate != NULL) { // right pattern that can be used by loop predication + assert(entry->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be"); + return entry; + } + } + return NULL; +} + //------------------------------Invariance----------------------------------- // Helper class for loop_predication_impl to compute invariance on the fly and // clone invariants. @@ -2151,6 +2232,11 @@ return false; } + if (loop->_head->unique_ctrl_out()->Opcode() == Op_NeverBranch) { + // do nothing for infinite loops + return false; + } + CountedLoopNode *cl = NULL; if (loop->_head->is_CountedLoop()) { cl = loop->_head->as_CountedLoop(); @@ -2158,40 +2244,22 @@ if (!cl->is_normal_loop()) return false; } - // Too many traps seen? - bool tmt = C->too_many_traps(C->method(), 0, Deoptimization::Reason_predicate); - int tc = C->trap_count(Deoptimization::Reason_predicate); - if (tmt || tc > 0) { - if (TraceLoopPredicate) { - tty->print_cr("too many predicate traps: %d", tc); - C->method()->print(); // which method has too many predicate traps - tty->print_cr(""); - } - return false; - } - LoopNode *lpn = loop->_head->as_Loop(); Node* entry = lpn->in(LoopNode::EntryControl); - ProjNode *predicate_proj = find_predicate_insertion_point(entry); - if (!predicate_proj){ + ProjNode *predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); + if (!predicate_proj) { #ifndef PRODUCT if (TraceLoopPredicate) { tty->print("missing predicate:"); loop->dump_head(); + lpn->dump(1); } #endif return false; } - ConNode* zero = _igvn.intcon(0); set_ctrl(zero, C->root()); - Node *cond_false = new (C, 2) Conv2BNode(zero); - register_new_node(cond_false, C->root()); - ConNode* one = _igvn.intcon(1); - set_ctrl(one, C->root()); - Node *cond_true = new (C, 2) Conv2BNode(one); - register_new_node(cond_true, C->root()); ResourceArea *area = Thread::current()->resource_area(); Invariance invar(area, loop); @@ -2218,7 +2286,7 @@ ProjNode* proj = if_proj_list.pop()->as_Proj(); IfNode* iff = proj->in(0)->as_If(); - if (!is_uncommon_trap_if_pattern(proj)) { + if (!is_uncommon_trap_if_pattern(proj, Deoptimization::Reason_none)) { if (loop->is_loop_exit(iff)) { // stop processing the remaining projs in the list because the execution of them // depends on the condition of "iff" (iff->in(1)). @@ -2242,7 +2310,8 @@ BoolNode* bol = test->as_Bool(); if (invar.is_invariant(bol)) { // Invariant test - new_predicate_proj = create_new_if_for_predicate(predicate_proj); + new_predicate_proj = create_new_if_for_predicate(predicate_proj, NULL, + Deoptimization::Reason_predicate); Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); @@ -2256,8 +2325,15 @@ IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); _igvn.hash_delete(new_predicate_iff); new_predicate_iff->set_req(1, new_predicate_bol); - if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx); - +#ifndef PRODUCT + if (TraceLoopPredicate) { + tty->print("Predicate invariant if%s: %d ", negated ? " negated" : "", new_predicate_iff->_idx); + loop->dump_head(); + } else if (TraceLoopOpts) { + tty->print("Predicate IC "); + loop->dump_head(); + } +#endif } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) { assert(proj->_con == predicate_proj->_con, "must match"); @@ -2281,8 +2357,8 @@ // lower_bound test will dominate the upper bound test and all // cloned or created nodes will use the lower bound test as // their declared control. - ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj); - ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj); + ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate); + ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate); assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); @@ -2311,41 +2387,24 @@ // Fall through into rest of the clean up code which will move // any dependent nodes onto the upper bound test. new_predicate_proj = upper_bound_proj; + +#ifndef PRODUCT + if (TraceLoopOpts && !TraceLoopPredicate) { + tty->print("Predicate RC "); + loop->dump_head(); + } +#endif } else { - // The other proj of the "iff" is a uncommon trap projection, and we can assume - // the other proj will not be executed ("executed" means uct raised). + // Loop variant check (for example, range check in non-counted loop) + // with uncommon trap. continue; } - + assert(new_predicate_proj != NULL, "sanity"); // Success - attach condition (new_predicate_bol) to predicate if invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate - // Eliminate the old if in the loop body - _igvn.hash_delete(iff); - iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true); - - Node* ctrl = new_predicate_proj; // new control - ProjNode* dp = proj; // old control - assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj"); - // Find nodes (depends only on the test) off the surviving projection; - // move them outside the loop with the control of proj_clone - for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { - Node* cd = dp->fast_out(i); // Control-dependent node - if (cd->depends_only_on_test()) { - assert(cd->in(0) == dp, ""); - _igvn.hash_delete(cd); - cd->set_req(0, ctrl); // ctrl, not NULL - set_early_ctrl(cd); - _igvn._worklist.push(cd); - IdealLoopTree *new_loop = get_loop(get_ctrl(cd)); - if (new_loop != loop) { - if (!loop->_child) loop->_body.yank(cd); - if (!new_loop->_child ) new_loop->_body.push(cd); - } - --i; - --imax; - } - } + // Eliminate the old If in the loop body + dominated_by( new_predicate_proj, iff, proj->_con != new_predicate_proj->_con ); hoisted = true; C->set_major_progress();