Skip to content

Commit 1e44a3b

Browse files
committedOct 27, 2020
8255230: [lworld] C2 compilation fails with assert(!inline_alloc) failed: Inline type allocations should not have safepoint uses
1 parent 9b5f54a commit 1e44a3b

File tree

6 files changed

+137
-33
lines changed

6 files changed

+137
-33
lines changed
 

‎src/hotspot/share/opto/compile.cpp

+15-11
Original file line numberDiff line numberDiff line change
@@ -1933,23 +1933,26 @@ static bool return_val_keeps_allocations_alive(Node* ret_val) {
19331933
return some_allocations;
19341934
}
19351935

1936-
void Compile::process_inline_types(PhaseIterGVN &igvn, bool post_ea) {
1936+
void Compile::process_inline_types(PhaseIterGVN &igvn, bool remove) {
19371937
// Make inline types scalar in safepoints
19381938
for (int i = _inline_type_nodes->length()-1; i >= 0; i--) {
19391939
InlineTypeBaseNode* vt = _inline_type_nodes->at(i)->as_InlineTypeBase();
19401940
vt->make_scalar_in_safepoints(&igvn);
19411941
}
1942-
// Remove InlineTypePtr nodes only after EA to give scalar replacement a chance
1943-
// to remove buffer allocations. InlineType nodes are kept until loop opts and
1944-
// removed via InlineTypeNode::remove_redundant_allocations.
1945-
if (post_ea) {
1942+
if (remove) {
1943+
// Remove inline type nodes
19461944
while (_inline_type_nodes->length() > 0) {
19471945
InlineTypeBaseNode* vt = _inline_type_nodes->pop()->as_InlineTypeBase();
1948-
if (vt->is_InlineTypePtr()) {
1946+
if (vt->outcnt() == 0) {
1947+
igvn.remove_dead_node(vt);
1948+
} else if (vt->is_InlineTypePtr()) {
19491949
igvn.replace_node(vt, vt->get_oop());
1950+
} else {
1951+
igvn.replace_node(vt, igvn.C->top());
19501952
}
19511953
}
19521954
}
1955+
// TODO only check once we are removing, right?
19531956
// Make sure that the return value does not keep an unused allocation alive
19541957
if (tf()->returns_inline_type_as_fields()) {
19551958
Node* ret = NULL;
@@ -2570,11 +2573,6 @@ void Compile::Optimize() {
25702573
}
25712574
}
25722575

2573-
if (_inline_type_nodes->length() > 0) {
2574-
// Process inline types again now that EA might have simplified the graph
2575-
process_inline_types(igvn, /* post_ea= */ true);
2576-
}
2577-
25782576
// Loop transforms on the ideal graph. Range Check Elimination,
25792577
// peeling, unrolling, etc.
25802578

@@ -2659,6 +2657,12 @@ void Compile::Optimize() {
26592657
bs->verify_gc_barriers(this, BarrierSetC2::BeforeMacroExpand);
26602658
#endif
26612659

2660+
if (_inline_type_nodes->length() > 0) {
2661+
// Process inline type nodes again and remove them. From here
2662+
// on we don't need to keep track of field values anymore.
2663+
process_inline_types(igvn, /* remove= */ true);
2664+
}
2665+
26622666
{
26632667
TracePhase tp("macroExpand", &timers[_t_macroExpand]);
26642668
PhaseMacroExpand mex(igvn);

‎src/hotspot/share/opto/compile.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ class Compile : public Phase {
724724
// Keep track of inline type nodes for later processing
725725
void add_inline_type(Node* n);
726726
void remove_inline_type(Node* n);
727-
void process_inline_types(PhaseIterGVN &igvn, bool post_ea = false);
727+
void process_inline_types(PhaseIterGVN &igvn, bool remove = false);
728728

729729
void adjust_flattened_array_access_aliases(PhaseIterGVN& igvn);
730730

‎src/hotspot/share/opto/inlinetypenode.cpp

+1-11
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,6 @@ Node* InlineTypeNode::Ideal(PhaseGVN* phase, bool can_reshape) {
860860
}
861861

862862
// Search for multiple allocations of this inline type and try to replace them by dominating allocations.
863-
// Then unlink the inline type node and remove it.
864863
void InlineTypeNode::remove_redundant_allocations(PhaseIterGVN* igvn, PhaseIdealLoop* phase) {
865864
// Search for allocations of this inline type. Ignore scalar replaceable ones, they
866865
// will be removed anyway and changing the memory chain will confuse other optimizations.
@@ -898,23 +897,14 @@ void InlineTypeNode::remove_redundant_allocations(PhaseIterGVN* igvn, PhaseIdeal
898897
for (DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++) {
899898
Node* out = fast_out(i);
900899
if (out->is_InlineType()) {
901-
// Unlink and recursively process inline type users
900+
// Recursively process inline type users
902901
igvn->rehash_node_delayed(out);
903-
int nb = out->replace_edge(this, igvn->C->top());
904902
out->as_InlineType()->remove_redundant_allocations(igvn, phase);
905-
--i; imax -= nb;
906903
} else if (out->isa_Allocate() != NULL) {
907904
// Unlink AllocateNode
908905
assert(out->in(AllocateNode::InlineTypeNode) == this, "should be linked");
909906
igvn->replace_input_of(out, AllocateNode::InlineTypeNode, igvn->C->top());
910907
--i; --imax;
911-
} else {
912-
#ifdef ASSERT
913-
// The inline type should not have any other users at this time
914-
out->dump();
915-
assert(false, "unexpected user of inline type");
916-
#endif
917908
}
918909
}
919-
igvn->remove_dead_node(this);
920910
}

‎src/hotspot/share/opto/loopopts.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,6 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) {
16181618
// Remove multiple allocations of the same inline type
16191619
if (n->is_InlineType()) {
16201620
n->as_InlineType()->remove_redundant_allocations(&_igvn, this);
1621-
return; // n is now dead
16221621
}
16231622

16241623
// Check for Opaque2's who's loop has disappeared - who's input is in the

‎src/hotspot/share/opto/split_if.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,6 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) {
239239
rtype = TypeLong::INT;
240240
}
241241

242-
// Inline types should not be split through Phis but each value input
243-
// needs to be merged individually. At this point, inline types should
244-
// only be used by AllocateNodes. Try to remove redundant allocations
245-
// and unlink the now dead inline type node.
246-
if (n->is_InlineType()) {
247-
n->as_InlineType()->remove_redundant_allocations(&_igvn, this);
248-
return true; // n is now dead
249-
}
250-
251242
// Now actually split-up this guy. One copy per control path merging.
252243
Node *phi = PhiNode::make_blank(blk1, n);
253244
for( uint j = 1; j < blk1->req(); j++ ) {

‎test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java

+120
Original file line numberDiff line numberDiff line change
@@ -3410,4 +3410,124 @@ public void test125_verifier(boolean warmup) {
34103410
test125(testValue1);
34113411
test125(null);
34123412
}
3413+
3414+
// Test inline type that can only be scalarized after loop opts
3415+
@Test(failOn = ALLOC + LOAD + STORE)
3416+
@Warmup(10000)
3417+
public long test126(boolean trap) {
3418+
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3419+
MyValue2.ref val = null;
3420+
3421+
for (int i = 0; i < 4; i++) {
3422+
if ((i % 2) == 0) {
3423+
val = nonNull;
3424+
}
3425+
}
3426+
// 'val' is always non-null here but that's only known after loop opts
3427+
if (trap) {
3428+
// Uncommon trap with an inline input that can only be scalarized after loop opts
3429+
return val.hash();
3430+
}
3431+
return 0;
3432+
}
3433+
3434+
@DontCompile
3435+
public void test126_verifier(boolean warmup) {
3436+
long res = test126(false);
3437+
Asserts.assertEquals(res, 0L);
3438+
if (!warmup) {
3439+
res = test126(true);
3440+
Asserts.assertEquals(res, testValue2.hash());
3441+
}
3442+
}
3443+
3444+
// Same as test126 but with interface type
3445+
@Test(failOn = ALLOC + LOAD + STORE)
3446+
@Warmup(10000)
3447+
public long test127(boolean trap) {
3448+
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3449+
MyInterface val = null;
3450+
3451+
for (int i = 0; i < 4; i++) {
3452+
if ((i % 2) == 0) {
3453+
val = nonNull;
3454+
}
3455+
}
3456+
// 'val' is always non-null here but that's only known after loop opts
3457+
if (trap) {
3458+
// Uncommon trap with an inline input that can only be scalarized after loop opts
3459+
return val.hash();
3460+
}
3461+
return 0;
3462+
}
3463+
3464+
@DontCompile
3465+
public void test127_verifier(boolean warmup) {
3466+
long res = test127(false);
3467+
Asserts.assertEquals(res, 0L);
3468+
if (!warmup) {
3469+
res = test127(true);
3470+
Asserts.assertEquals(res, testValue2.hash());
3471+
}
3472+
}
3473+
3474+
// Test inline type that can only be scalarized after CCP
3475+
@Test(failOn = ALLOC + LOAD + STORE)
3476+
@Warmup(10000)
3477+
public long test128(boolean trap) {
3478+
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3479+
MyValue2.ref val = null;
3480+
3481+
int limit = 2;
3482+
for (; limit < 4; limit *= 2);
3483+
for (int i = 2; i < limit; i++) {
3484+
val = nonNull;
3485+
}
3486+
// 'val' is always non-null here but that's only known after CCP
3487+
if (trap) {
3488+
// Uncommon trap with an inline input that can only be scalarized after CCP
3489+
return val.hash();
3490+
}
3491+
return 0;
3492+
}
3493+
3494+
@DontCompile
3495+
public void test128_verifier(boolean warmup) {
3496+
long res = test128(false);
3497+
Asserts.assertEquals(res, 0L);
3498+
if (!warmup) {
3499+
res = test128(true);
3500+
Asserts.assertEquals(res, testValue2.hash());
3501+
}
3502+
}
3503+
3504+
// Same as test128 but with interface type
3505+
@Test(failOn = ALLOC + LOAD + STORE)
3506+
@Warmup(10000)
3507+
public long test129(boolean trap) {
3508+
MyValue2 nonNull = MyValue2.createWithFieldsInline(rI, rD);
3509+
MyInterface val = null;
3510+
3511+
int limit = 2;
3512+
for (; limit < 4; limit *= 2);
3513+
for (int i = 0; i < limit; i++) {
3514+
val = nonNull;
3515+
}
3516+
// 'val' is always non-null here but that's only known after CCP
3517+
if (trap) {
3518+
// Uncommon trap with an inline input that can only be scalarized after CCP
3519+
return val.hash();
3520+
}
3521+
return 0;
3522+
}
3523+
3524+
@DontCompile
3525+
public void test129_verifier(boolean warmup) {
3526+
long res = test129(false);
3527+
Asserts.assertEquals(res, 0L);
3528+
if (!warmup) {
3529+
res = test129(true);
3530+
Asserts.assertEquals(res, testValue2.hash());
3531+
}
3532+
}
34133533
}

0 commit comments

Comments
 (0)
Please sign in to comment.