diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index cc8ce550ec8..c9a7f31835b 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -667,6 +667,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), @@ -2775,6 +2776,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; @@ -2792,6 +2794,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 0b9e745df1b..03ceb8798f0 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 @@ -607,6 +608,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 7fe8383f6f3..353c4a0b4d6 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" @@ -2039,45 +2040,52 @@ 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)); - - 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; + // 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(), + 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.sync_kit(this); - } ideal.end_if(); + ideal.set(res, buf); + 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.set(res, ret); + } sync_kit(ideal); ret = _gvn.transform(ideal.value(res)); } @@ -2218,9 +2226,19 @@ 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 type 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) { diff --git a/test/hotspot/jtreg/ProblemList-enable-preview.txt b/test/hotspot/jtreg/ProblemList-enable-preview.txt index bcc47f76255..e71ce3bf36e 100644 --- a/test/hotspot/jtreg/ProblemList-enable-preview.txt +++ b/test/hotspot/jtreg/ProblemList-enable-preview.txt @@ -34,7 +34,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 8372605 generic-all -runtime/exceptionMsgs/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsExceptionTest.java#id1 8369045 macosx-aarch64 # Runtime (all Valhalla): runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java 8372602 generic-all 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 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