8202949: C2: assert(false) failed: Bad graph detected in build_loop_late
authorthartmann
Fri, 25 May 2018 09:05:42 +0200
changeset 50262 131a631b271a
parent 50261 3fd701692627
child 50263 42165815ee40
8202949: C2: assert(false) failed: Bad graph detected in build_loop_late Summary: Fixed trip count computation for counted loop with negative stride to prevent over-unrolling. Reviewed-by: roland
src/hotspot/share/opto/loopTransform.cpp
test/hotspot/jtreg/compiler/loopopts/TestOverunrolling.java
--- a/src/hotspot/share/opto/loopTransform.cpp	Thu May 24 22:21:00 2018 -0700
+++ b/src/hotspot/share/opto/loopTransform.cpp	Fri May 25 09:05:42 2018 +0200
@@ -116,9 +116,11 @@
   if (init_n != NULL && limit_n != NULL) {
     // Use longs to avoid integer overflow.
     int stride_con = cl->stride_con();
-    jlong init_con = phase->_igvn.type(init_n)->is_int()->_lo;
-    jlong limit_con = phase->_igvn.type(limit_n)->is_int()->_hi;
-    int stride_m   = stride_con - (stride_con > 0 ? 1 : -1);
+    const TypeInt* init_type = phase->_igvn.type(init_n)->is_int();
+    const TypeInt* limit_type = phase->_igvn.type(limit_n)->is_int();
+    jlong init_con = (stride_con > 0) ? init_type->_lo : init_type->_hi;
+    jlong limit_con = (stride_con > 0) ? limit_type->_hi : limit_type->_lo;
+    int stride_m = stride_con - (stride_con > 0 ? 1 : -1);
     jlong trip_count = (limit_con - init_con + stride_m)/stride_con;
     if (trip_count > 0 && (julong)trip_count < (julong)max_juint) {
       if (init_n->is_Con() && limit_n->is_Con()) {
--- a/test/hotspot/jtreg/compiler/loopopts/TestOverunrolling.java	Thu May 24 22:21:00 2018 -0700
+++ b/test/hotspot/jtreg/compiler/loopopts/TestOverunrolling.java	Fri May 25 09:05:42 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. 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
@@ -23,20 +23,19 @@
 
 /*
  * @test
- * @bug 8159016
+ * @bug 8159016 8202949
  * @summary Tests correct dominator information after over-unrolling a loop.
  * @requires vm.gc == "Parallel" | vm.gc == "null"
- *
- * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xcomp -XX:-TieredCompilation
- *                   -XX:-UseG1GC -XX:+UseParallelGC
- *                   compiler.loopopts.TestOverunrolling
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockExperimentalVMOptions
+ *                   -Xcomp -XX:-TieredCompilation -XX:-UseSwitchProfiling
+ *                   -XX:-UseG1GC -XX:+UseParallelGC compiler.loopopts.TestOverunrolling
  */
 
 package compiler.loopopts;
 
 public class TestOverunrolling {
 
-    public static Object test(int arg) {
+    public static Object test1(int arg) {
         Object arr[] = new Object[3];
         int lim = (arg & 3);
         // The pre loop is executed for one iteration, initializing p[0].
@@ -53,10 +52,40 @@
         return arr;
     }
 
+    public static long lFld = 0;
+    public static volatile double dFld = 0;
+
+    public static void test2() {
+        int iArr[] = new int[10];
+        // The inner for-loop is overunrolled because we fail to determine
+        // the constant lower and upper bound (6,8]. After unrolling multiple times,
+        // the range check dependent CastII/ConvI2L emitted for the iArr access become
+        // TOP because index 'j' is out of bounds. As a result, the memory graph is
+        // corrupted with memory consuming nodes still being reachable because the dead
+        // loop is not (yet) removed (Opaque1 nodes are still guarding the bounds).
+        for (int i = 6; i < 10; i++) {
+            for (int j = 8; j > i; j--) {
+                int k = 1;
+                do {
+                    iArr[j] = 0;
+                    switch (k) {
+                    case 1:
+                        lFld = 0;
+                        break;
+                    case 10:
+                        dFld = 0;
+                        break;
+                    }
+                } while (++k < 1);
+            }
+        }
+    }
+
     public static void main(String args[]) {
         for (int i = 0; i < 42; ++i) {
-            test(i);
+            test1(i);
         }
+        test2();
     }
 }