--- old/src/hotspot/share/opto/loopPredicate.cpp 2018-11-06 13:57:30.554396254 +0100 +++ new/src/hotspot/share/opto/loopPredicate.cpp 2018-11-06 13:57:21.911376947 +0100 @@ -370,9 +370,9 @@ // Clone loop predicates to cloned loops (peeled, unswitched, split_if). Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, - bool clone_limit_check, - PhaseIdealLoop* loop_phase, - PhaseIterGVN* igvn) { + bool clone_limit_check, + PhaseIdealLoop* loop_phase, + PhaseIterGVN* igvn) { #ifdef ASSERT if (new_entry == NULL || !(new_entry->is_Proj() || new_entry->is_Region() || new_entry->is_SafePoint())) { if (new_entry != NULL) @@ -385,7 +385,7 @@ ProjNode* limit_check_proj = NULL; limit_check_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (limit_check_proj != NULL) { - entry = entry->in(0)->in(0); + entry = skip_loop_predicates(entry); } ProjNode* profile_predicate_proj = NULL; ProjNode* predicate_proj = NULL; @@ -467,7 +467,7 @@ Node* predicate = NULL; predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (predicate != NULL) { - entry = entry->in(0)->in(0); + entry = skip_loop_predicates(entry); } if (UseProfiledLoopPredicate) { predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_profile_predicate); @@ -1354,7 +1354,7 @@ // Loop limit check predicate should be near the loop. loop_limit_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (loop_limit_proj != NULL) { - entry = loop_limit_proj->in(0)->in(0); + entry = skip_loop_predicates(loop_limit_proj); } bool has_profile_predicates = false; profile_predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_profile_predicate); --- old/src/hotspot/share/opto/loopTransform.cpp 2018-11-06 13:57:39.362415929 +0100 +++ new/src/hotspot/share/opto/loopTransform.cpp 2018-11-06 13:57:30.654396478 +0100 @@ -1200,7 +1200,7 @@ Node* predicate = NULL; predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (predicate != NULL) { - entry = entry->in(0)->in(0); + entry = skip_loop_predicates(entry); } Node* profile_predicate = NULL; if (UseProfiledLoopPredicate) { --- old/src/hotspot/share/opto/loopnode.cpp 2018-11-06 13:57:47.979435178 +0100 +++ new/src/hotspot/share/opto/loopnode.cpp 2018-11-06 13:57:39.478416189 +0100 @@ -324,6 +324,31 @@ return outer_ilt; } +void PhaseIdealLoop::insert_loop_limit_check(Node* init_control, Node* cmp_limit, Node* bol) { + Node* new_predicate_proj = create_new_if_for_predicate(init_control->as_Proj(), NULL, + Deoptimization::Reason_loop_limit_check, + Op_If); + Node* iff = new_predicate_proj->in(0); + assert(iff->Opcode() == Op_If, "bad graph shape"); + Node* conv = iff->in(1); + assert(conv->Opcode() == Op_Conv2B, "bad graph shape"); + Node* opaq = conv->in(1); + assert(opaq->Opcode() == Op_Opaque1, "bad graph shape"); + cmp_limit = _igvn.register_new_node_with_optimizer(cmp_limit); + bol = _igvn.register_new_node_with_optimizer(bol); + set_subtree_ctrl(bol); + _igvn.replace_input_of(iff, 1, bol); + +#ifndef PRODUCT + // report that the loop predication has been actually performed + // for this loop + if (TraceLoopLimitCheck) { + tty->print_cr("Counted Loop Limit Check generated:"); + debug_only( bol->dump(2); ) + } +#endif +} + //------------------------------is_counted_loop-------------------------------- bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*& loop) { PhaseGVN *gvn = &_igvn; @@ -540,7 +565,7 @@ return false; // cyclic loop or this loop trips only once } - if (phi_incr != NULL) { + if (phi_incr != NULL && bt != BoolTest::ne) { // check if there is a possiblity of IV overflowing after the first increment if (stride_con > 0) { if (init_t->_hi > max_jint - stride_con) { @@ -631,28 +656,60 @@ cmp_limit = new CmpINode(limit, _igvn.intcon(min_jint - stride_m)); bol = new BoolNode(cmp_limit, BoolTest::ge); } - cmp_limit = _igvn.register_new_node_with_optimizer(cmp_limit); - bol = _igvn.register_new_node_with_optimizer(bol); - set_subtree_ctrl(bol); - - // Replace condition in original predicate but preserve Opaque node - // so that previous predicates could be found. - assert(check_iff->in(1)->Opcode() == Op_Conv2B && - check_iff->in(1)->in(1)->Opcode() == Op_Opaque1, ""); - Node* opq = check_iff->in(1)->in(1); - _igvn.replace_input_of(opq, 1, bol); - // Update ctrl. - set_ctrl(opq, check_iff->in(0)); - set_ctrl(check_iff->in(1), check_iff->in(0)); -#ifndef PRODUCT - // report that the loop predication has been actually performed - // for this loop - if (TraceLoopLimitCheck) { - tty->print_cr("Counted Loop Limit Check generated:"); - debug_only( bol->dump(2); ) - } + insert_loop_limit_check(init_control, cmp_limit, bol); + } + + // Now we need to canonicalize loop condition. + if (bt == BoolTest::ne) { + assert(stride_con == 1 || stride_con == -1, "simple increment only"); + if (stride_con > 0 && init_t->_hi < limit_t->_lo) { + // 'ne' can be replaced with 'lt' only when init < limit. + bt = BoolTest::lt; + } else if (stride_con < 0 && init_t->_lo > limit_t->_hi) { + // 'ne' can be replaced with 'gt' only when init > limit. + bt = BoolTest::gt; + } else { + ProjNode *limit_check_proj = find_predicate_insertion_point(init_control, Deoptimization::Reason_loop_limit_check); + if (!limit_check_proj) { + // The limit check predicate is not generated if this method trapped here before. +#ifdef ASSERT + if (TraceLoopLimitCheck) { + tty->print("missing loop limit check:"); + loop->dump_head(); + x->dump(1); + } #endif + return false; + } + IfNode* check_iff = limit_check_proj->in(0)->as_If(); + + if (!is_dominator(get_ctrl(limit), check_iff->in(0)) || + !is_dominator(get_ctrl(init_trip), check_iff->in(0))) { + return false; + } + + Node* cmp_limit; + Node* bol; + + if (stride_con > 0) { + cmp_limit = new CmpINode(init_trip, limit); + bol = new BoolNode(cmp_limit, BoolTest::lt); + } else { + cmp_limit = new CmpINode(init_trip, limit); + bol = new BoolNode(cmp_limit, BoolTest::gt); + } + + insert_loop_limit_check(init_control, cmp_limit, bol); + + if (stride_con > 0) { + // 'ne' can be replaced with 'lt' only when init < limit. + bt = BoolTest::lt; + } else if (stride_con < 0) { + // 'ne' can be replaced with 'gt' only when init > limit. + bt = BoolTest::gt; + } + } } if (phi_incr != NULL) { @@ -668,17 +725,6 @@ limit = gvn->transform(new AddINode(limit, stride)); } - // Now we need to canonicalize loop condition. - if (bt == BoolTest::ne) { - assert(stride_con == 1 || stride_con == -1, "simple increment only"); - // 'ne' can be replaced with 'lt' only when init < limit. - if (stride_con > 0 && init_t->_hi < limit_t->_lo) - bt = BoolTest::lt; - // 'ne' can be replaced with 'gt' only when init > limit. - if (stride_con < 0 && init_t->_lo > limit_t->_hi) - bt = BoolTest::gt; - } - if (incl_limit) { // The limit check guaranties that 'limit <= (max_jint - stride)' so // we can convert 'i <= limit' to 'i < limit+1' since stride != 0. @@ -2404,7 +2450,7 @@ Node* predicate = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); if (predicate != NULL ) { tty->print(" limit_check"); - entry = entry->in(0)->in(0); + entry = PhaseIdealLoop::skip_loop_predicates(entry); } if (UseLoopPredicate) { entry = PhaseIdealLoop::find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); --- old/src/hotspot/share/opto/loopnode.hpp 2018-11-06 13:57:56.683454621 +0100 +++ new/src/hotspot/share/opto/loopnode.hpp 2018-11-06 13:57:48.107435464 +0100 @@ -749,6 +749,7 @@ LoopNode* outer_main_head, uint dd_main_head); Node* update_skeleton_predicate(Node* iff, Node* value, Node* predicate = NULL, Node* uncommon_proj = NULL, Node* current_proj = NULL, IdealLoopTree* outer_loop = NULL, Node* prev_proj = NULL); + void insert_loop_limit_check(Node* init_control, Node* cmp_limit, Node* bol); public: