8352963: [REDO] Missing late inline cleanup causes compiler/vectorapi/VectorLogicalOpIdentityTest.java IR failure

Reviewed-by: vlivanov, thartmann
This commit is contained in:
Damon Fenacci 2025-04-08 13:05:15 +00:00
parent dfa79c3730
commit d9f2e69215
7 changed files with 95 additions and 53 deletions

View File

@ -470,7 +470,7 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator {
virtual void do_late_inline();
virtual void set_callee_method(ciMethod* m) {
assert(_callee == nullptr, "repeated inlining attempt");
assert(_callee == nullptr || _callee == m, "repeated inline attempt with different callee");
_callee = m;
}
@ -987,8 +987,8 @@ CallGenerator* CallGenerator::for_method_handle_call(JVMState* jvms, ciMethod* c
Compile* C = Compile::current();
bool should_delay = C->should_delay_inlining();
if (cg != nullptr) {
if (should_delay) {
return CallGenerator::for_late_inline(callee, cg);
if (should_delay && IncrementalInlineMH) {
return CallGenerator::for_mh_late_inline(caller, callee, input_not_const);
} else {
return cg;
}

View File

@ -1091,6 +1091,15 @@ void CallJavaNode::dump_compact_spec(outputStream* st) const {
}
#endif
void CallJavaNode::register_for_late_inline() {
if (generator() != nullptr) {
Compile::current()->prepend_late_inline(generator());
set_generator(nullptr);
} else {
assert(false, "repeated inline attempt");
}
}
//=============================================================================
uint CallStaticJavaNode::size_of() const { return sizeof(*this); }
bool CallStaticJavaNode::cmp( const Node &n ) const {
@ -1101,26 +1110,35 @@ bool CallStaticJavaNode::cmp( const Node &n ) const {
Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
CallGenerator* cg = generator();
if (can_reshape && cg != nullptr) {
assert(IncrementalInlineMH, "required");
assert(cg->call_node() == this, "mismatch");
assert(cg->is_mh_late_inline(), "not virtual");
if (cg->is_mh_late_inline()) {
assert(IncrementalInlineMH, "required");
assert(cg->call_node() == this, "mismatch");
assert(cg->method()->is_method_handle_intrinsic(), "required");
// Check whether this MH handle call becomes a candidate for inlining.
ciMethod* callee = cg->method();
vmIntrinsics::ID iid = callee->intrinsic_id();
if (iid == vmIntrinsics::_invokeBasic) {
if (in(TypeFunc::Parms)->Opcode() == Op_ConP) {
phase->C->prepend_late_inline(cg);
set_generator(nullptr);
// Check whether this MH handle call becomes a candidate for inlining.
ciMethod* callee = cg->method();
vmIntrinsics::ID iid = callee->intrinsic_id();
if (iid == vmIntrinsics::_invokeBasic) {
if (in(TypeFunc::Parms)->Opcode() == Op_ConP) {
register_for_late_inline();
}
} else if (iid == vmIntrinsics::_linkToNative) {
// never retry
} else {
assert(callee->has_member_arg(), "wrong type of call?");
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
register_for_late_inline();
phase->C->inc_number_of_mh_late_inlines();
}
}
} else if (iid == vmIntrinsics::_linkToNative) {
// never retry
} else {
assert(callee->has_member_arg(), "wrong type of call?");
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
phase->C->prepend_late_inline(cg);
set_generator(nullptr);
assert(IncrementalInline, "required");
assert(!cg->method()->is_method_handle_intrinsic(), "required");
if (phase->C->print_inlining()) {
phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE,
"static call node changed: trying again");
}
register_for_late_inline();
}
}
return CallNode::Ideal(phase, can_reshape);
@ -1189,39 +1207,46 @@ bool CallDynamicJavaNode::cmp( const Node &n ) const {
Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
CallGenerator* cg = generator();
if (can_reshape && cg != nullptr) {
assert(IncrementalInlineVirtual, "required");
assert(cg->call_node() == this, "mismatch");
assert(cg->is_virtual_late_inline(), "not virtual");
if (cg->is_virtual_late_inline()) {
assert(IncrementalInlineVirtual, "required");
assert(cg->call_node() == this, "mismatch");
// Recover symbolic info for method resolution.
ciMethod* caller = jvms()->method();
ciBytecodeStream iter(caller);
iter.force_bci(jvms()->bci());
// Recover symbolic info for method resolution.
ciMethod* caller = jvms()->method();
ciBytecodeStream iter(caller);
iter.force_bci(jvms()->bci());
bool not_used1;
ciSignature* not_used2;
ciMethod* orig_callee = iter.get_method(not_used1, &not_used2); // callee in the bytecode
ciKlass* holder = iter.get_declared_method_holder();
if (orig_callee->is_method_handle_intrinsic()) {
assert(_override_symbolic_info, "required");
orig_callee = method();
holder = method()->holder();
}
bool not_used1;
ciSignature* not_used2;
ciMethod* orig_callee = iter.get_method(not_used1, &not_used2); // callee in the bytecode
ciKlass* holder = iter.get_declared_method_holder();
if (orig_callee->is_method_handle_intrinsic()) {
assert(_override_symbolic_info, "required");
orig_callee = method();
holder = method()->holder();
}
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
Node* receiver_node = in(TypeFunc::Parms);
const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr();
Node* receiver_node = in(TypeFunc::Parms);
const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr();
int not_used3;
bool call_does_dispatch;
ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/,
call_does_dispatch, not_used3); // out-parameters
if (!call_does_dispatch) {
// Register for late inlining.
cg->set_callee_method(callee);
phase->C->prepend_late_inline(cg); // MH late inlining prepends to the list, so do the same
set_generator(nullptr);
int not_used3;
bool call_does_dispatch;
ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/,
call_does_dispatch, not_used3); // out-parameters
if (!call_does_dispatch) {
// Register for late inlining.
cg->set_callee_method(callee);
register_for_late_inline(); // MH late inlining prepends to the list, so do the same
}
} else {
assert(IncrementalInline, "required");
if (phase->C->print_inlining()) {
phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE,
"dynamic call node changed: trying again");
}
register_for_late_inline();
}
}
return CallNode::Ideal(phase, can_reshape);

View File

@ -790,6 +790,7 @@ public:
void set_arg_escape(bool f) { _arg_escape = f; }
bool arg_escape() const { return _arg_escape; }
void copy_call_debug_info(PhaseIterGVN* phase, SafePointNode *sfpt);
void register_for_late_inline();
DEBUG_ONLY( bool validate_symbolic_info() const; )

View File

@ -2085,6 +2085,7 @@ bool Compile::inline_incrementally_one() {
for (int i = 0; i < _late_inlines.length(); i++) {
_late_inlines_pos = i+1;
CallGenerator* cg = _late_inlines.at(i);
bool is_scheduled_for_igvn_before = C->igvn_worklist()->member(cg->call_node());
bool does_dispatch = cg->is_virtual_late_inline() || cg->is_mh_late_inline();
if (inlining_incrementally() || does_dispatch) { // a call can be either inlined or strength-reduced to a direct call
cg->do_late_inline();
@ -2095,6 +2096,16 @@ bool Compile::inline_incrementally_one() {
_late_inlines_pos = i+1; // restore the position in case new elements were inserted
print_method(PHASE_INCREMENTAL_INLINE_STEP, 3, cg->call_node());
break; // process one call site at a time
} else {
bool is_scheduled_for_igvn_after = C->igvn_worklist()->member(cg->call_node());
if (!is_scheduled_for_igvn_before && is_scheduled_for_igvn_after) {
// Avoid potential infinite loop if node already in the IGVN list
assert(false, "scheduled for IGVN during inlining attempt");
} else {
// Ensure call node has not disappeared from IGVN worklist during a failed inlining attempt
assert(!is_scheduled_for_igvn_before || is_scheduled_for_igvn_after, "call node removed from IGVN list during inlining pass");
cg->call_node()->set_generator(cg);
}
}
} else {
// Ignore late inline direct calls when inlining is not allowed.

View File

@ -56,7 +56,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x
compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64
compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all
compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, 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
@ -32,7 +32,7 @@ import java.nio.ByteOrder;
/**
* @test
* @bug 8325520
* @bug 8325520 8302459
* @library /test/lib /
* @summary Don't allow folding of Load/Store vectors when using incompatible indices or masks
* @modules jdk.incubator.vector
@ -1398,7 +1398,12 @@ public class VectorGatherMaskFoldingTest {
public static void main(String[] args) {
TestFramework testFramework = new TestFramework();
testFramework.setDefaultWarmup(10000)
.addFlags("--add-modules=jdk.incubator.vector", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+IncrementalInlineForceCleanup")
.addFlags("--add-modules=jdk.incubator.vector")
.start();
testFramework = new TestFramework();
testFramework.setDefaultWarmup(10000)
.addFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation")
.start();
}
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2022, 2023, Arm Limited. All rights reserved.
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, 2025, 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
@ -41,7 +41,7 @@ import jdk.test.lib.Utils;
/**
* @test
* @bug 8288294
* @bug 8288294 8302459
* @key randomness
* @library /test/lib /
* @summary Add identity transformations for vector logic operations
@ -761,5 +761,6 @@ public class VectorLogicalOpIdentityTest {
public static void main(String[] args) {
TestFramework.runWithFlags("--add-modules=jdk.incubator.vector");
TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation");
}
}