RFR: 8338100: C2: assert(!n_loop->is_member(get_loop(lca))) failed: control must not be back in the loop
Roland Westrelin
roland at openjdk.org
Fri Aug 30 16:05:10 UTC 2024
The crash occurs because a `Store` is sunk out of a loop that's an
inner loop of an infinite loop. The infinite loop was just found to be
infinite in the current round of loop opts. When that happens the
infinite loop is not properly attached to the rest of the loop tree. As
a consequence, the `IdealLoopTree` instance for the infinite loop and
its children are only partially initialized (`_nest` is not set) and
the structure is an inconsistent state.
When the `Store` is sunk it's reported as belonging to a loop but the
`IdealLoopTree` for that loop is only half populated. As a consequence
a call to `is_dominator` for that loop hits an inconsistency, returns
an incorrect result and the assert fires.
A possible fix would be a point fix that skips that optimization for a
loop that's part of an infinite loop nest. But given basic methods of
loop opts can't be trusted to work in the infinite loop nest, I
suppose similar issues can surface elsewhere.
It's not the first time, we have issues with an infinite loop that's
not properly attached to the loop tree the first time it is
encountered (a NeverBranch is then added and on the next loop passes,
the infinite loop is properly attached to the loop tree). For instance
on a loop opts round, C2 can see that it has no loops and on the next
that it has some.
I propose fixing this by properly attaching the infinite loop to the
loop tree when it's first discovered. A comment in the code seems to
hint that it requires going over the graph again after the
`NeverBranch` is added but I don't think that's case.
I changed the assert in `loopnode.cpp` because it was there to work
around the inconsistency I mentioned above (no loop in a round, some
loops on the next one).
The change in `parse1.cpp` fixes an issue I ran into when testing the
fix. The existing logic doesn't properly detect an exception backedge.
I added the test case from 8336478 to this. The problem there is that
an infinite loop contains a long counted loop. The long counted loop
is transformed into a loop nest which is a 2 step process that
requires 2 rounds of loop opts. But c2 finds an infinite loop in the
middle of the process which causes it to see no more loops and to not
attempt another round of loop opts. The assert fires because it finds
a long counted loop nest that's half transformed. The change I propose
here fixes this too. If we go with this fix, I'll close 8336478 as
duplicate of this one.
-------------
Commit messages:
- comment
- test fix
- remove verification code
- test & fix
Changes: https://git.openjdk.org/jdk/pull/20797/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=20797&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8338100
Stats: 287 lines in 7 files changed: 257 ins; 11 del; 19 mod
Patch: https://git.openjdk.org/jdk/pull/20797.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/20797/head:pull/20797
PR: https://git.openjdk.org/jdk/pull/20797
More information about the hotspot-compiler-dev
mailing list