Skip to content

Commit 2e4d7d1

Browse files
dafedafeVladimir Ivanov
andcommitted
8302459: Missing late inline cleanup causes compiler/vectorapi/VectorLogicalOpIdentityTest.java IR failure
Co-authored-by: Vladimir Ivanov <vlivanov@openjdk.org> Reviewed-by: thartmann, vlivanov
1 parent 1a8c8e0 commit 2e4d7d1

File tree

7 files changed

+96
-54
lines changed

7 files changed

+96
-54
lines changed

src/hotspot/share/opto/callGenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator {
470470
virtual void do_late_inline();
471471

472472
virtual void set_callee_method(ciMethod* m) {
473-
assert(_callee == nullptr, "repeated inlining attempt");
473+
assert(_callee == nullptr || _callee == m, "repeated inline attempt with different callee");
474474
_callee = m;
475475
}
476476

src/hotspot/share/opto/callnode.cpp

Lines changed: 72 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,6 +1091,15 @@ void CallJavaNode::dump_compact_spec(outputStream* st) const {
10911091
}
10921092
#endif
10931093

1094+
void CallJavaNode::register_for_late_inline() {
1095+
if (generator() != nullptr) {
1096+
Compile::current()->prepend_late_inline(generator());
1097+
set_generator(nullptr);
1098+
} else {
1099+
assert(false, "repeated inline attempt");
1100+
}
1101+
}
1102+
10941103
//=============================================================================
10951104
uint CallStaticJavaNode::size_of() const { return sizeof(*this); }
10961105
bool CallStaticJavaNode::cmp( const Node &n ) const {
@@ -1101,26 +1110,35 @@ bool CallStaticJavaNode::cmp( const Node &n ) const {
11011110
Node* CallStaticJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
11021111
CallGenerator* cg = generator();
11031112
if (can_reshape && cg != nullptr) {
1104-
assert(IncrementalInlineMH, "required");
1105-
assert(cg->call_node() == this, "mismatch");
1106-
assert(cg->is_mh_late_inline(), "not virtual");
1107-
1108-
// Check whether this MH handle call becomes a candidate for inlining.
1109-
ciMethod* callee = cg->method();
1110-
vmIntrinsics::ID iid = callee->intrinsic_id();
1111-
if (iid == vmIntrinsics::_invokeBasic) {
1112-
if (in(TypeFunc::Parms)->Opcode() == Op_ConP) {
1113-
phase->C->prepend_late_inline(cg);
1114-
set_generator(nullptr);
1113+
if (cg->is_mh_late_inline()) {
1114+
assert(IncrementalInlineMH, "required");
1115+
assert(cg->call_node() == this, "mismatch");
1116+
assert(cg->method()->is_method_handle_intrinsic(), "required");
1117+
1118+
// Check whether this MH handle call becomes a candidate for inlining.
1119+
ciMethod* callee = cg->method();
1120+
vmIntrinsics::ID iid = callee->intrinsic_id();
1121+
if (iid == vmIntrinsics::_invokeBasic) {
1122+
if (in(TypeFunc::Parms)->Opcode() == Op_ConP) {
1123+
register_for_late_inline();
1124+
}
1125+
} else if (iid == vmIntrinsics::_linkToNative) {
1126+
// never retry
1127+
} else {
1128+
assert(callee->has_member_arg(), "wrong type of call?");
1129+
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
1130+
register_for_late_inline();
1131+
phase->C->inc_number_of_mh_late_inlines();
1132+
}
11151133
}
1116-
} else if (iid == vmIntrinsics::_linkToNative) {
1117-
// never retry
11181134
} else {
1119-
assert(callee->has_member_arg(), "wrong type of call?");
1120-
if (in(TypeFunc::Parms + callee->arg_size() - 1)->Opcode() == Op_ConP) {
1121-
phase->C->prepend_late_inline(cg);
1122-
set_generator(nullptr);
1135+
assert(IncrementalInline, "required");
1136+
assert(!cg->method()->is_method_handle_intrinsic(), "required");
1137+
if (phase->C->print_inlining()) {
1138+
phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE,
1139+
"static call node changed: trying again");
11231140
}
1141+
register_for_late_inline();
11241142
}
11251143
}
11261144
return CallNode::Ideal(phase, can_reshape);
@@ -1189,39 +1207,46 @@ bool CallDynamicJavaNode::cmp( const Node &n ) const {
11891207
Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) {
11901208
CallGenerator* cg = generator();
11911209
if (can_reshape && cg != nullptr) {
1192-
assert(IncrementalInlineVirtual, "required");
1193-
assert(cg->call_node() == this, "mismatch");
1194-
assert(cg->is_virtual_late_inline(), "not virtual");
1195-
1196-
// Recover symbolic info for method resolution.
1197-
ciMethod* caller = jvms()->method();
1198-
ciBytecodeStream iter(caller);
1199-
iter.force_bci(jvms()->bci());
1200-
1201-
bool not_used1;
1202-
ciSignature* not_used2;
1203-
ciMethod* orig_callee = iter.get_method(not_used1, &not_used2); // callee in the bytecode
1204-
ciKlass* holder = iter.get_declared_method_holder();
1205-
if (orig_callee->is_method_handle_intrinsic()) {
1206-
assert(_override_symbolic_info, "required");
1207-
orig_callee = method();
1208-
holder = method()->holder();
1209-
}
1210+
if (cg->is_virtual_late_inline()) {
1211+
assert(IncrementalInlineVirtual, "required");
1212+
assert(cg->call_node() == this, "mismatch");
1213+
1214+
// Recover symbolic info for method resolution.
1215+
ciMethod* caller = jvms()->method();
1216+
ciBytecodeStream iter(caller);
1217+
iter.force_bci(jvms()->bci());
1218+
1219+
bool not_used1;
1220+
ciSignature* not_used2;
1221+
ciMethod* orig_callee = iter.get_method(not_used1, &not_used2); // callee in the bytecode
1222+
ciKlass* holder = iter.get_declared_method_holder();
1223+
if (orig_callee->is_method_handle_intrinsic()) {
1224+
assert(_override_symbolic_info, "required");
1225+
orig_callee = method();
1226+
holder = method()->holder();
1227+
}
12101228

1211-
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
1229+
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
12121230

1213-
Node* receiver_node = in(TypeFunc::Parms);
1214-
const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr();
1231+
Node* receiver_node = in(TypeFunc::Parms);
1232+
const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr();
12151233

1216-
int not_used3;
1217-
bool call_does_dispatch;
1218-
ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/,
1219-
call_does_dispatch, not_used3); // out-parameters
1220-
if (!call_does_dispatch) {
1221-
// Register for late inlining.
1222-
cg->set_callee_method(callee);
1223-
phase->C->prepend_late_inline(cg); // MH late inlining prepends to the list, so do the same
1224-
set_generator(nullptr);
1234+
int not_used3;
1235+
bool call_does_dispatch;
1236+
ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/,
1237+
call_does_dispatch, not_used3); // out-parameters
1238+
if (!call_does_dispatch) {
1239+
// Register for late inlining.
1240+
cg->set_callee_method(callee);
1241+
register_for_late_inline(); // MH late inlining prepends to the list, so do the same
1242+
}
1243+
} else {
1244+
assert(IncrementalInline, "required");
1245+
if (phase->C->print_inlining()) {
1246+
phase->C->inline_printer()->record(cg->method(), cg->call_node()->jvms(), InliningResult::FAILURE,
1247+
"dynamic call node changed: trying again");
1248+
}
1249+
register_for_late_inline();
12251250
}
12261251
}
12271252
return CallNode::Ideal(phase, can_reshape);

src/hotspot/share/opto/callnode.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -790,6 +790,7 @@ class CallJavaNode : public CallNode {
790790
void set_arg_escape(bool f) { _arg_escape = f; }
791791
bool arg_escape() const { return _arg_escape; }
792792
void copy_call_debug_info(PhaseIterGVN* phase, SafePointNode *sfpt);
793+
void register_for_late_inline();
793794

794795
DEBUG_ONLY( bool validate_symbolic_info() const; )
795796

src/hotspot/share/opto/compile.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,7 @@ bool Compile::inline_incrementally_one() {
20852085
for (int i = 0; i < _late_inlines.length(); i++) {
20862086
_late_inlines_pos = i+1;
20872087
CallGenerator* cg = _late_inlines.at(i);
2088+
bool is_scheduled_for_igvn_before = C->igvn_worklist()->member(cg->call_node());
20882089
bool does_dispatch = cg->is_virtual_late_inline() || cg->is_mh_late_inline();
20892090
if (inlining_incrementally() || does_dispatch) { // a call can be either inlined or strength-reduced to a direct call
20902091
cg->do_late_inline();
@@ -2095,6 +2096,16 @@ bool Compile::inline_incrementally_one() {
20952096
_late_inlines_pos = i+1; // restore the position in case new elements were inserted
20962097
print_method(PHASE_INCREMENTAL_INLINE_STEP, 3, cg->call_node());
20972098
break; // process one call site at a time
2099+
} else {
2100+
bool is_scheduled_for_igvn_after = C->igvn_worklist()->member(cg->call_node());
2101+
if (!is_scheduled_for_igvn_before && is_scheduled_for_igvn_after) {
2102+
// Avoid potential infinite loop if node already in the IGVN list
2103+
assert(false, "scheduled for IGVN during inlining attempt");
2104+
} else {
2105+
// Ensure call node has not disappeared from IGVN worklist during a failed inlining attempt
2106+
assert(!is_scheduled_for_igvn_before || is_scheduled_for_igvn_after, "call node removed from IGVN list during inlining pass");
2107+
cg->call_node()->set_generator(cg);
2108+
}
20982109
}
20992110
} else {
21002111
// Ignore late inline direct calls when inlining is not allowed.

test/hotspot/jtreg/ProblemList.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all
5656
compiler/codecache/jmx/PoolsIndependenceTest.java 8264632 macosx-all
5757

5858
compiler/vectorapi/reshape/TestVectorReinterpret.java 8320897,8348519 aix-ppc64,linux-ppc64le,linux-s390x
59-
compiler/vectorapi/VectorLogicalOpIdentityTest.java 8302459 linux-x64,windows-x64
6059
compiler/vectorapi/VectorRebracket128Test.java 8330538 generic-all
6160

6261
compiler/jvmci/TestUncaughtErrorInCompileMethod.java 8309073 generic-all

test/hotspot/jtreg/compiler/vectorapi/VectorGatherMaskFoldingTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
3232

3333
/**
3434
* @test
35-
* @bug 8325520
35+
* @bug 8325520 8302459
3636
* @library /test/lib /
3737
* @summary Don't allow folding of Load/Store vectors when using incompatible indices or masks
3838
* @modules jdk.incubator.vector
@@ -1398,7 +1398,12 @@ public static void testFloatVectorLoadMaskedStoreVector() {
13981398
public static void main(String[] args) {
13991399
TestFramework testFramework = new TestFramework();
14001400
testFramework.setDefaultWarmup(10000)
1401-
.addFlags("--add-modules=jdk.incubator.vector", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:+IncrementalInlineForceCleanup")
1401+
.addFlags("--add-modules=jdk.incubator.vector")
14021402
.start();
1403+
testFramework = new TestFramework();
1404+
testFramework.setDefaultWarmup(10000)
1405+
.addFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation")
1406+
.start();
1407+
14031408
}
14041409
}

test/hotspot/jtreg/compiler/vectorapi/VectorLogicalOpIdentityTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2022, 2023, Arm Limited. All rights reserved.
3-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
44
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
4141

4242
/**
4343
* @test
44-
* @bug 8288294
44+
* @bug 8288294 8302459
4545
* @key randomness
4646
* @library /test/lib /
4747
* @summary Add identity transformations for vector logic operations
@@ -761,5 +761,6 @@ public static void testMaskXorSame() {
761761

762762
public static void main(String[] args) {
763763
TestFramework.runWithFlags("--add-modules=jdk.incubator.vector");
764+
TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:-TieredCompilation");
764765
}
765766
}

0 commit comments

Comments
 (0)