--- hotspot/src/share/vm/opto/loopTransform.cpp Wed Jun 1 12:36:45 2011 +++ hotspot/src/share/vm/opto/loopTransform.cpp Wed Jun 1 12:36:45 2011 @@ -824,13 +824,23 @@ //------------------------------clone_up_backedge_goo-------------------------- // If Node n lives in the back_ctrl block and cannot float, we clone a private // version of n in preheader_ctrl block and return that, otherwise return n. -Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n ) { +Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones ) { if( get_ctrl(n) != back_ctrl ) return n; + // Only visit once + if (visited.test_set(n->_idx)) { + Node *x = clones.find(n->_idx); + if (x != NULL) + return x; + return n; + } + Node *x = NULL; // If required, a clone of 'n' // Check for 'n' being pinned in the backedge. if( n->in(0) && n->in(0) == back_ctrl ) { + assert(clones.find(n->_idx) == NULL, "dead loop"); x = n->clone(); // Clone a copy of 'n' to preheader + clones.push(x, n->_idx); x->set_req( 0, preheader_ctrl ); // Fix x's control input to preheader } @@ -838,10 +848,13 @@ // If there are no changes we can just return 'n', otherwise // we need to clone a private copy and change it. for( uint i = 1; i < n->req(); i++ ) { - Node *g = clone_up_backedge_goo( back_ctrl, preheader_ctrl, n->in(i) ); + Node *g = clone_up_backedge_goo( back_ctrl, preheader_ctrl, n->in(i), visited, clones ); if( g != n->in(i) ) { - if( !x ) + if( !x ) { + assert(clones.find(n->_idx) == NULL, "dead loop"); x = n->clone(); + clones.push(x, n->_idx); + } x->set_req(i, g); } } @@ -960,6 +973,9 @@ post_head->set_req(LoopNode::EntryControl, zer_taken); set_idom(post_head, zer_taken, dd_main_exit); + Arena *a = Thread::current()->resource_area(); + VectorSet visited(a); + Node_Stack clones(a, main_head->back_control()->outcnt()); // Step A3: Make the fall-in values to the post-loop come from the // fall-out values of the main-loop. for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) { @@ -968,7 +984,8 @@ Node *post_phi = old_new[main_phi->_idx]; Node *fallmain = clone_up_backedge_goo(main_head->back_control(), post_head->init_control(), - main_phi->in(LoopNode::LoopBackControl)); + main_phi->in(LoopNode::LoopBackControl), + visited, clones); _igvn.hash_delete(post_phi); post_phi->set_req( LoopNode::EntryControl, fallmain ); } @@ -1032,6 +1049,8 @@ main_head->set_req(LoopNode::EntryControl, min_taken); set_idom(main_head, min_taken, dd_main_head); + visited.Clear(); + clones.clear(); // Step B3: Make the fall-in values to the main-loop come from the // fall-out values of the pre-loop. for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) { @@ -1040,7 +1059,8 @@ Node *pre_phi = old_new[main_phi->_idx]; Node *fallpre = clone_up_backedge_goo(pre_head->back_control(), main_head->init_control(), - pre_phi->in(LoopNode::LoopBackControl)); + pre_phi->in(LoopNode::LoopBackControl), + visited, clones); _igvn.hash_delete(main_phi); main_phi->set_req( LoopNode::EntryControl, fallpre ); } --- hotspot/src/share/vm/opto/loopnode.hpp Wed Jun 1 12:36:45 2011 +++ hotspot/src/share/vm/opto/loopnode.hpp Wed Jun 1 12:36:45 2011 @@ -843,7 +843,7 @@ void insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ); // If Node n lives in the back_ctrl block, we clone a private version of n // in preheader_ctrl block and return that, otherwise return n. - Node *clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n ); + Node *clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones ); // Take steps to maximally unroll the loop. Peel any odd iterations, then // unroll to do double iterations. The next round of major loop transforms --- hotspot/src/share/vm/opto/macro.cpp Wed Jun 1 12:36:46 2011 +++ hotspot/src/share/vm/opto/macro.cpp Wed Jun 1 12:36:46 2011 @@ -391,13 +391,9 @@ } } // Check if an appropriate new value phi already exists. - Node* new_phi = NULL; - uint size = value_phis->size(); - for (uint i=0; i < size; i++) { - if ( mem->_idx == value_phis->index_at(i) ) { - return value_phis->node_at(i); - } - } + Node* new_phi = value_phis->find(mem->_idx); + if (new_phi != NULL) + return new_phi; if (level <= 0) { return NULL; // Give up: phi tree too deep --- hotspot/src/share/vm/opto/node.cpp Wed Jun 1 12:36:46 2011 +++ hotspot/src/share/vm/opto/node.cpp Wed Jun 1 12:36:46 2011 @@ -2012,6 +2012,16 @@ _inode_top = _inodes + old_top; // restore _top } +// Node_Stack is used to map nodes. +Node* Node_Stack::find(uint idx) const { + uint sz = size(); + for (uint i=0; i < sz; i++) { + if (idx == index_at(i) ) + return node_at(i); + } + return NULL; +} + //============================================================================= uint TypeNode::size_of() const { return sizeof(*this); } #ifndef PRODUCT --- hotspot/src/share/vm/opto/node.hpp Wed Jun 1 12:36:47 2011 +++ hotspot/src/share/vm/opto/node.hpp Wed Jun 1 12:36:47 2011 @@ -1463,6 +1463,9 @@ bool is_nonempty() const { return (_inode_top >= _inodes); } bool is_empty() const { return (_inode_top < _inodes); } void clear() { _inode_top = _inodes - 1; } // retain storage + + // Node_Stack is used to map nodes. + Node* find(uint idx) const; }; --- hotspot/src/share/vm/opto/cfgnode.cpp Wed Jul 20 14:06:31 2011 +++ hotspot/src/share/vm/opto/cfgnode.cpp Wed Jul 20 14:06:31 2011 @@ -1349,17 +1349,9 @@ static void split_once(PhaseIterGVN *igvn, Node *phi, Node *val, Node *n, Node *newn) { igvn->hash_delete(n); // Remove from hash before hacking edges - Node* predicate_proj = NULL; uint j = 1; for (uint i = phi->req()-1; i > 0; i--) { if (phi->in(i) == val) { // Found a path with val? - if (n->is_Region()) { - Node* proj = PhaseIdealLoop::find_predicate(n->in(i)); - if (proj != NULL) { - assert(predicate_proj == NULL, "only one predicate entry expected"); - predicate_proj = proj; - } - } // Add to NEW Region/Phi, no DU info newn->set_req( j++, n->in(i) ); // Remove from OLD Region/Phi @@ -1371,11 +1363,6 @@ // entire Region/Phi conglomerate has been hacked as a single huge transform. igvn->register_new_node_with_optimizer( newn ); - // Clone loop predicates - if (predicate_proj != NULL) { - newn = igvn->clone_loop_predicates(predicate_proj, newn, !n->is_CountedLoop()); - } - // Now I can point to the new node. n->add_req(newn); igvn->_worklist.push(n); @@ -1404,13 +1391,18 @@ Node *val = phi->in(i); // Constant to split for uint hit = 0; // Number of times it occurs + Node *r = phi->region(); for( ; i < phi->req(); i++ ){ // Count occurrences of constant Node *n = phi->in(i); if( !n ) return NULL; if( phase->type(n) == Type::TOP ) return NULL; - if( phi->in(i) == val ) + if( phi->in(i) == val ) { hit++; + if (PhaseIdealLoop::find_predicate(r->in(i)) != NULL) { + return NULL; // don't split loop entry path + } + } } if( hit <= 1 || // Make sure we find 2 or more @@ -1420,7 +1412,6 @@ // Now start splitting out the flow paths that merge the same value. // Split first the RegionNode. PhaseIterGVN *igvn = phase->is_IterGVN(); - Node *r = phi->region(); RegionNode *newr = new (phase->C, hit+1) RegionNode(hit+1); split_once(igvn, phi, val, r, newr); --- hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 20 14:06:32 2011 +++ hotspot/src/share/vm/opto/ifnode.cpp Wed Jul 20 14:06:31 2011 @@ -255,6 +255,14 @@ predicate_x = predicate_proj; } } + if (predicate_c != NULL && (req_c > 1)) { + assert(predicate_x == NULL, "only one predicate entry expected"); + predicate_c = NULL; // Do not clone predicate below merge point + } + if (predicate_x != NULL && ((len - req_c) > 2)) { + assert(predicate_c == NULL, "only one predicate entry expected"); + predicate_x = NULL; // Do not clone predicate below merge point + } // Register the new RegionNodes but do not transform them. Cannot // transform until the entire Region/Phi conglomerate has been hacked --- hotspot/src/share/vm/opto/loopPredicate.cpp Wed Jul 20 14:06:32 2011 +++ hotspot/src/share/vm/opto/loopPredicate.cpp Wed Jul 20 14:06:32 2011 @@ -327,81 +327,20 @@ return new_predicate_proj; } -//--------------------------move_predicate----------------------- -// Cut predicate from old place and move it to new. -ProjNode* PhaseIdealLoop::move_predicate(ProjNode* predicate_proj, Node* new_entry, - Deoptimization::DeoptReason reason, - PhaseIdealLoop* loop_phase, - PhaseIterGVN* igvn) { - assert(new_entry != NULL, "must be"); - assert(predicate_proj->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be"); - IfNode* iff = predicate_proj->in(0)->as_If(); - Node* old_entry = iff->in(0); - // Cut predicate from old place. - Node* old = predicate_proj; - igvn->_worklist.push(old); - for (DUIterator_Last imin, i = old->last_outs(imin); i >= imin;) { - Node* use = old->last_out(i); // for each use... - igvn->hash_delete(use); - igvn->_worklist.push(use); - // Update use-def info - uint uses_found = 0; - for (uint j = 0; j < use->req(); j++) { - if (use->in(j) == old) { - use->set_req(j, old_entry); - uses_found++; - if (loop_phase != NULL) { - if (use->is_CFG()) { - // When called from beautify_loops() idom is not constructed yet. - if (loop_phase->_idom != NULL) - loop_phase->set_idom(use, old_entry, loop_phase->dom_depth(use)); - } else { - loop_phase->set_ctrl(use, old_entry); - } - } - } - } - i -= uses_found; // we deleted 1 or more copies of this edge - } - - // Move predicate. - igvn->hash_delete(iff); - iff->set_req(0, new_entry); - igvn->_worklist.push(iff); - - if (loop_phase != NULL) { - // Fix up idom and ctrl. - loop_phase->set_ctrl(iff->in(1), new_entry); - loop_phase->set_ctrl(iff->in(1)->in(1), new_entry); - // When called from beautify_loops() idom is not constructed yet. - if (loop_phase->_idom != NULL) - loop_phase->set_idom(iff, new_entry, loop_phase->dom_depth(iff)); - } - - return predicate_proj; -} - //--------------------------clone_loop_predicates----------------------- // Interface from IGVN Node* PhaseIterGVN::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { - return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, false, clone_limit_check, NULL, this); + return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, clone_limit_check, NULL, this); } -Node* PhaseIterGVN::move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { - return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, true, clone_limit_check, NULL, this); -} // Interface from PhaseIdealLoop Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { - return clone_loop_predicates(old_entry, new_entry, false, clone_limit_check, this, &this->_igvn); + return clone_loop_predicates(old_entry, new_entry, clone_limit_check, this, &this->_igvn); } -Node* PhaseIdealLoop::move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { - return clone_loop_predicates(old_entry, new_entry, true, clone_limit_check, this, &this->_igvn); -} // Clone loop predicates to cloned loops (peeled, unswitched, split_if). Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, - bool move_predicates, bool clone_limit_check, PhaseIdealLoop* loop_phase, PhaseIterGVN* igvn) { @@ -424,20 +363,13 @@ if (UseLoopPredicate) { ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); if (predicate_proj != NULL) { // right pattern that can be used by loop predication - if (move_predicates) { - new_entry = move_predicate(predicate_proj, new_entry, - Deoptimization::Reason_predicate, - loop_phase, igvn); - assert(new_entry == predicate_proj, "old predicate fall through projection"); - } else { - // clone predicate - new_entry = clone_predicate(predicate_proj, new_entry, - Deoptimization::Reason_predicate, - loop_phase, igvn); - assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate"); - } + // clone predicate + new_entry = clone_predicate(predicate_proj, new_entry, + Deoptimization::Reason_predicate, + loop_phase, igvn); + assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate"); if (TraceLoopPredicate) { - tty->print_cr("Loop Predicate %s: ", move_predicates ? "moved" : "cloned"); + tty->print("Loop Predicate cloned: "); debug_only( new_entry->in(0)->dump(); ) } } @@ -446,19 +378,12 @@ // Clone loop limit check last to insert it before loop. // Don't clone a limit check which was already finalized // for this counted loop (only one limit check is needed). - if (move_predicates) { - new_entry = move_predicate(limit_check_proj, new_entry, - Deoptimization::Reason_loop_limit_check, - loop_phase, igvn); - assert(new_entry == limit_check_proj, "old limit check fall through projection"); - } else { - new_entry = clone_predicate(limit_check_proj, new_entry, - Deoptimization::Reason_loop_limit_check, - loop_phase, igvn); - assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone limit check"); - } + new_entry = clone_predicate(limit_check_proj, new_entry, + Deoptimization::Reason_loop_limit_check, + loop_phase, igvn); + assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone limit check"); if (TraceLoopLimitCheck) { - tty->print_cr("Loop Limit Check %s: ", move_predicates ? "moved" : "cloned"); + tty->print("Loop Limit Check cloned: "); debug_only( new_entry->in(0)->dump(); ) } } @@ -465,26 +390,6 @@ return new_entry; } -//--------------------------eliminate_loop_predicates----------------------- -void PhaseIdealLoop::eliminate_loop_predicates(Node* entry) { - if (LoopLimitCheck) { - Node* predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); - if (predicate != NULL) { - entry = entry->in(0)->in(0); - } - } - if (UseLoopPredicate) { - ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); - if (predicate_proj != NULL) { // right pattern that can be used by loop predication - Node* n = entry->in(0)->in(1)->in(1); - assert(n->Opcode()==Op_Opaque1, "must be"); - // Remove Opaque1 node from predicates list. - // IGVN will remove this predicate check. - _igvn.replace_node(n, n->in(1)); - } - } -} - //--------------------------skip_loop_predicates------------------------------ // Skip related predicates. Node* PhaseIdealLoop::skip_loop_predicates(Node* entry) { --- hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 20 14:06:33 2011 +++ hotspot/src/share/vm/opto/loopTransform.cpp Wed Jul 20 14:06:32 2011 @@ -509,14 +509,13 @@ // backedges) and then map to the new peeled iteration. This leaves // the pre-loop with only 1 user (the new peeled iteration), but the // peeled-loop backedge has 2 users. - Node* new_exit_value = old_new[head->in(LoopNode::LoopBackControl)->_idx]; - new_exit_value = move_loop_predicates(entry, new_exit_value, !counted_loop); + Node* new_entry = old_new[head->in(LoopNode::LoopBackControl)->_idx]; _igvn.hash_delete(head); - head->set_req(LoopNode::EntryControl, new_exit_value); + head->set_req(LoopNode::EntryControl, new_entry); for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { Node* old = head->fast_out(j); if (old->in(0) == loop->_head && old->req() == 3 && old->is_Phi()) { - new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx]; + Node* new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx]; if (!new_exit_value ) // Backedge value is ALSO loop invariant? // Then loop body backedge value remains the same. new_exit_value = old->in(LoopNode::LoopBackControl); --- hotspot/src/share/vm/opto/loopUnswitch.cpp Wed Jul 20 14:06:33 2011 +++ hotspot/src/share/vm/opto/loopUnswitch.cpp Wed Jul 20 14:06:33 2011 @@ -255,7 +255,7 @@ _igvn._worklist.push(head); // Slow (false) control - Node* ifslow_pred = move_loop_predicates(entry, ifslow, !counted_loop); + Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); LoopNode* slow_head = old_new[head->_idx]->as_Loop(); _igvn.hash_delete(slow_head); slow_head->set_req(LoopNode::EntryControl, ifslow_pred); --- hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 20 14:06:34 2011 +++ hotspot/src/share/vm/opto/loopnode.cpp Wed Jul 20 14:06:33 2011 @@ -1167,9 +1167,8 @@ outer = igvn.register_new_node_with_optimizer(outer, _head); phase->set_created_loop_node(); - Node* pred = phase->clone_loop_predicates(ctl, outer, true); // Outermost loop falls into '_head' loop - _head->set_req(LoopNode::EntryControl, pred); + _head->set_req(LoopNode::EntryControl, outer); _head->del_req(outer_idx); // Split all the Phis up between '_head' loop and 'outer' loop. for (DUIterator_Fast jmax, j = _head->fast_outs(jmax); j < jmax; j++) { --- hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 20 14:06:34 2011 +++ hotspot/src/share/vm/opto/loopnode.hpp Wed Jul 20 14:06:34 2011 @@ -877,19 +877,13 @@ Deoptimization::DeoptReason reason, PhaseIdealLoop* loop_phase, PhaseIterGVN* igvn); - static ProjNode* move_predicate(ProjNode* predicate_proj, Node* new_entry, - Deoptimization::DeoptReason reason, - PhaseIdealLoop* loop_phase, - PhaseIterGVN* igvn); + static Node* clone_loop_predicates(Node* old_entry, Node* new_entry, - bool move_predicates, bool clone_limit_check, PhaseIdealLoop* loop_phase, PhaseIterGVN* igvn); Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check); - Node* move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check); - void eliminate_loop_predicates(Node* entry); static Node* skip_loop_predicates(Node* entry); // Find a good location to insert a predicate --- hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 20 14:06:35 2011 +++ hotspot/src/share/vm/opto/phaseX.hpp Wed Jul 20 14:06:34 2011 @@ -473,7 +473,6 @@ // Clone loop predicates. Defined in loopTransform.cpp. Node* clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check); - Node* move_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check); // Create a new if below new_entry for the predicate to be cloned ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, Deoptimization::DeoptReason reason); --- hotspot/src/share/vm/opto/ifnode.cpp Mon Jul 25 19:19:11 2011 +++ hotspot/src/share/vm/opto/ifnode.cpp Mon Jul 25 19:19:11 2011 @@ -1009,6 +1009,13 @@ int prev_op = prev_dom->Opcode(); Node *top = igvn->C->top(); // Shortcut to top + // Loop predicates may have depending checks which should not + // be skipped. For example, range check predicate has two checks + // for lower and upper bounds. + ProjNode* unc_proj = proj_out(1 - prev_dom->as_Proj()->_con)->as_Proj(); + if (PhaseIdealLoop::is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate)) + prev_dom = idom; + // Now walk the current IfNode's projections. // Loop ends when 'this' has no more uses. for (DUIterator_Last imin, i = last_outs(imin); i >= imin; --i) { @@ -1019,9 +1026,9 @@ // or TOP if the dominating projection is of opposite type. // Data-target will be used as the new control edge for the non-CFG // nodes like Casts and Loads. - Node *data_target = (ifp->Opcode() == prev_op ) ? prev_dom : top; + Node *data_target = (ifp->Opcode() == prev_op) ? prev_dom : top; // Control-target is just the If's immediate dominator or TOP. - Node *ctrl_target = (ifp->Opcode() == prev_op ) ? idom : top; + Node *ctrl_target = (ifp->Opcode() == prev_op) ? idom : top; // For each child of an IfTrue/IfFalse projection, reroute. // Loop ends when projection has no more uses. --- hotspot/src/share/vm/opto/loopPredicate.cpp Mon Jul 25 19:19:11 2011 +++ hotspot/src/share/vm/opto/loopPredicate.cpp Mon Jul 25 19:19:11 2011 @@ -817,6 +817,10 @@ cl = head->as_CountedLoop(); // do nothing for iteration-splitted loops if (!cl->is_normal_loop()) return false; + // Avoid RCE if Counted loop's test is '!='. + BoolTest::mask bt = cl->loopexit()->test_trip(); + if (bt != BoolTest::lt && bt != BoolTest::gt) + cl = NULL; } Node* entry = head->in(LoopNode::EntryControl); @@ -958,7 +962,7 @@ if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); // Test the upper bound - Node* upper_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, true); + Node* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true); IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); _igvn.hash_delete(upper_bound_iff); upper_bound_iff->set_req(1, upper_bound_bol); --- hotspot/src/share/vm/opto/loopnode.hpp Mon Jul 25 19:19:12 2011 +++ hotspot/src/share/vm/opto/loopnode.hpp Mon Jul 25 19:19:12 2011 @@ -1009,7 +1009,7 @@ Node *has_local_phi_input( Node *n ); // Mark an IfNode as being dominated by a prior test, // without actually altering the CFG (and hence IDOM info). - void dominated_by( Node *prevdom, Node *iff, bool flip = false ); + void dominated_by( Node *prevdom, Node *iff, bool flip = false, bool exclude_loop_predicate = false ); // Split Node 'n' through merge point Node *split_thru_region( Node *n, Node *region ); --- hotspot/src/share/vm/opto/loopopts.cpp Mon Jul 25 19:19:12 2011 +++ hotspot/src/share/vm/opto/loopopts.cpp Mon Jul 25 19:19:12 2011 @@ -194,7 +194,7 @@ // Replace the dominated test with an obvious true or false. Place it on the // IGVN worklist for later cleanup. Move control-dependent data Nodes on the // live path up to the dominating control. -void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip ) { +void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exclude_loop_predicate ) { #ifndef PRODUCT if (VerifyLoopOptimizations && PrintOpto) tty->print_cr("dominating test"); #endif @@ -228,7 +228,16 @@ // Make control-dependent data Nodes on the live path (path that will remain // once the dominated IF is removed) become control-dependent on the // dominating projection. - Node* dp = ((IfNode*)iff)->proj_out(pop == Op_IfTrue); + Node* dp = iff->as_If()->proj_out(pop == Op_IfTrue); + + // Loop predicates may have depending checks which should not + // be skipped. For example, range check predicate has two checks + // for lower and upper bounds. + ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp->as_Proj()->_con)->as_Proj(); + if (exclude_loop_predicate && + is_uncommon_trap_proj(unc_proj, Deoptimization::Reason_predicate)) + return; + IdealLoopTree *old_loop = get_loop(dp); for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { @@ -859,7 +868,7 @@ // Replace the dominated test with an obvious true or false. // Place it on the IGVN worklist for later cleanup. C->set_major_progress(); - dominated_by( prevdom, n ); + dominated_by( prevdom, n, false, true ); #ifndef PRODUCT if( VerifyLoopOptimizations ) verify(); #endif