8205515: assert(opcode == Op_RangeCheck) failed: no other if variant here
authorroland
Mon, 02 Jul 2018 10:44:46 +0200
changeset 50923 c98bf5aa35c5
parent 50922 c418c173158e
child 50924 012ab74e9802
8205515: assert(opcode == Op_RangeCheck) failed: no other if variant here Reviewed-by: thartmann, kvn
src/hotspot/share/opto/ifnode.cpp
src/hotspot/share/opto/loopPredicate.cpp
src/hotspot/share/opto/loopnode.cpp
src/hotspot/share/opto/loopopts.cpp
test/hotspot/jtreg/compiler/loopopts/CountedLoopPeelingProfilePredicates.java
--- 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) {
+            }
+        }
+    }
+}