Integrated: 8287217: C2: PhaseCCP: remove not visited nodes, prevent type inconsistency
Emanuel Peter
epeter at openjdk.org
Wed Sep 21 07:25:49 UTC 2022
On Tue, 13 Sep 2022 14:33:14 GMT, Emanuel Peter <epeter at openjdk.org> wrote:
> **Context:**
> [JDK-8265973](https://bugs.openjdk.org/browse/JDK-8265973) Fix in Valhalla repository (Tobias @TobiHartmann ).
> [JDK-8290711](https://bugs.openjdk.org/browse/JDK-8290711) Fix in mainline (Roland @rwestrel ).
> Tobias' fix is a superset of Rolands. Unfortunately, Tobias gave up his fix once Rolands came up, because they did not have tests that required the superset fix.
>
> We now have such a test, where Rolands fix is not sufficient. But Tobias' fix is the solution. So I ported Tobias' fix to mainline.
>
> **Analysis:**
> In this bug, we have two `LoadB` nodes re-pushing themselves to the `igvn.worklist`, without end. This leads to an assert after too many iterations.
>
> `PhaseCCP::analyze` is looking at a post-loop. The loop has a memory access, so there is a `null_check`. The data-part of the loop is connected down to Root via this `null_check`
> (`Phi-> CmpP -> Bool -> If -> IfFalse -> Region -> CallStaticJava uncommon_trap -> ... -> Root`).
> During `CCP::analyze`, we discover that the memory address is NonNull. So we update the `phase->type(n)` for many of the data-nodes of the loop.
>
> During `PhaseCCP::do_transform`, we now traverse recursively up from the root, visiting all reachable nodes.
> When we visit a node, we store the cached `phase->type(n)` into the node, making the node's type consistent.
> We traverse up through the `null_check`, through the `uncommon_trap`, and the `If`, to the `Bool` node.
> `BoolNode::Value` realizes that we can never have Null, and is subsumed by constant `#int:1` (true).
> This means that the data-part of the loop just lost its connection down to Root.
> The traversal now also does not reach further than the Bool node which was just subsumed, and hence does not reach the data-part of the loop.
> This means we have nodes with inconsistent type.
>
> Summary: CCP disconnects the last path down to root for a data-loop, because it realizes that a `null_check` will never trap. The disconnected state means the types of the data-loop may be left inconsistent.
>
> Right after PhaseCCP, we continue with IGVN.
> The `LoadB` from that data-part of the loop has `MemNode::Ideal_common` called, which defers its transformation until the type of the address is consistent. However, this is never made consistent, as it is already left inconsistent after PhaseCCP.
> https://github.com/openjdk/jdk/blob/aa7ccdf44549a52cce9e99f6569097d3343d9ee4/src/hotspot/share/opto/memnode.cpp#L351-L358
> Note that we only re-push if there is another node in the worklist - a node that hopefully has something to do with the address.
> But in our case it is just the two LoadB nodes, which were generated from the same `split_through_phi`.
>
> **Solution:**
> At the end of PhaseCCP, we remove all nodes that were not visited (and may have an inconsistent state). We can do this because we visited all nodes that are still relevant. Rolands fix already made sure that SafePointNodes are visited, such that infinite loops are covered as well.
>
> Regression test added.
> Test suite passed.
> Tests rerunning for review suggestion (commit 3)...
This pull request has now been integrated.
Changeset: 379f3094
Author: Emanuel Peter <epeter at openjdk.org>
URL: https://git.openjdk.org/jdk/commit/379f3094db0b8afe90ed6b7a341164222744085f
Stats: 102 lines in 5 files changed: 81 ins; 2 del; 19 mod
8287217: C2: PhaseCCP: remove not visited nodes, prevent type inconsistency
Reviewed-by: roland, chagedorn, thartmann
-------------
PR: https://git.openjdk.org/jdk/pull/10250
More information about the hotspot-compiler-dev
mailing list