changeset 47795:a93ce8f7bddb

8190375: Java Crash in JavaBug.formatPos(I)Ljava/lang/String Summary: Skip the logic that set the value of the Phi iv if the exit condition is "not equal" Reviewed-by: thartmann, mdoerr
author roland
date Mon, 13 Nov 2017 14:53:28 -0500
parents 0ce0ac68ace7
children acda08206310 e20d8f168bb6
files src/hotspot/share/opto/cfgnode.cpp test/hotspot/jtreg/compiler/loopopts/TestCountedLoopBadIVRange.java
diffstat 2 files changed, 98 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/opto/cfgnode.cpp	Thu Aug 31 10:00:28 2017 +0200
+++ b/src/hotspot/share/opto/cfgnode.cpp	Mon Nov 13 14:53:28 2017 -0500
@@ -918,11 +918,18 @@
         const TypeInt* stride_t = phase->type(stride)->isa_int();
         if (lo != NULL && hi != NULL && stride_t != NULL) { // Dying loops might have TOP here
           assert(stride_t->_hi >= stride_t->_lo, "bad stride type");
-          if (stride_t->_hi < 0) {          // Down-counter loop
-            swap(lo, hi);
-            return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3);
-          } else if (stride_t->_lo >= 0) {
-            return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3);
+          BoolTest::mask bt = l->loopexit()->test_trip();
+          // If the loop exit condition is "not equal", the condition
+          // would not trigger if init > limit (if stride > 0) or if
+          // init < limit if (stride > 0) so we can't deduce bounds
+          // for the iv from the exit condition.
+          if (bt != BoolTest::ne) {
+            if (stride_t->_hi < 0) {          // Down-counter loop
+              swap(lo, hi);
+              return TypeInt::make(MIN2(lo->_lo, hi->_lo) , hi->_hi, 3);
+            } else if (stride_t->_lo >= 0) {
+              return TypeInt::make(lo->_lo, MAX2(lo->_hi, hi->_hi), 3);
+            }
           }
         }
       }
@@ -933,7 +940,7 @@
       // before the special code for counted loop above has a chance
       // to run (that is as long as the type of the backedge's control
       // is top), we might end up with non monotonic types
-      return phase->type(in(LoopNode::EntryControl));
+      return phase->type(in(LoopNode::EntryControl))->filter_speculative(_type);
     }
   }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/loopopts/TestCountedLoopBadIVRange.java	Mon Nov 13 14:53:28 2017 -0500
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 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 8190375
+ * @summary Bad range for IV phi when exit condition is a not equal test
+ * @run main/othervm -XX:-TieredCompilation TestCountedLoopBadIVRange
+ *
+ */
+
+
+public class TestCountedLoopBadIVRange {
+
+    static int test1(int[] arr) {
+        int j = 0;
+        int res = 0;
+        for (int i = 0; i < 2; i++) {
+            // When entered with j == 10, exit condition never
+            // succeeds so range of values for j can't be computed
+            // from exit condition
+            for (; j != 5; j++) {
+                if (j >= 20) {
+                    break;
+                }
+                res += arr[j];
+            }
+            j = 10;
+        }
+        return res;
+    }
+
+    static int test2(int[] arr) {
+        int j = 10;
+        int res = 0;
+        for (int i = 0; i < 2; i++) {
+            // Same as above but loop variable is decreasing
+            for (; j != 5; j--) {
+                if (j < 0) {
+                    break;
+                }
+                res += arr[j];
+            }
+            j = 1;
+        }
+        return res;
+    }
+
+    public static void main(String[] args) {
+        int[] arr = new int[20];
+        for (int i = 0; i < arr.length; i++) {
+            arr[i] = i;
+        }
+        for (int i = 0; i < 20_000; i++) {
+            int res = test1(arr);
+            if (res != 155) {
+                throw new RuntimeException("Incorrect result " + res);
+            }
+            res = test2(arr);
+            if (res != 41) {
+                throw new RuntimeException("Incorrect result " + res);
+            }
+        }
+    }
+}