# HG changeset patch # User roland # Date 1530521086 -7200 # Node ID c98bf5aa35c56139c522e4ef2a8fe9f0ddc1014a # Parent c418c173158e2a284e833bbf82536851dcaf780f 8205515: assert(opcode == Op_RangeCheck) failed: no other if variant here Reviewed-by: thartmann, kvn diff -r c418c173158e -r c98bf5aa35c5 src/hotspot/share/opto/ifnode.cpp --- a/src/hotspot/share/opto/ifnode.cpp Mon Jul 02 13:11:41 2018 +0200 +++ b/src/hotspot/share/opto/ifnode.cpp Mon Jul 02 10:44:46 2018 +0200 @@ -1490,7 +1490,8 @@ // 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 (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL) { + if (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL || + unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_profile_predicate) != NULL) { prev_dom = idom; } diff -r c418c173158e -r c98bf5aa35c5 src/hotspot/share/opto/loopPredicate.cpp --- a/src/hotspot/share/opto/loopPredicate.cpp Mon Jul 02 13:11:41 2018 +0200 +++ b/src/hotspot/share/opto/loopPredicate.cpp Mon Jul 02 10:44:46 2018 +0200 @@ -1056,7 +1056,9 @@ stack.push(in, 1); break; } else if (in->is_IfProj() && - in->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) { + in->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none) && + (in->in(0)->Opcode() == Op_If || + in->in(0)->Opcode() == Op_RangeCheck)) { if (pf.to(in) * loop_trip_cnt >= 1) { stack.push(in, 1); } @@ -1281,7 +1283,7 @@ Node* n = skip_loop_predicates(entry); // Check if predicates were already added to the profile predicate // block - if (n != entry->in(0)->in(0)) { + if (n != entry->in(0)->in(0) || n->outcnt() != 1) { has_profile_predicates = true; } entry = n; diff -r c418c173158e -r c98bf5aa35c5 src/hotspot/share/opto/loopnode.cpp --- a/src/hotspot/share/opto/loopnode.cpp Mon Jul 02 13:11:41 2018 +0200 +++ b/src/hotspot/share/opto/loopnode.cpp Mon Jul 02 10:44:46 2018 +0200 @@ -4224,34 +4224,34 @@ // which can inhibit range check elimination. if (least != early) { Node* ctrl_out = least->unique_ctrl_out(); - if (ctrl_out && ctrl_out->is_CountedLoop() && + if (ctrl_out && ctrl_out->is_Loop() && least == ctrl_out->in(LoopNode::EntryControl)) { + // Move the node above predicates as far up as possible so a + // following pass of loop predication doesn't hoist a predicate + // that depends on it above that node. 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) { + for (;;) { + if (!new_ctrl->is_Proj()) { + break; + } + CallStaticJavaNode* call = new_ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none); + if (call == NULL) { + break; + } + int req = call->uncommon_trap_request(); + Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); + if (trap_reason != Deoptimization::Reason_loop_limit_check && + trap_reason != Deoptimization::Reason_predicate && + trap_reason != Deoptimization::Reason_profile_predicate) { + break; + } Node* c = new_ctrl->in(0)->in(0); - assert(is_dominator(early, c), "least != early so we can move up the dominator tree"); + if (is_dominator(c, early) && c != early) { + break; + } 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; - } - } + least = new_ctrl; } } diff -r c418c173158e -r c98bf5aa35c5 src/hotspot/share/opto/loopopts.cpp --- a/src/hotspot/share/opto/loopopts.cpp Mon Jul 02 13:11:41 2018 +0200 +++ b/src/hotspot/share/opto/loopopts.cpp Mon Jul 02 10:44:46 2018 +0200 @@ -257,6 +257,7 @@ ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj(); if (exclude_loop_predicate && (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL || + unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_profile_predicate) != NULL || unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check) != NULL)) { // If this is a range check (IfNode::is_range_check), do not // reorder because Compile::allow_range_check_smearing might have diff -r c418c173158e -r c98bf5aa35c5 test/hotspot/jtreg/compiler/loopopts/CountedLoopPeelingProfilePredicates.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/hotspot/jtreg/compiler/loopopts/CountedLoopPeelingProfilePredicates.java Mon Jul 02 10:44:46 2018 +0200 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8205515 + * @summary CountedLoopEndNode from peeled loop body is not candidate for profile loop predication + * + * @run main/othervm -XX:-TieredCompilation -XX:-BackgroundCompilation -XX:-UseOnStackReplacement CountedLoopPeelingProfilePredicates + * + */ + +import java.util.Arrays; + +public class CountedLoopPeelingProfilePredicates { + public static void main(String[] args) { + int stop = 2; + boolean[] flags1 = new boolean[stop]; + flags1[stop-1] = true; + boolean[] flags2 = new boolean[stop]; + flags2[0] = true; + boolean[] flags3 = new boolean[100]; + Arrays.fill(flags3, true); + flags3[0] = false; + + for (int i = 0; i < 20_000; i++) { + test_helper(stop, flags1, false); + test_helper(stop, flags2, false); + test_helper(stop, flags2, false); + } + for (int i = 0; i < 20_000; i++) { + test(stop, flags1, false, flags3, 1); + test(stop, flags2, false, flags3, 1); + test(stop, flags2, false, flags3, 1); + } + } + + + + private static void test(int stop, boolean[] flags1, boolean flag2, boolean[] flags3, int inc) { + for (int j = 0; j < 100; j+=inc) { + if (flags3[j]) { + test_helper(stop, flags1, flag2); + } + } + } + + private static void test_helper(int stop, boolean[] flags1, boolean flag2) { + for (int i = 0; i < stop; i++) { + if (flags1[i]) { + return; + } + if (flag2) { + } + } + } +}