From 75e2dd95df5d847d7d6e35a23016d22705681cf4 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 1 Dec 2025 11:14:42 +0100 Subject: [PATCH 01/13] JDK-8369045: [lworld] valhalla/valuetypes/WeakReferenceTest.java has an unschedulable graph --- src/hotspot/share/opto/callGenerator.cpp | 7 +++++++ src/hotspot/share/opto/compile.hpp | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 6d20d05312b..f0620d389fe 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -739,6 +739,13 @@ void CallGenerator::do_late_inline_helper() { jvms = arg_kit.transfer_exceptions_into_jvms(); } + // Don't late inline if this is a late pass to optimize virtual and MH calls only and the type of caller and callee are not loaded. + // This is to avoid potential issues with cascading calls to store to buffer that mess up the graph. + ciType* caller_return_type = method()->return_type(); + if (!C->inlining_incrementally() && C->late_inline_count() > 0 && InlineTypeReturnedAsFields && !return_type->is_loaded() && !caller_return_type->is_loaded()) { + return; + } + // Setup default node notes to be picked up by the inlining Node_Notes* old_nn = C->node_notes_at(call->_idx); if (old_nn != nullptr) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 5c6f28bc86c..6a5dc05641a 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1101,6 +1101,10 @@ class Compile : public Phase { _late_inlines.insert_before(0, cg); } + int late_inline_count() const { + return _late_inlines.length(); + } + void add_string_late_inline(CallGenerator* cg) { _string_late_inlines.push(cg); } From 461677452b2ec01e0def2049de6a22fe8ff7bfab Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Thu, 4 Dec 2025 14:59:43 +0100 Subject: [PATCH 02/13] JDK-8369045: replace result projections instead of no strength reduction --- src/hotspot/share/opto/callGenerator.cpp | 7 --- src/hotspot/share/opto/compile.cpp | 3 ++ src/hotspot/share/opto/compile.hpp | 7 ++- src/hotspot/share/opto/graphKit.cpp | 62 ++++++++++++++++-------- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index f0620d389fe..6d20d05312b 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -739,13 +739,6 @@ void CallGenerator::do_late_inline_helper() { jvms = arg_kit.transfer_exceptions_into_jvms(); } - // Don't late inline if this is a late pass to optimize virtual and MH calls only and the type of caller and callee are not loaded. - // This is to avoid potential issues with cascading calls to store to buffer that mess up the graph. - ciType* caller_return_type = method()->return_type(); - if (!C->inlining_incrementally() && C->late_inline_count() > 0 && InlineTypeReturnedAsFields && !return_type->is_loaded() && !caller_return_type->is_loaded()) { - return; - } - // Setup default node notes to be picked up by the inlining Node_Notes* old_nn = C->node_notes_at(call->_idx); if (old_nn != nullptr) { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 4256923a695..0b761abe2e9 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -662,6 +662,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _allow_macro_nodes(true), _inlining_progress(false), _inlining_incrementally(false), + _strength_reduction(false), _do_cleanup(false), _has_reserved_stack_access(target->has_reserved_stack_access()), _has_circular_inline_type(false), @@ -2741,6 +2742,7 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { // Tracking and verification of modified nodes is disabled by setting "_modified_nodes == nullptr" // as if "inlining_incrementally() == true" were set. assert(inlining_incrementally() == false, "not allowed"); + set_strength_reduction(true); #ifdef ASSERT Unique_Node_List* modified_nodes = _modified_nodes; _modified_nodes = nullptr; @@ -2758,6 +2760,7 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { inline_incrementally_cleanup(igvn); } DEBUG_ONLY( _modified_nodes = modified_nodes; ) + set_strength_reduction(false); } bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 6a5dc05641a..e577515d751 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -337,6 +337,7 @@ class Compile : public Phase { bool _major_progress; bool _inlining_progress; // progress doing incremental inlining? bool _inlining_incrementally;// Are we doing incremental inlining (post parse) + bool _strength_reduction; // Are we doing strength reduction bool _do_cleanup; // Cleanup is needed before proceeding with incremental inlining bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if @@ -605,6 +606,8 @@ class Compile : public Phase { int inlining_progress() const { return _inlining_progress; } void set_inlining_incrementally(bool z) { _inlining_incrementally = z; } int inlining_incrementally() const { return _inlining_incrementally; } + void set_strength_reduction(bool z) { _strength_reduction = z; } + bool strength_reduction() const { return _strength_reduction; } void set_do_cleanup(bool z) { _do_cleanup = z; } int do_cleanup() const { return _do_cleanup; } bool major_progress() const { return _major_progress; } @@ -1101,10 +1104,6 @@ class Compile : public Phase { _late_inlines.insert_before(0, cg); } - int late_inline_count() const { - return _late_inlines.length(); - } - void add_string_late_inline(CallGenerator* cg) { _string_late_inlines.push(cg); } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 69cd035d015..840df42401a 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -25,6 +25,7 @@ #include "asm/register.hpp" #include "ci/ciFlatArrayKlass.hpp" #include "ci/ciInlineKlass.hpp" +#include "ci/ciMethod.hpp" #include "ci/ciObjArray.hpp" #include "ci/ciUtilities.hpp" #include "classfile/javaClasses.hpp" @@ -2047,28 +2048,36 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p _gvn.set_type(call, call->Value(&_gvn)); _gvn.set_type(ret, ret->Value(&_gvn)); - Node* store_to_buf_call = make_runtime_call(RC_NO_LEAF | RC_NO_IO, - OptoRuntime::store_inline_type_fields_Type(), - StubRoutines::store_inline_type_fields_to_buf(), - nullptr, TypePtr::BOTTOM, ret); - - // We don't know how many values are returned. This assumes the - // worst case, that all available registers are used. - for (uint i = TypeFunc::Parms+1; i < domain->cnt(); i++) { - if (domain->field_at(i) == Type::HALF) { - store_to_buf_call->init_req(i, top()); - continue; + // Don't add store to buffer call if we are strength reducing + if (!C->strength_reduction()) { + Node* store_to_buf_call = make_runtime_call(RC_NO_LEAF | RC_NO_IO, + OptoRuntime::store_inline_type_fields_Type(), + StubRoutines::store_inline_type_fields_to_buf(), + nullptr, TypePtr::BOTTOM, ret); + + // We don't know how many values are returned. This assumes the + // worst case, that all available registers are used. + for (uint i = TypeFunc::Parms+1; i < domain->cnt(); i++) { + if (domain->field_at(i) == Type::HALF) { + store_to_buf_call->init_req(i, top()); + continue; + } + Node* proj =_gvn.transform(new ProjNode(call, i)); + store_to_buf_call->init_req(i, proj); } - Node* proj =_gvn.transform(new ProjNode(call, i)); - store_to_buf_call->init_req(i, proj); - } - make_slow_call_ex(store_to_buf_call, env()->Throwable_klass(), false); + make_slow_call_ex(store_to_buf_call, env()->Throwable_klass(), false); - Node* buf = _gvn.transform(new ProjNode(store_to_buf_call, TypeFunc::Parms)); - const Type* buf_type = TypeOopPtr::make_from_klass(t->as_klass())->join_speculative(TypePtr::NOTNULL); - buf = _gvn.transform(new CheckCastPPNode(control(), buf, buf_type)); + Node* buf = _gvn.transform(new ProjNode(store_to_buf_call, TypeFunc::Parms)); + const Type* buf_type = TypeOopPtr::make_from_klass(t->as_klass())->join_speculative(TypePtr::NOTNULL); + buf = _gvn.transform(new CheckCastPPNode(control(), buf, buf_type)); - ideal.set(res, buf); + ideal.set(res, buf); + } else { + for (uint i = TypeFunc::Parms+1; i < domain->cnt(); i++) { + Node* proj =_gvn.transform(new ProjNode(call, i)); + } + ideal.set(res, ret); + } ideal.sync_kit(this); } ideal.end_if(); sync_kit(ideal); @@ -2211,9 +2220,20 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes if (callprojs->resproj[0] != nullptr && result != nullptr) { // If the inlined code is dead, the result projections for an inline type returned as // fields have not been replaced. They will go away once the call is replaced by TOP below. - assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()), + assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || + (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), "unexpected number of results"); - C->gvn_replace_by(callprojs->resproj[0], result); + // If we are doing strength reduction and the return types is not loaded we + // need to rewire all projections since store_inline_type_fields_to_buf is already present + if (C->strength_reduction() && InlineTypeReturnedAsFields && + !call->as_CallJava()->method()->return_type()->is_loaded()) { + const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); + for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { + C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); + } + } else { + C->gvn_replace_by(callprojs->resproj[0], result); + } } if (ejvms == nullptr) { From 696695f03afdeb5f2538eb2279658b31661536d0 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 8 Dec 2025 08:38:44 +0100 Subject: [PATCH 03/13] JDK-8369045: add bool for rt_loaded --- src/hotspot/share/opto/graphKit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 840df42401a..5e5bc8d41e0 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2218,15 +2218,15 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes // Replace the result with the new result if it exists and is used if (callprojs->resproj[0] != nullptr && result != nullptr) { + bool rt_loaded = !call->as_CallJava()->method()->return_type()->is_loaded(); // If the inlined code is dead, the result projections for an inline type returned as // fields have not been replaced. They will go away once the call is replaced by TOP below. assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || - (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), + (C->strength_reduction() && InlineTypeReturnedAsFields && rt_loaded), "unexpected number of results"); // If we are doing strength reduction and the return types is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present - if (C->strength_reduction() && InlineTypeReturnedAsFields && - !call->as_CallJava()->method()->return_type()->is_loaded()) { + if (C->strength_reduction() && InlineTypeReturnedAsFields && rt_loaded) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); From 92d19656b904441aa59b7fed1e3132fee6d2c6e0 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 8 Dec 2025 08:47:22 +0100 Subject: [PATCH 04/13] JDK-8369045: add comment --- src/hotspot/share/opto/compile.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index e577515d751..95eb5d856a8 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -337,7 +337,7 @@ class Compile : public Phase { bool _major_progress; bool _inlining_progress; // progress doing incremental inlining? bool _inlining_incrementally;// Are we doing incremental inlining (post parse) - bool _strength_reduction; // Are we doing strength reduction + bool _strength_reduction; // Are we doing strength reduction to direct call bool _do_cleanup; // Cleanup is needed before proceeding with incremental inlining bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if From f59ecefd0339ee371254d7d8e3e1a841b86bc779 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 8 Dec 2025 10:29:49 +0100 Subject: [PATCH 05/13] Revert "JDK-8369045: add bool for rt_loaded" This reverts commit 696695f03afdeb5f2538eb2279658b31661536d0. --- src/hotspot/share/opto/graphKit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 5e5bc8d41e0..840df42401a 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2218,15 +2218,15 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes // Replace the result with the new result if it exists and is used if (callprojs->resproj[0] != nullptr && result != nullptr) { - bool rt_loaded = !call->as_CallJava()->method()->return_type()->is_loaded(); // If the inlined code is dead, the result projections for an inline type returned as // fields have not been replaced. They will go away once the call is replaced by TOP below. assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || - (C->strength_reduction() && InlineTypeReturnedAsFields && rt_loaded), + (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), "unexpected number of results"); // If we are doing strength reduction and the return types is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present - if (C->strength_reduction() && InlineTypeReturnedAsFields && rt_loaded) { + if (C->strength_reduction() && InlineTypeReturnedAsFields && + !call->as_CallJava()->method()->return_type()->is_loaded()) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); From 76f2e96f6a606d03f00e516fda6756e920e91c4e Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 8 Dec 2025 10:31:27 +0100 Subject: [PATCH 06/13] JDK-8369045: remove new line --- src/hotspot/share/opto/graphKit.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 840df42401a..8ddc5c004b8 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2225,8 +2225,7 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes "unexpected number of results"); // If we are doing strength reduction and the return types is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present - if (C->strength_reduction() && InlineTypeReturnedAsFields && - !call->as_CallJava()->method()->return_type()->is_loaded()) { + if (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); From ccf58125b13655bb6c15af747345efbd6791f93d Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 15 Dec 2025 10:33:17 +0100 Subject: [PATCH 07/13] JDK-8369045: remove strength reduction flag --- src/hotspot/share/opto/compile.cpp | 3 --- src/hotspot/share/opto/compile.hpp | 3 --- src/hotspot/share/opto/graphKit.cpp | 6 +++--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 0b761abe2e9..4256923a695 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -662,7 +662,6 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _allow_macro_nodes(true), _inlining_progress(false), _inlining_incrementally(false), - _strength_reduction(false), _do_cleanup(false), _has_reserved_stack_access(target->has_reserved_stack_access()), _has_circular_inline_type(false), @@ -2742,7 +2741,6 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { // Tracking and verification of modified nodes is disabled by setting "_modified_nodes == nullptr" // as if "inlining_incrementally() == true" were set. assert(inlining_incrementally() == false, "not allowed"); - set_strength_reduction(true); #ifdef ASSERT Unique_Node_List* modified_nodes = _modified_nodes; _modified_nodes = nullptr; @@ -2760,7 +2758,6 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { inline_incrementally_cleanup(igvn); } DEBUG_ONLY( _modified_nodes = modified_nodes; ) - set_strength_reduction(false); } bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 95eb5d856a8..5c6f28bc86c 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -337,7 +337,6 @@ class Compile : public Phase { bool _major_progress; bool _inlining_progress; // progress doing incremental inlining? bool _inlining_incrementally;// Are we doing incremental inlining (post parse) - bool _strength_reduction; // Are we doing strength reduction to direct call bool _do_cleanup; // Cleanup is needed before proceeding with incremental inlining bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if @@ -606,8 +605,6 @@ class Compile : public Phase { int inlining_progress() const { return _inlining_progress; } void set_inlining_incrementally(bool z) { _inlining_incrementally = z; } int inlining_incrementally() const { return _inlining_incrementally; } - void set_strength_reduction(bool z) { _strength_reduction = z; } - bool strength_reduction() const { return _strength_reduction; } void set_do_cleanup(bool z) { _do_cleanup = z; } int do_cleanup() const { return _do_cleanup; } bool major_progress() const { return _major_progress; } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 8ddc5c004b8..25db04ba31c 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2049,7 +2049,7 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p _gvn.set_type(ret, ret->Value(&_gvn)); // Don't add store to buffer call if we are strength reducing - if (!C->strength_reduction()) { + if (!_gvn.is_IterGVN() || C->inlining_incrementally()) { Node* store_to_buf_call = make_runtime_call(RC_NO_LEAF | RC_NO_IO, OptoRuntime::store_inline_type_fields_Type(), StubRoutines::store_inline_type_fields_to_buf(), @@ -2221,11 +2221,11 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes // If the inlined code is dead, the result projections for an inline type returned as // fields have not been replaced. They will go away once the call is replaced by TOP below. assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || - (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), + ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), "unexpected number of results"); // If we are doing strength reduction and the return types is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present - if (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { + if ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); From 60aef9315cf01bc94da65ac89f9b57625bd589e5 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Wed, 17 Dec 2025 10:10:31 +0100 Subject: [PATCH 08/13] Update src/hotspot/share/opto/graphKit.cpp Co-authored-by: Tobias Hartmann --- src/hotspot/share/opto/graphKit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 25db04ba31c..56c9e372553 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2223,7 +2223,7 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), "unexpected number of results"); - // If we are doing strength reduction and the return types is not loaded we + // If we are doing strength reduction and the return type is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present if ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); From b384c0ae168732a115458ad663eb1155f18020b7 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Wed, 17 Dec 2025 13:36:51 +0100 Subject: [PATCH 09/13] Revert "JDK-8369045: remove strength reduction flag" This reverts commit ccf58125b13655bb6c15af747345efbd6791f93d. --- src/hotspot/share/opto/compile.cpp | 3 +++ src/hotspot/share/opto/compile.hpp | 3 +++ src/hotspot/share/opto/graphKit.cpp | 6 +++--- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 4256923a695..0b761abe2e9 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -662,6 +662,7 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _allow_macro_nodes(true), _inlining_progress(false), _inlining_incrementally(false), + _strength_reduction(false), _do_cleanup(false), _has_reserved_stack_access(target->has_reserved_stack_access()), _has_circular_inline_type(false), @@ -2741,6 +2742,7 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { // Tracking and verification of modified nodes is disabled by setting "_modified_nodes == nullptr" // as if "inlining_incrementally() == true" were set. assert(inlining_incrementally() == false, "not allowed"); + set_strength_reduction(true); #ifdef ASSERT Unique_Node_List* modified_nodes = _modified_nodes; _modified_nodes = nullptr; @@ -2758,6 +2760,7 @@ void Compile::process_late_inline_calls_no_inline(PhaseIterGVN& igvn) { inline_incrementally_cleanup(igvn); } DEBUG_ONLY( _modified_nodes = modified_nodes; ) + set_strength_reduction(false); } bool Compile::optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 5c6f28bc86c..95eb5d856a8 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -337,6 +337,7 @@ class Compile : public Phase { bool _major_progress; bool _inlining_progress; // progress doing incremental inlining? bool _inlining_incrementally;// Are we doing incremental inlining (post parse) + bool _strength_reduction; // Are we doing strength reduction to direct call bool _do_cleanup; // Cleanup is needed before proceeding with incremental inlining bool _has_loops; // True if the method _may_ have some loops bool _has_split_ifs; // True if the method _may_ have some split-if @@ -605,6 +606,8 @@ class Compile : public Phase { int inlining_progress() const { return _inlining_progress; } void set_inlining_incrementally(bool z) { _inlining_incrementally = z; } int inlining_incrementally() const { return _inlining_incrementally; } + void set_strength_reduction(bool z) { _strength_reduction = z; } + bool strength_reduction() const { return _strength_reduction; } void set_do_cleanup(bool z) { _do_cleanup = z; } int do_cleanup() const { return _do_cleanup; } bool major_progress() const { return _major_progress; } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 25db04ba31c..8ddc5c004b8 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2049,7 +2049,7 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p _gvn.set_type(ret, ret->Value(&_gvn)); // Don't add store to buffer call if we are strength reducing - if (!_gvn.is_IterGVN() || C->inlining_incrementally()) { + if (!C->strength_reduction()) { Node* store_to_buf_call = make_runtime_call(RC_NO_LEAF | RC_NO_IO, OptoRuntime::store_inline_type_fields_Type(), StubRoutines::store_inline_type_fields_to_buf(), @@ -2221,11 +2221,11 @@ void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes // If the inlined code is dead, the result projections for an inline type returned as // fields have not been replaced. They will go away once the call is replaced by TOP below. assert(callprojs->nb_resproj == 1 || (call->tf()->returns_inline_type_as_fields() && stopped()) || - ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), + (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()), "unexpected number of results"); // If we are doing strength reduction and the return types is not loaded we // need to rewire all projections since store_inline_type_fields_to_buf is already present - if ((_gvn.is_IterGVN() && !C->inlining_incrementally()) && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { + if (C->strength_reduction() && InlineTypeReturnedAsFields && !call->as_CallJava()->method()->return_type()->is_loaded()) { const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); for (uint i = TypeFunc::Parms; i < domain->cnt(); i++) { C->gvn_replace_by(callprojs->resproj[0], final_state->in(i)); From 0685e19ac03e7ab122582bde36b933c38b767881 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Wed, 17 Dec 2025 14:34:55 +0100 Subject: [PATCH 10/13] JDK-8369045: don't re-add condition if stress-reducing --- src/hotspot/share/opto/graphKit.cpp | 47 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 8ddc5c004b8..244dc8da668 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2033,23 +2033,22 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p IdealKit ideal(this); IdealVariable res(ideal); ideal.declarations_done(); - ideal.if_then(ret, BoolTest::eq, ideal.makecon(TypePtr::NULL_PTR)); { - // Return value is null - ideal.set(res, makecon(TypePtr::NULL_PTR)); - } ideal.else_(); { - // Return value is non-null - sync_kit(ideal); - - // Change return type of call to scalarized return - const TypeFunc* tf = call->_tf; - const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); - const TypeFunc* new_tf = TypeFunc::make(tf->domain_sig(), tf->domain_cc(), tf->range_sig(), domain); - call->_tf = new_tf; - _gvn.set_type(call, call->Value(&_gvn)); - _gvn.set_type(ret, ret->Value(&_gvn)); - - // Don't add store to buffer call if we are strength reducing - if (!C->strength_reduction()) { + // Change return type of call to scalarized return + const TypeFunc* tf = call->_tf; + const TypeTuple* domain = OptoRuntime::store_inline_type_fields_Type()->domain_cc(); + const TypeFunc* new_tf = TypeFunc::make(tf->domain_sig(), tf->domain_cc(), tf->range_sig(), domain); + call->_tf = new_tf; + _gvn.set_type(call, call->Value(&_gvn)); + _gvn.set_type(ret, ret->Value(&_gvn)); + // Don't add store to buffer call if we are strength reducing + if (!C->strength_reduction()) { + ideal.if_then(ret, BoolTest::eq, ideal.makecon(TypePtr::NULL_PTR)); { + // Return value is null + ideal.set(res, makecon(TypePtr::NULL_PTR)); + } ideal.else_(); { + // Return value is non-null + sync_kit(ideal); + Node* store_to_buf_call = make_runtime_call(RC_NO_LEAF | RC_NO_IO, OptoRuntime::store_inline_type_fields_Type(), StubRoutines::store_inline_type_fields_to_buf(), @@ -2072,14 +2071,14 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p buf = _gvn.transform(new CheckCastPPNode(control(), buf, buf_type)); ideal.set(res, buf); - } else { - for (uint i = TypeFunc::Parms+1; i < domain->cnt(); i++) { - Node* proj =_gvn.transform(new ProjNode(call, i)); - } - ideal.set(res, ret); + ideal.sync_kit(this); + } ideal.end_if(); + } else { + for (uint i = TypeFunc::Parms+1; i < domain->cnt(); i++) { + Node* proj =_gvn.transform(new ProjNode(call, i)); } - ideal.sync_kit(this); - } ideal.end_if(); + ideal.set(res, ret); + } sync_kit(ideal); ret = _gvn.transform(ideal.value(res)); } From 32fae207c83ce5d5b4a35b5c85c3b641ff08a54e Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Wed, 17 Dec 2025 14:52:42 +0100 Subject: [PATCH 11/13] JDK-8369045 remove tests from problemlist --- test/jdk/ProblemList-Xcomp.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt index 01d38f1fd94..5ed171a1fea 100644 --- a/test/jdk/ProblemList-Xcomp.txt +++ b/test/jdk/ProblemList-Xcomp.txt @@ -29,7 +29,3 @@ java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/lang/reflect/callerCache/ReflectionCallerCacheTest.java 8332028 generic-all -valhalla/valuetypes/ObjectMethodsViaCondy.java 8369045 macosx-all -valhalla/valuetypes/ObjectNewInstance.java 8369045 macosx-all -valhalla/valuetypes/ProxyTest.java 8369045 macosx-all -valhalla/valuetypes/WeakReferenceTest.java 8369045 macosx-all From 7790bef43c385ba8b08e24da46252b77aff389b6 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Wed, 17 Dec 2025 15:06:29 +0100 Subject: [PATCH 12/13] JDK-8369045 remove another test from problemlist --- test/hotspot/jtreg/ProblemList-enable-preview.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList-enable-preview.txt b/test/hotspot/jtreg/ProblemList-enable-preview.txt index 72a368612ac..1b38feeb51e 100644 --- a/test/hotspot/jtreg/ProblemList-enable-preview.txt +++ b/test/hotspot/jtreg/ProblemList-enable-preview.txt @@ -35,7 +35,6 @@ compiler/c2/irTests/stable/StableRefFinalTest.java compiler/c2/irTests/stable/StableRefPlainTest.java 8372700 generic-all compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java 8372605 generic-all compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java 8372604 generic-all -runtime/exceptionMsgs/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsExceptionTest.java#id1 8369045 macosx-aarch64 # Runtime (all Valhalla): runtime/cds/NonBootLoaderClasses.java 8373596 generic-all From b0c496af01696252de3c6c27e171a4a72802f960 Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 22 Dec 2025 10:24:59 +0100 Subject: [PATCH 13/13] JDK-8369045 remove more tests from problemlist --- test/jdk/ProblemList-enable-preview.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/jdk/ProblemList-enable-preview.txt b/test/jdk/ProblemList-enable-preview.txt index 75535845569..a92fed8260f 100644 --- a/test/jdk/ProblemList-enable-preview.txt +++ b/test/jdk/ProblemList-enable-preview.txt @@ -31,9 +31,6 @@ java/foreign/TestRestricted.java 8372744 generic-all java/lang/module/ModuleReader/ModuleReaderTest.java 8372744 generic-all java/lang/module/ModuleReader/patched/PatchedModuleReaderTest.java 8372744 generic-all -java/lang/StackWalker/LocalsAndOperands.java#id0 8369045 macosx-all -java/lang/StackWalker/LocalsAndOperands.java#id1 8369045 macosx-all -java/lang/StringBuilder/CompactStringBuilder.java 8369045 macosx-all java/foreign/sharedclosejvmti/TestSharedCloseJvmti.java 8372745 generic-all java/util/Map/MapBinToFromTreeTest.java 8373878 linux-aarch64 java/util/NavigableMap/LockStep.java 8372824 generic-all