From 528b2b27d3aab8021ab6b1bbc8b59e4bf3f8ab9d Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 12:07:47 +0200 Subject: [PATCH 1/6] more --- src/hotspot/share/opto/cfgnode.cpp | 78 ++++++++++++++++++- .../TestInlineTypeInfinitePushThruPhi.java | 74 ++++++++++++++++++ 2 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 55fe2f47d2f..bbb6bf6a5cd 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2935,17 +2935,26 @@ class PushInlineTypeDown { for (uint j = 1; j < n->req(); ++j) { Node* in = n->in(j); if (in != nullptr) { + // if (in->is_InlineType()) { + // _subgraph_to_clone.push(in); + // } _nodes_from_phi.push(in); } } } else if (n->is_ConstraintCast()) { Node* in = n->in(1); if (in != nullptr) { + // if (in->is_InlineType()) { + // _subgraph_to_clone.push(in); + // } _nodes_from_phi.push(in); } } else if (n->is_InlineType()) { Node* buf = n->as_InlineType()->get_oop(); if (buf != nullptr) { + // if (buf->is_InlineType()) { + // _subgraph_to_clone.push(buf); + // } _nodes_from_phi.push(buf); _subgraph_to_clone.push(n); } @@ -2966,6 +2975,23 @@ class PushInlineTypeDown { } } } + // assert(_subgraph_to_clone.size() == 0 || _subgraph_to_clone.member(_root_phi), ""); +#if 0 //def ASSERT + for (uint i = 0; i < _subgraph_to_clone.size(); ++i) { + Node* n = _subgraph_to_clone.at(i); + if (n->is_InlineType()) { + bool has_use_to_clone = false; + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* u = n->fast_out(i); + if (_subgraph_to_clone.member(u)) { + has_use_to_clone = true; + break; + } + } + assert(has_use_to_clone, ""); + } + } +#endif } void clone_nodes() { @@ -3106,10 +3132,37 @@ class PushInlineTypeDown { } #endif + Node* unique_non_null_phi_input(Node* n) { + if (!n->is_Phi()) { + return n; + } + Node* unique_input = nullptr; + for (uint i = 1; i < n->req(); i++) { + Node* in = n->in(i); + if (in != nullptr) { + if (unique_input == nullptr) { + unique_input = in; + } else { + unique_input = NodeSentinel; + } + } + } + if (unique_input != nullptr && unique_input != NodeSentinel) { + return unique_input; + } + return n; + } + Node* do_transform(PhiNode* phi) { + if (phi->req() == 3 && phi->in(1) != nullptr && phi->in(1)->is_InlineType() && phi->in(1)->as_InlineType()->get_oop() == phi->in(2)) { + ShouldNotReachHere(); + } assert(_inline_klass != nullptr, "must be"); - InlineTypeNode *vt = InlineTypeNode::make_null(*_phase, _inline_klass, /* transform = */ false)->clone_with_phis( + InlineTypeNode* vt = InlineTypeNode::make_null(*_phase, _inline_klass, /* transform = */ false)->clone_with_phis( _phase, phi->in(0), nullptr, !phi->type()->maybe_null(), true); + // Record that vt was created to replace phi to be able to use the inline type node when reaching the phi again + // through data loops. + _clones.map(phi->_idx, vt); if (_can_reshape) { // Replace phi right away to be able to use the inline // type node when reaching the phi again through data loops. @@ -3123,22 +3176,39 @@ class PushInlineTypeDown { igvn->rehash_node_delayed(phi); assert(phi->outcnt() == 0, "should be dead now"); } - ResourceMark rm; + // ResourceMark rm; Node_List casts; for (uint i = 1; i < phi->req(); ++i) { Node* n = phi->in(i); if (n == nullptr) { continue; } + // while (true) { while (n->is_ConstraintCast()) { casts.push(n); n = n->in(1); } + // Node* prev = n; + // n = unique_non_null_phi_input(n); + // if (prev == n) { + // break; + // } + // } if (_phase->type(n)->is_zero_type()) { n = InlineTypeNode::make_null(*_phase, _inline_klass); } else if (n->is_Phi()) { assert(_can_reshape, "can only handle phis during IGVN"); - n = _phase->transform(do_transform(n->as_Phi())); + Node* clone = get_clone(n); + // if (clone != nullptr) { + // n = clone; + // } else { + n = _phase->transform(do_transform(n->as_Phi())); + // } + } else { + if (!n->is_InlineType()) { + n->dump(); + } + assert(n->is_InlineType(), "unexpected node type"); } while (casts.size() != 0) { // Push the cast(s) through the InlineTypeNode @@ -3233,10 +3303,10 @@ class PushInlineTypeDown { Node* do_it() { if (_can_reshape) { - Node_List clones; collect_nodes_to_clone(); clone_subgraph(); DEBUG_ONLY(verify_clone()); + _clones.clear(); } return do_transform(_root_phi); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java new file mode 100644 index 00000000000..15da7f09e29 --- /dev/null +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2026, 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 8386676 + * @summary [lworld] Infinite loop when pushing inline types down though phis during IGVN + * @enablePreview + * @modules java.base/jdk.internal.value + * java.base/jdk.internal.vm.annotation + * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch -XX:-UseOnStackReplacement -XX:CompileCommand=repeatcompilation,${test.main.class}::test,500 -XX:CompileTaskTimeout=8000 ${test.main.class} + */ + +package compiler.valhalla.inlinetypes; + +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; + +public class TestInlineTypeInfinitePushThruPhi { + static V2 v2 = new V2(3); + + public static void main(String[] args) { + for (int i = 0; i < 20_000; i++) { + test(); + } + } + + public static void test() { + V1 v1 = new V1(null, v2); + for (int i = 0; i < 100; i++) { + v1 = new V1(v1.x, v1.y); + } + } + + @LooselyConsistentValue + static value class V1 { + V2 x; + @NullRestricted + V2 y; + + V1(V2 x, V2 y) { + this.x = x; + this.y = y; + } + } + + static value class V2 { + int i; + + V2(int i) { + this.i = i; + } + } +} From 0bfbe844f9010bef6c5e844d882b0dd7a548ee8e Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 12:10:18 +0200 Subject: [PATCH 2/6] more --- src/hotspot/share/opto/cfgnode.cpp | 82 ++---------------------------- 1 file changed, 3 insertions(+), 79 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index bbb6bf6a5cd..46016bceaf8 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2935,26 +2935,17 @@ class PushInlineTypeDown { for (uint j = 1; j < n->req(); ++j) { Node* in = n->in(j); if (in != nullptr) { - // if (in->is_InlineType()) { - // _subgraph_to_clone.push(in); - // } _nodes_from_phi.push(in); } } } else if (n->is_ConstraintCast()) { Node* in = n->in(1); if (in != nullptr) { - // if (in->is_InlineType()) { - // _subgraph_to_clone.push(in); - // } _nodes_from_phi.push(in); } } else if (n->is_InlineType()) { Node* buf = n->as_InlineType()->get_oop(); if (buf != nullptr) { - // if (buf->is_InlineType()) { - // _subgraph_to_clone.push(buf); - // } _nodes_from_phi.push(buf); _subgraph_to_clone.push(n); } @@ -2975,23 +2966,6 @@ class PushInlineTypeDown { } } } - // assert(_subgraph_to_clone.size() == 0 || _subgraph_to_clone.member(_root_phi), ""); -#if 0 //def ASSERT - for (uint i = 0; i < _subgraph_to_clone.size(); ++i) { - Node* n = _subgraph_to_clone.at(i); - if (n->is_InlineType()) { - bool has_use_to_clone = false; - for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { - Node* u = n->fast_out(i); - if (_subgraph_to_clone.member(u)) { - has_use_to_clone = true; - break; - } - } - assert(has_use_to_clone, ""); - } - } -#endif } void clone_nodes() { @@ -3132,83 +3106,33 @@ class PushInlineTypeDown { } #endif - Node* unique_non_null_phi_input(Node* n) { - if (!n->is_Phi()) { - return n; - } - Node* unique_input = nullptr; - for (uint i = 1; i < n->req(); i++) { - Node* in = n->in(i); - if (in != nullptr) { - if (unique_input == nullptr) { - unique_input = in; - } else { - unique_input = NodeSentinel; - } - } - } - if (unique_input != nullptr && unique_input != NodeSentinel) { - return unique_input; - } - return n; - } - Node* do_transform(PhiNode* phi) { - if (phi->req() == 3 && phi->in(1) != nullptr && phi->in(1)->is_InlineType() && phi->in(1)->as_InlineType()->get_oop() == phi->in(2)) { - ShouldNotReachHere(); - } assert(_inline_klass != nullptr, "must be"); InlineTypeNode* vt = InlineTypeNode::make_null(*_phase, _inline_klass, /* transform = */ false)->clone_with_phis( _phase, phi->in(0), nullptr, !phi->type()->maybe_null(), true); // Record that vt was created to replace phi to be able to use the inline type node when reaching the phi again // through data loops. _clones.map(phi->_idx, vt); - if (_can_reshape) { - // Replace phi right away to be able to use the inline - // type node when reaching the phi again through data loops. - PhaseIterGVN* igvn = _phase->is_IterGVN(); - for (DUIterator_Fast imax, i = phi->fast_outs(imax); i < imax; i++) { - Node* u = phi->fast_out(i); - igvn->rehash_node_delayed(u); - imax -= u->replace_edge(phi, vt); - --i; - } - igvn->rehash_node_delayed(phi); - assert(phi->outcnt() == 0, "should be dead now"); - } - // ResourceMark rm; Node_List casts; for (uint i = 1; i < phi->req(); ++i) { Node* n = phi->in(i); if (n == nullptr) { continue; } - // while (true) { while (n->is_ConstraintCast()) { casts.push(n); n = n->in(1); } - // Node* prev = n; - // n = unique_non_null_phi_input(n); - // if (prev == n) { - // break; - // } - // } if (_phase->type(n)->is_zero_type()) { n = InlineTypeNode::make_null(*_phase, _inline_klass); } else if (n->is_Phi()) { assert(_can_reshape, "can only handle phis during IGVN"); Node* clone = get_clone(n); - // if (clone != nullptr) { - // n = clone; - // } else { + if (clone != nullptr) { + n = clone; + } else { n = _phase->transform(do_transform(n->as_Phi())); - // } - } else { - if (!n->is_InlineType()) { - n->dump(); } - assert(n->is_InlineType(), "unexpected node type"); } while (casts.size() != 0) { // Push the cast(s) through the InlineTypeNode From 129b05863c3b52c9d38124306ce14e90fa0db82b Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 12:39:35 +0200 Subject: [PATCH 3/6] more --- .../inlinetypes/TestInlineTypeInfinitePushThruPhi.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java index 15da7f09e29..f998bd8b8b6 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java @@ -28,7 +28,10 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch -XX:-UseOnStackReplacement -XX:CompileCommand=repeatcompilation,${test.main.class}::test,500 -XX:CompileTaskTimeout=8000 ${test.main.class} + * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * -XX:-UseOnStackReplacement -XX:StressSeed=3696073068 -XX:CompileTaskTimeout=8000 ${test.main.class} + * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * -XX:-UseOnStackReplacement -XX:CompileTaskTimeout=8000 ${test.main.class} */ package compiler.valhalla.inlinetypes; From 521e7d92856800b388620e1f33028a5bc69ba35b Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 16:13:27 +0200 Subject: [PATCH 4/6] whitespaces --- .../inlinetypes/TestInlineTypeInfinitePushThruPhi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java index f998bd8b8b6..070e578ff70 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java @@ -29,9 +29,9 @@ * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch - * -XX:-UseOnStackReplacement -XX:StressSeed=3696073068 -XX:CompileTaskTimeout=8000 ${test.main.class} + * -XX:-UseOnStackReplacement -XX:StressSeed=3696073068 -XX:CompileTaskTimeout=8000 ${test.main.class} * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch - * -XX:-UseOnStackReplacement -XX:CompileTaskTimeout=8000 ${test.main.class} + * -XX:-UseOnStackReplacement -XX:CompileTaskTimeout=8000 ${test.main.class} */ package compiler.valhalla.inlinetypes; From 6c1e39ed1cebc017c5f8a06b0ce6bff00485e7f5 Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 16:27:39 +0200 Subject: [PATCH 5/6] review --- .../inlinetypes/TestInlineTypeInfinitePushThruPhi.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java index 070e578ff70..cf252fc3e22 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java @@ -28,9 +28,9 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch * -XX:-UseOnStackReplacement -XX:StressSeed=3696073068 -XX:CompileTaskTimeout=8000 ${test.main.class} - * @run main/othervm -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch * -XX:-UseOnStackReplacement -XX:CompileTaskTimeout=8000 ${test.main.class} */ From 350dc74e990eda813d859088a8cd742198dff126 Mon Sep 17 00:00:00 2001 From: rwestrel Date: Tue, 30 Jun 2026 16:31:06 +0200 Subject: [PATCH 6/6] review --- .../inlinetypes/TestInlineTypeInfinitePushThruPhi.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java index cf252fc3e22..9bb53506271 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineTypeInfinitePushThruPhi.java @@ -28,9 +28,11 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+StressIGVN + * -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch * -XX:-UseOnStackReplacement -XX:StressSeed=3696073068 -XX:CompileTaskTimeout=8000 ${test.main.class} - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+StressIGVN + * -XX:CompileCommand=compileonly,${test.main.class}::test -Xbatch * -XX:-UseOnStackReplacement -XX:CompileTaskTimeout=8000 ${test.main.class} */