RFR: 8338100: C2: assert(!n_loop->is_member(get_loop(lca))) failed: control must not be back in the loop
Tobias Hartmann
thartmann at openjdk.org
Tue Sep 3 10:04:22 UTC 2024
On Fri, 30 Aug 2024 15:58:30 GMT, Roland Westrelin <roland at openjdk.org> wrote:
> 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.
Thanks for the detailed summary. The fix looks reasonable to me.
src/hotspot/share/opto/loopnode.cpp line 4591:
> 4589: // Verify that the has_loops() flag set at parse time is consistent with the just built loop tree. When the back edge
> 4590: // is an exception edge, parsing doesn't set has_loops().
> 4591: assert(_ltree_root->_child == nullptr || C->has_loops() || C->has_exception_backedge(), "parsing found no loops but there are some");
`PhaseIdealLoop::only_has_infinite_loops` is dead now and should be removed.
src/hotspot/share/opto/loopnode.hpp line 1081:
> 1079: // Place 'n' in some loop nest, where 'n' is a CFG node
> 1080: void build_loop_tree();
> 1081: int build_loop_tree_impl(Node *n, int pre_order);
Suggestion:
int build_loop_tree_impl(Node* n, int pre_order);
-------------
Marked as reviewed by thartmann (Reviewer).
PR Review: https://git.openjdk.org/jdk/pull/20797#pullrequestreview-2276967473
PR Review Comment: https://git.openjdk.org/jdk/pull/20797#discussion_r1741779954
PR Review Comment: https://git.openjdk.org/jdk/pull/20797#discussion_r1741782737
More information about the hotspot-compiler-dev
mailing list