--- old/src/hotspot/share/opto/loopnode.cpp 2018-05-16 09:40:20.964249170 +0200 +++ new/src/hotspot/share/opto/loopnode.cpp 2018-05-16 09:40:14.778267124 +0200 @@ -1252,9 +1252,7 @@ return l->outer_safepoint(); } -Node* CountedLoopNode::skip_predicates() { - if (is_main_loop()) { - Node* ctrl = skip_strip_mined()->in(LoopNode::EntryControl); +Node* CountedLoopNode::skip_predicates_from_entry(Node* ctrl) { while (ctrl != NULL && ctrl->is_Proj() && ctrl->in(0)->is_If() && ctrl->in(0)->as_If()->proj_out(1-ctrl->as_Proj()->_con)->outcnt() == 1 && ctrl->in(0)->as_If()->proj_out(1-ctrl->as_Proj()->_con)->unique_out()->Opcode() == Op_Halt) { @@ -1263,6 +1261,13 @@ return ctrl; } + +Node* CountedLoopNode::skip_predicates() { + if (is_main_loop()) { + Node* ctrl = skip_strip_mined()->in(LoopNode::EntryControl); + + return skip_predicates_from_entry(ctrl); + } return in(LoopNode::EntryControl); } @@ -2371,6 +2376,13 @@ entry = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); if (entry != NULL) { tty->print(" predicated"); + entry = PhaseIdealLoop::skip_loop_predicates(entry); + } + } + if (UseProfiledLoopPredicate) { + entry = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_profile_predicate); + if (entry != NULL) { + tty->print(" profile_predicated"); } } if (_head->is_CountedLoop()) { @@ -2478,11 +2490,18 @@ if (predicate_proj != NULL ) { // right pattern that can be used by loop predication assert(entry->in(0)->in(1)->in(1)->Opcode() == Op_Opaque1, "must be"); useful_predicates.push(entry->in(0)->in(1)->in(1)); // good one - entry = entry->in(0)->in(0); + entry = skip_loop_predicates(entry); } predicate_proj = find_predicate(entry); // Predicate if (predicate_proj != NULL ) { useful_predicates.push(entry->in(0)->in(1)->in(1)); // good one + entry = skip_loop_predicates(entry); + } + if (UseProfiledLoopPredicate) { + predicate_proj = find_predicate(entry); // Predicate + if (predicate_proj != NULL ) { + useful_predicates.push(entry->in(0)->in(1)->in(1)); // good one + } } } @@ -4165,12 +4184,33 @@ // which can inhibit range check elimination. if (least != early) { Node* ctrl_out = least->unique_ctrl_out(); - if (ctrl_out && ctrl_out->is_Loop() && - least == ctrl_out->in(LoopNode::EntryControl) && - (ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop())) { - Node* least_dom = idom(least); - if (get_loop(least_dom)->is_member(get_loop(least))) { - least = least_dom; + if (ctrl_out && ctrl_out->is_CountedLoop() && + least == ctrl_out->in(LoopNode::EntryControl)) { + Node* new_ctrl = least; + // Move the node above predicates so a following pass of loop + // predication doesn't hoist a predicate that depends on it + // above that node. + if (find_predicate_insertion_point(new_ctrl, Deoptimization::Reason_loop_limit_check) != NULL) { + new_ctrl = new_ctrl->in(0)->in(0); + assert(is_dominator(early, new_ctrl), "least != early so we can move up the dominator tree"); + } + if (find_predicate_insertion_point(new_ctrl, Deoptimization::Reason_profile_predicate) != NULL) { + Node* c = new_ctrl->in(0)->in(0); + assert(is_dominator(early, c), "least != early so we can move up the dominator tree"); + new_ctrl = c; + } + if (find_predicate_insertion_point(new_ctrl, Deoptimization::Reason_predicate) != NULL) { + Node* c = new_ctrl->in(0)->in(0); + assert(is_dominator(early, c), "least != early so we can move up the dominator tree"); + new_ctrl = c; + } + if (new_ctrl != ctrl_out) { + least = new_ctrl; + } else if (ctrl_out->is_CountedLoop() || ctrl_out->is_OuterStripMinedLoop()) { + Node* least_dom = idom(least); + if (get_loop(least_dom)->is_member(get_loop(least))) { + least = least_dom; + } } } }