From d87c05ca8d219c1917dd4c5becb5803172b6eeaa Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Tue, 13 Jan 2026 08:09:59 +0000 Subject: [PATCH] 8373508: C2: sinking CreateEx out of loop breaks the graph Reviewed-by: thartmann, shade Backport-of: 6ae3e064352a56c5be140fba1ad6d040219432b0 --- src/hotspot/share/opto/loopopts.cpp | 1 + .../loopopts/TestCreateExSunkOutOfLoop.java | 73 ++++++++++++++++ .../loopopts/TestCreateExSunkOutOfLoop2.java | 85 +++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop.java create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop2.java diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index b1422d5db20..98494b8bc7e 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1708,6 +1708,7 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) { !n->is_OpaqueInitializedAssertionPredicate() && !n->is_OpaqueTemplateAssertionPredicate() && !is_raw_to_oop_cast && // don't extend live ranges of raw oops + n->Opcode() != Op_CreateEx && (KillPathsReachableByDeadTypeNode || !n->is_Type()) ) { Node *n_ctrl = get_ctrl(n); diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop.java b/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop.java new file mode 100644 index 00000000000..2e75325afea --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2025 IBM Corporation. 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 8373508 + * @summary C2: sinking CreateEx out of loop breaks the graph + * @library /test/lib + * @run main/othervm -Xbatch ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.loopopts; + +import jdk.test.lib.Utils; + +public class TestCreateExSunkOutOfLoop { + volatile boolean _mutatorToggle; + + boolean _mutatorFlip() { + _mutatorToggle = !_mutatorToggle; + return _mutatorToggle; + } + + void test() { + int idx = -845; + for (;;) { + try { + try { + for (Object temp = new byte[idx];;) {;} + } finally { + boolean flag = _mutatorFlip(); + _mutatorFlip(); + for (;;) { + if (flag) { + break; + } + } + } + } catch (Throwable $) {;} + } + } + + public static void main(String[] strArr) throws InterruptedException { + Thread thread = new Thread(() -> { + TestCreateExSunkOutOfLoop t = new TestCreateExSunkOutOfLoop(); + t.test(); + }); + thread.setDaemon(true); + thread.start(); + Thread.sleep(Utils.adjustTimeout(4000)); + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop2.java b/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop2.java new file mode 100644 index 00000000000..8c3854995b5 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCreateExSunkOutOfLoop2.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025 IBM Corporation. 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 8373508 + * @summary C2: sinking CreateEx out of loop breaks the graph + * @run main/othervm -Xbatch -XX:-TieredCompilation ${test.main.class} + * @run main ${test.main.class} + */ + +package compiler.loopopts; + +public class TestCreateExSunkOutOfLoop2 { + boolean b; + + boolean getB() { + return b; + } + + void test() { + int x = -845; + + for (int i = 5; i > 1; i -= 2) { + try { + try { + for (Object temp = new byte[x]; ; ) { + // infinite loop + } + } finally { + int zeroLimit = 2; + for (; zeroLimit < 4; zeroLimit *= 2) { } + + int zero = 34; + for (int peel = 2; peel < zeroLimit; peel++) { + zero = 0; + } + + if (zero == 0) { + // nop + } + + int flagLimit = 2; + for (; flagLimit < 4; flagLimit *= 2) { } + + boolean flag = getB(); + for (int peel = 2; peel < flagLimit; peel++) { + if (flag) { + break; + } + } + } + } catch (Throwable t) { + // ignored + } + } + } + + public static void main(String[] strArr) { + TestCreateExSunkOutOfLoop2 t = new TestCreateExSunkOutOfLoop2(); + for (int i = 0; i < 10_000; ++i) { + t.test(); + } + } +}