diff --git a/src/hotspot/share/opto/inlinetypenode.cpp b/src/hotspot/share/opto/inlinetypenode.cpp index 6e701a27599..68a664c23fe 100644 --- a/src/hotspot/share/opto/inlinetypenode.cpp +++ b/src/hotspot/share/opto/inlinetypenode.cpp @@ -865,6 +865,8 @@ Node* InlineTypeNode::emit_substitutability_check(GraphKit* kit, Node* lhs, Node Node* cur_lhs_field = cur_lhs->field_value(field_idx); Node* cur_rhs_field = cur_rhs->field_value(field_idx); + InlineTypeNode* cur_lhs_inline = cur_lhs_field->isa_InlineType(); + InlineTypeNode* cur_rhs_inline = cur_rhs_field->isa_InlineType(); Node* preprocess = emit_substitutability_check_pointer(kit, result, cur_lhs_field, cur_rhs_field); if (kit->stopped()) { @@ -951,21 +953,30 @@ Node* InlineTypeNode::emit_substitutability_check(GraphKit* kit, Node* lhs, Node Node* vk_klass = igvn.makecon(vk_klass_type); // Both must be vk - Node* not_vk = kit->top(); - cur_lhs_field = kit->gen_checkcast(cur_lhs_field, vk_klass, ¬_vk); - if (!not_vk->is_top()) { - region->add_req(not_vk); - result->add_req(igvn.intcon(0)); + // InlineTypeNodes need no (new) field loads, so we can use the uncasted value below. + if (cur_lhs_inline != nullptr && cur_lhs_inline->inline_klass() == vk) { + cur_lhs_field = cur_lhs_inline; + } else { + Node* not_vk = kit->top(); + cur_lhs_field = kit->gen_checkcast(cur_lhs_field, vk_klass, ¬_vk); + if (!not_vk->is_top()) { + region->add_req(not_vk); + result->add_req(igvn.intcon(0)); + } + cur_lhs_field = InlineTypeNode::make_from_oop(kit, cur_lhs_field, vk); } - cur_lhs_field = InlineTypeNode::make_from_oop(kit, cur_lhs_field, vk); - not_vk = kit->top(); - cur_rhs_field = kit->gen_checkcast(cur_rhs_field, vk_klass, ¬_vk); - if (!not_vk->is_top()) { - region->add_req(not_vk); - result->add_req(igvn.intcon(0)); + if (cur_rhs_inline != nullptr && cur_rhs_inline->inline_klass() == vk) { + cur_rhs_field = cur_rhs_inline; + } else { + Node* not_vk = kit->top(); + cur_rhs_field = kit->gen_checkcast(cur_rhs_field, vk_klass, ¬_vk); + if (!not_vk->is_top()) { + region->add_req(not_vk); + result->add_req(igvn.intcon(0)); + } + cur_rhs_field = InlineTypeNode::make_from_oop(kit, cur_rhs_field, vk); } - cur_rhs_field = InlineTypeNode::make_from_oop(kit, cur_rhs_field, vk); if (!kit->stopped()) { // Push the expanded InlineTypeNodes for processing later diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java index 71ece91bd46..ef64dc12e78 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java @@ -5479,4 +5479,36 @@ public static void testBadCastToInlineKlass_verifier() { // expected } } + + // TODO 8376254: C1 bails out if the type of the nullable flat field is uninitialized + static ObjectHolderHolder objectHolderHolder = new ObjectHolderHolder(); + + static value class ObjectHolder { + Object obj = new Object(); + } + + static value class ObjectHolderHolder { + ObjectHolder objectHolder = new ObjectHolder(); + } + + // Test that acmp expansion works with field of exact Object type + @Test + @IR(failOn = {STATIC_CALL_OF_METHOD, "isSubstitutable.*"}, + counts = {IRNode.ALLOC, "= 2"}) // The two Object allocations + static boolean testAcmp() { + Object lhs = null; + Object rhs = null; + for (int i = 0; i < 10; i++) { + if ((i & 1) == 0) { + lhs = new ObjectHolderHolder(); + rhs = new ObjectHolderHolder(); + } + } + return lhs == rhs; + } + + @Run(test = "testAcmp") + public void runTestAcmp() { + Asserts.assertFalse(testAcmp()); + } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizePtrCompare.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizePtrCompare.java index 3f5dca15f0f..df4b3d91f0b 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizePtrCompare.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOptimizePtrCompare.java @@ -164,6 +164,7 @@ static MyValue2 notInlined5(MyValue2 v) { return v; } + // TODO 8376254: C1 bails out if the type of the nullable flat field is uninitialized @Test(allowNotCompilable = true) @IR(applyIfAnd = {"InlineTypePassFieldsAsArgs", "true", "InlineTypeReturnedAsFields", "true"}, failOn = {IRNode.CMP_P_OR_N}) @IR(applyIfAnd = {"InlineTypePassFieldsAsArgs", "false", "InlineTypeReturnedAsFields", "true"}, counts = {IRNode.CMP_P_OR_N, "4", IRNode.CMP_I, "2"})