changeset 62510:21ef0858cc7f

8249603: C1: assert(has_error == false) failed: register allocation invalid Summary: Added bailout in combine_spilled_intervals() to avoid an overlap between two intervals Reviewed-by: kvn, thartmann
author chagedorn
date Wed, 12 Aug 2020 08:45:44 +0200
parents 0d7947ba5389
children 63b1fe3160fd
files src/hotspot/share/c1/c1_LinearScan.cpp src/hotspot/share/c1/c1_LinearScan.hpp test/hotspot/jtreg/compiler/regalloc/TestC1OverlappingRegisterHint.java
diffstat 3 files changed, 121 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/c1/c1_LinearScan.cpp	Tue Aug 11 22:05:56 2020 -0700
+++ b/src/hotspot/share/c1/c1_LinearScan.cpp	Wed Aug 12 08:45:44 2020 +0200
@@ -4542,6 +4542,18 @@
   return false;
 }
 
+// Check if there is an intersection with any of the split children of 'interval'
+bool Interval::intersects_any_children_of(Interval* interval) const {
+  if (interval->_split_children != NULL) {
+    for (int i = 0; i < interval->_split_children->length(); i++) {
+      if (intersects(interval->_split_children->at(i))) {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
 
 #ifndef PRODUCT
 void Interval::print(outputStream* out) const {
@@ -5722,6 +5734,13 @@
     return;
   }
   assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
+  assert(!cur->intersects(register_hint), "cur should not intersect register_hint");
+
+  if (cur->intersects_any_children_of(register_hint)) {
+    // Bail out if cur intersects any split children of register_hint, which have the same spill slot as their parent. An overlap of two intervals with
+    // the same spill slot could result in a situation where both intervals are spilled at the same time to the same stack location which is not correct.
+    return;
+  }
 
   // modify intervals such that cur gets the same stack slot as register_hint
   // delete use positions to prevent the intervals to get a register at beginning
--- a/src/hotspot/share/c1/c1_LinearScan.hpp	Tue Aug 11 22:05:56 2020 -0700
+++ b/src/hotspot/share/c1/c1_LinearScan.hpp	Wed Aug 12 08:45:44 2020 +0200
@@ -613,6 +613,7 @@
   bool   covers(int op_id, LIR_OpVisitState::OprMode mode) const;
   bool   has_hole_between(int from, int to);
   bool   intersects(Interval* i) const           { return _first->intersects(i->_first); }
+  bool   intersects_any_children_of(Interval* i) const;
   int    intersects_at(Interval* i) const        { return _first->intersects_at(i->_first); }
 
   // range iteration
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/regalloc/TestC1OverlappingRegisterHint.java	Wed Aug 12 08:45:44 2020 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2020, 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
+ * 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 8249603
+ * @summary The C1 register allocator uses a register hint interval i as spill location for an interval j which
+ *          overlaps with one of i's split children which has the same spill location which lets verification fail.
+ *
+ * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.regalloc.TestC1OverlappingRegisterHint::*
+ *                   compiler.regalloc.TestC1OverlappingRegisterHint
+ */
+package compiler.regalloc;
+
+public class TestC1OverlappingRegisterHint {
+
+    public static int iFldStatic = 10;
+    public int iFld = 11;
+
+    public int test() {
+        int a = 1;
+        int b = 2;
+        int c = 3;
+        int v = 4;
+        int w = 5;
+        int x = 6;
+        int y = 7;
+        int z = 8;
+        int iArr[] = new int[400];
+
+        double d = 1.5;
+
+        int k = 0;
+        for (a = 9; a < 283; a += 2) {
+            for (int i = 8; i < 183; i++) {
+            }
+        }
+
+        for (int i = 12; i < 283; i++) {
+            iFldStatic += i;
+            for (int j = 1; 93 > j; j += 2) {
+                x += (j - z);
+                c -= iFld;
+                k = 3;
+                while ((k -= 2) > 0) {
+                }
+                switch ((i % 8) + 52) {
+                case 52:
+                    iArr[8] = 5;
+                    for (int i20 = 1; i20 < 3; ++i20) {
+                        x *= (int)d;
+                        w += 5;
+                    }
+                    break;
+                case 53:
+                case 55:
+                    v *= iFldStatic;
+                    break;
+                case 56:
+                case 57:
+                    try {
+                        iArr[5] = a;
+                        v = (a / b);
+                    } catch (ArithmeticException a_e) {}
+                    break;
+                default:
+                    iFldStatic += iFldStatic;
+                }
+            }
+        }
+        return y + k;
+    }
+
+    public static void main(String[] strArr) {
+        TestC1OverlappingRegisterHint _instance = new TestC1OverlappingRegisterHint();
+        for (int i = 0; i < 10; i++) {
+            _instance.test();
+        }
+    }
+}
+