# HG changeset patch
# User roland
# Date 1590664914 -7200
# Thu May 28 13:21:54 2020 +0200
# Node ID 516c889e7582598020e49ed62bcf77871fe315d8
# Parent b2e6516f67ff98224f14e65beb944ddb04b24548
8245714: "Bad graph detected in build_loop_late" when loads are pinned on loop limit check uncommon branch
Reviewed-by: thartmann
diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp
--- a/src/hotspot/share/opto/loopPredicate.cpp
+++ b/src/hotspot/share/opto/loopPredicate.cpp
@@ -111,6 +111,9 @@
CallNode* call = rgn->as_Call();
IdealLoopTree* loop = get_loop(call);
rgn = new RegionNode(1);
+ Node* uncommon_proj_orig = uncommon_proj;
+ uncommon_proj = uncommon_proj->clone()->as_Proj();
+ register_control(uncommon_proj, loop, iff);
rgn->add_req(uncommon_proj);
register_control(rgn, loop, uncommon_proj);
_igvn.replace_input_of(call, 0, rgn);
@@ -118,13 +121,9 @@
if (_idom != NULL) {
set_idom(call, rgn, dom_depth(rgn));
}
- for (DUIterator_Fast imax, i = uncommon_proj->fast_outs(imax); i < imax; i++) {
- Node* n = uncommon_proj->fast_out(i);
- if (n->is_Load() || n->is_Store()) {
- _igvn.replace_input_of(n, 0, rgn);
- --i; --imax;
- }
- }
+ // Move nodes pinned on the projection or whose control is set to
+ // the projection to the region.
+ lazy_replace(uncommon_proj_orig, rgn);
} else {
// Find region's edge corresponding to uncommon_proj
for (; proj_index < rgn->req(); proj_index++)
diff --git a/test/hotspot/jtreg/compiler/loopopts/TestBadControlLoopLimitCheck.java b/test/hotspot/jtreg/compiler/loopopts/TestBadControlLoopLimitCheck.java
new file mode 100644
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopopts/TestBadControlLoopLimitCheck.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2020, 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 8245714
+ * @requires vm.compiler2.enabled
+ * @summary "Bad graph detected in build_loop_late" when loads are pinned on loop limit check uncommon branch
+ *
+ * @run main/othervm -XX:-BackgroundCompilation -XX:ArrayCopyLoadStoreMaxElem=0 TestBadControlLoopLimitCheck
+ */
+
+public class TestBadControlLoopLimitCheck {
+ public static void main(String[] args) {
+ int[] int_array = {0, 0};
+ A[] obj_array = {new A(), new A()};
+ for (int i = 0; i < 20_000; i++) {
+ test1(int_array, 0, 10, false);
+ test_helper(42);
+ test2(obj_array, 0, 10, false);
+ }
+ }
+
+ private static int test1(int[] a, int start, int stop, boolean flag) {
+ int[] b = new int[2]; // non escaping allocation
+ System.arraycopy(a, 0, b, 0, 2); // optimized out
+ int v = 1;
+ int j = 0;
+ for (; j < 10; j++);
+ int inc = test_helper(j); // delay transformation to counted loop
+ // loop limit check here has loads pinned on unc branch
+ for (int i = start; i < stop; i += inc) {
+ v *= 2;
+ }
+ if (flag) {
+ v += b[0] + b[1];
+ }
+ return v;
+ }
+
+ private static int test2(A[] a, int start, int stop, boolean flag) {
+ A[] b = new A[2]; // non escaping allocation
+ System.arraycopy(a, 0, b, 0, 2); // optimized out
+ int v = 1;
+ int j = 0;
+ for (; j < 10; j++);
+ int inc = test_helper(j); // delay transformation to counted loop
+ // loop limit check here has loads pinned on unc branch
+ for (int i = start; i < stop; i += inc) {
+ v *= 2;
+ }
+ if (flag) {
+ v += b[0].f + b[1].f;
+ }
+ return v;
+ }
+
+ static class A {
+ int f;
+ }
+
+ static int test_helper(int j) {
+ return j == 10 ? 10 : 1;
+ }
+}