RFR: 8371581: C2: PhaseCCP should reach fixpoint by revisiting deeply-Value-d nodes
Quan Anh Mai
qamai at openjdk.org
Thu Nov 13 11:33:25 UTC 2025
On Thu, 13 Nov 2025 10:49:14 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:
> I started this as investigation into one rare/intermittent CTW failure that I get with [JDK-8360557](https://bugs.openjdk.org/browse/JDK-8360557). The bug seems to reproduce on a very specific JAR with a very specific random seed, so no easy regression test.
>
> At this point I believe we found that PhaseCCP does not reach the fix point for a peculiar reason: `LoadN` that looks deeply into the graph is not revisited and thus misses the chance to update its type. There is an exception for loads in `verify_Value_for`, but it seems to only apply to constants, and does not apply to `LoadN` in question. Revisiting `LoadN` shows that updating the types downstream performs type widenings (= current types are too narrow), which AFAICS says that this unsound analysis can lead to miscompilation. See more debugging breadcrumbs in the bug.
>
> It looks like we can reach the fixpoint by recording the nodes we need to revisit and doing another CCP round. This also makes CCP verification stricter: we effectively move 2 exceptional cases recorded in `verify_Value_for` into the analysis itself.
>
> Testing shows there are no ill effects on correctness doing this. But I would appreciate someone more savvy in this code to sanity check all of this.
>
> Additional testing:
> - [x] Linux x86_64 server fastdebug, CTW reproducer no longer fails
> - [x] Linux x86_64 server fastdebug, `all` tests pass
> - [x] Linux x86_64 server fastdebug, Maven Central CTW passes (!)
LGTM. One minor concern is that for nodes in `worklist_revisit`, if the type changes, then we will perform `n->Value(this)` twice before updating the type table. Do you think it is preferable to duplicate this snippet instead:
const Type* new_type = n->Value(this);
if (new_type != type(n)) {
DEBUG_ONLY(verify_type(n, new_type, type(n));)
dump_type_and_node(n, new_type);
set_type(n, new_type);
push_child_nodes_to_worklist(worklist, n);
}
if (KillPathsReachableByDeadTypeNode && n->is_Type() && new_type == Type::TOP) {
// Keep track of Type nodes to kill CFG paths that use Type
// nodes that become dead.
_maybe_top_type_nodes.push(n);
}
-------------
Marked as reviewed by qamai (Committer).
PR Review: https://git.openjdk.org/jdk/pull/28288#pullrequestreview-3459340457
More information about the hotspot-compiler-dev
mailing list