The algorithm in allLoopPathsLeadToBlock() does not handle the case where the loop latch is part of the predecessor set correctly: In this case, we may take the backedge and not execute other latch successors. This can happen if the latch is part of an inner cycle.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
I need to think more about this particular one, but my general preference would be "do nothing if there is an irreducible loop". Is it an option here?
I've given this some more thought, and the irreducible control flow is ultimately not relevant: We only need the latch to be part of an inner cycle. The LICM issue does not reproduce with an inner natural cycle (because we don't hoist instructions from inner loops), but we can see this when testing MustExecute directly.
To provide some more context here: What the algorithm essentially does is collect all the predecessors in the loop, and then check that this is a closed set, in the sense that all control flow either stays in the set or goes to the target block. If no loops are involved, then this ensures control flow will eventually hit the target block.
Once loops are involved, we can run into two complications:
- The issue fixed here: If we have a loop latch in the set, then control flow can escape the set by going to the next loop iteration. However, this "next iteration" distinction gets lost in the current representation, and it looks as if we were staying in the set. This is why the separate check is necessary.
- Separate issue not addressed by this patch: Control flow might infinitely loop around an inner cycle and thus never reach the target block. Haven't tried to reproduce this, but I suspect that this may not be handled correctly (for non-mustprogress semantics).
llvm/lib/Analysis/MustExecute.cpp | ||
---|---|---|
204 | Should this say latch blocks? Also, predecessors(CurLoop->getHeader() will include non-latch blocks (i.e. predecessors not in the loop). I suppose it doesn't matter in practice as Predecessors only contains loop blocks but it might be possible to include this in the comment somehow? |
Should this say latch blocks?
Also, predecessors(CurLoop->getHeader() will include non-latch blocks (i.e. predecessors not in the loop). I suppose it doesn't matter in practice as Predecessors only contains loop blocks but it might be possible to include this in the comment somehow?