8205515: assert(opcode == Op_RangeCheck) failed: no other if variant here
Reviewed-by: thartmann, kvn
--- 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;
}
--- 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;
--- 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;
}
}
--- 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
--- /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) {
+ }
+ }
+ }
+}