mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 09:04:41 +02:00
7008866: Missing loop predicate for loop with multiple entries
Add predicates when loop head bytecode is parsed instead of when back branch bytecode is parsed. Reviewed-by: never
This commit is contained in:
parent
a3e259c335
commit
3de260da41
15 changed files with 703 additions and 480 deletions
|
@ -205,6 +205,8 @@ Node* IdealLoopTree::reassociate_add_sub(Node* n1, PhaseIdealLoop *phase) {
|
|||
}
|
||||
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 @@ void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
|
|||
// 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 @@ Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ct
|
|||
// 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 @@ bool IdealLoopTree::is_invariant(Node* n) const {
|
|||
//------------------------------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 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
|
|||
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 @@ void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
|
|||
// 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_unroll( IdealLoopTree *loop, Node_List &old_new, bool ad
|
|||
|
||||
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 @@ bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale,
|
|||
// 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 @@ void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
|
|||
// 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 @@ void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
|
|||
// 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 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
|
|||
//------------------------------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 @@ bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new )
|
|||
|
||||
// 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 @@ bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new )
|
|||
}
|
||||
|
||||
// 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 @@ bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_pred
|
|||
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 @@ bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_pred
|
|||
// 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 @@ bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reaso
|
|||
}
|
||||
|
||||
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 @@ bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reaso
|
|||
//
|
||||
// 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 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
// 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 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
|
|||
// 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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue