RFR: 8371716: C2: Phi node fails Value()'s verification when speculative types clash [v2]
Marc Chevalier
mchevalier at openjdk.org
Wed Nov 19 11:26:03 UTC 2025
On Wed, 19 Nov 2025 08:55:07 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=TestSpeculativeTypes$C2:NotNull:exact * (inline_depth=3))
>> in(2): null
>>
>> We compute the join (HS' meet):
>> https://github.com/openjdk/jdk/blob/09b25cd0a24a4eaddce49917d958adc667ab5465/src/hotspot/share/opto/cfgnode.cpp#L1299-L1306
>>
>> t=java/lang/Object * (speculative=compiler/igvn/ClashingSpeculativeTypePhiNode$C2:exact *)
>>
>> But the current `_type` (of the `PhiNode` as a `TypeNode`) is
>>
>> _type=java/lang/Object * (speculative=compiler/igvn/ClashingSpeculativeTypePhiNode$C1:exact *)
>>
>> We filter `t` by `_type`
>> https://github.com/openjdk/jdk/blob/09b25cd0a24a4eaddce49917d958adc667ab5465/src/hotspot/share/opto/cfgnode.cpp#L1321
>> 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/jdk/blob/09b25cd0a24a4eaddce49917d958adc667ab5465/src/hotspot/share/opto/phaseX.cpp#L2150-L2164
>> and
>> https://github.com/openjdk/jdk/blob/09b25cd0a24a4eaddce49917d958adc667ab5465/src/hotspot/share/opto/node.cpp#L1117-L1123
>>
>>
>> ### 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/igvn/ClashingSpeculativeTypePhiNode$C2: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 and see if something change".
>>
>> To me, the surprising fact was that the intersection
>>
>> java/lang/Object * (speculative=compiler/igvn/ClashingSpeculativeTypePhiNode$C2:exact *)
>> /\
>> _type=java/lang/Objec...
>
> Marc Chevalier has updated the pull request incrementally with one additional commit since the last revision:
>
> Fix bug number
I think reading the code and the comments to understand the situation might not be as good as reading the description of this PR. I regret I gave a reproducer and proposed a solution.
Given the very obvious lack of consensus on the Valhalla PR, it is clear that this issue might evolve radically and that the proposed solution may not be the final one. Therefore, I will not do any cleanup before agreeing on the way to go, as it might very well be erased and it would be a very poor use of everybody's time.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/28331#issuecomment-3552162304
More information about the hotspot-compiler-dev
mailing list