RFR: 8371716: C2 compilation fails with "Missed optimization opportunity in PhaseIterGVN"
Emanuel Peter
epeter at openjdk.org
Mon Nov 17 07:58:02 UTC 2025
On Fri, 14 Nov 2025 19:57:22 GMT, Marc Chevalier <mchevalier at openjdk.org> wrote:
>> This bug was originally found and reported as a Valhalla problem. It quickly became apparent it has no reason to be Valhalla-specific, while I couldn't prove so. Roland managed to make a mainline reproducer. The explanation details my Valhalla investigation, but it has nothing to do with value classes anyway.
>>
>> # Analysis
>> ## Obervationally
>> ### IGVN
>> During IGVN, in `PhiNode::Value`, a `PhiNode` has 2 inputs. Their types are:
>>
>> in(1): java/lang/Object * (speculative=compiler/valhalla/inlinetypes/MyValue2 (compiler/valhalla/inlinetypes/MyInterface):exact * (inline_depth=4))
>> in(2): java/lang/Object * (speculative=null)
>>
>> We compute the join (HS' meet):
>> https://github.com/openjdk/valhalla/blob/412ec882767d3ee1792d1e0f98da54ff800c60ce/src/hotspot/share/opto/cfgnode.cpp#L1310-L1317
>>
>> t=java/lang/Object * (speculative=compiler/valhalla/inlinetypes/MyValue2 (compiler/valhalla/inlinetypes/MyInterface):exact *)
>>
>> But the current `_type` (of the `PhiNode` as a `TypeNode`) is
>>
>> _type=java/lang/Object * (speculative=compiler/valhalla/inlinetypes/MyValue3 (compiler/valhalla/inlinetypes/MyInterface):exact *)
>>
>> We filter `t` by `_type`
>> https://github.com/openjdk/valhalla/blob/412ec882767d3ee1792d1e0f98da54ff800c60ce/src/hotspot/share/opto/cfgnode.cpp#L1332
>> and we get
>>
>> ft=java/lang/Object *
>>
>> which is what we return. After the end of `Value`, the returned becomes the new `PhiNode`'s `_type`.
>> https://github.com/openjdk/valhalla/blob/412ec882767d3ee1792d1e0f98da54ff800c60ce/src/hotspot/share/opto/phaseX.cpp#L2150-L2164
>> and
>> https://github.com/openjdk/valhalla/blob/412ec882767d3ee1792d1e0f98da54ff800c60ce/src/hotspot/share/opto/node.cpp#L1127-L1133
>>
>>
>> ### Verification
>> On verification, `in(1)`, `in(2)` have the same value, so does `t`. But this time
>>
>> _type=java/lang/Object *
>>
>> and so after filtering `t` by (new) `_type` and we get
>>
>> ft=java/lang/Object * (speculative=compiler/valhalla/inlinetypes/MyValue2 (compiler/valhalla/inlinetypes/MyInterface):exact *)
>>
>> which is retuned. Verification gets angry because the new `ft` is not the same as the previous one.
>>
>> ## But why?!
>> ### Details on type computation
>> In short, we are doing
>>
>> t = typeof(in(1)) / typeof(in(2))
>> ft = t /\ _type (* IGVN *)
>> ft' = t /\ ft (* Verification *)
>>
>> and observing that `ft != ft'`. It seems our lattice doesn't ensure `(a /\ b) /\ b = a /\ b` which is problematic for this kind of verfication that will just "try again a...
>
> For the reproducer, now test.
@marc-chevalier I tried to review the issue at hand, but it is a little tricky because the regression test uses one set of class names and your description another (valhalla reproducer). Would it be possible to adjust the explanation to your mainline reproducer? Or maybe even just annotating your mainline reproducer with comments would help already.
I think it would be easier to review the PR once it is easy to follow the example.
Also: the issue name should be adjusted to say something a bit more specific about the issue. We have a lot of "missed optimization opportunity" issues, and it would be nice to be able to tell them apart easily ;)
-------------
PR Comment: https://git.openjdk.org/jdk/pull/28331#issuecomment-3540413579
More information about the hotspot-compiler-dev
mailing list