RFR: 8371716: C2 compilation fails with "Missed optimization opportunity in PhaseIterGVN"

Marc Chevalier mchevalier at openjdk.org
Fri Nov 14 20:06:19 UTC 2025


On Fri, 14 Nov 2025 19:56:14 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 and see if something change".
> 
> To me, the surprising fact was that the intersection
> 
> java/lang/Object *...

For the reproducer, now test.

-------------

PR Comment: https://git.openjdk.org/jdk/pull/28331#issuecomment-3534353796


More information about the hotspot-compiler-dev mailing list