mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
[LPM] Fix PR18643, another scary place where loop transforms failed to
preserve loop simplify of enclosing loops. The problem here starts with LoopRotation which ends up cloning code out of the latch into the new preheader it is buidling. This can create a new edge from the preheader into the exit block of the loop which breaks LoopSimplify form. The code tries to fix this by splitting the critical edge between the latch and the exit block to get a new exit block that only the latch dominates. This sadly isn't sufficient. The exit block may be an exit block for multiple nested loops. When we clone an edge from the latch of the inner loop to the new preheader being built in the outer loop, we create an exiting edge from the outer loop to this exit block. Despite breaking the LoopSimplify form for the inner loop, this is fine for the outer loop. However, when we split the edge from the inner loop to the exit block, we create a new block which is in neither the inner nor outer loop as the new exit block. This is a predecessor to the old exit block, and so the split itself takes the outer loop out of LoopSimplify form. We need to split every edge entering the exit block from inside a loop nested more deeply than the exit block in order to preserve all of the loop simplify constraints. Once we try to do that, a problem with splitting critical edges surfaces. Previously, we tried a very brute force to update LoopSimplify form by re-computing it for all exit blocks. We don't need to do this, and doing this much will sometimes but not always overlap with the LoopRotate bug fix. Instead, the code needs to specifically handle the cases which can start to violate LoopSimplify -- they aren't that common. We need to see if the destination of the split edge was a loop exit block in simplified form for the loop of the source of the edge. For this to be true, all the predecessors need to be in the exact same loop as the source of the edge being split. If the dest block was originally in this form, we have to split all of the deges back into this loop to recover it. The old mechanism of doing this was conservatively correct because at least *one* of the exiting blocks it rewrote was the DestBB and so the DestBB's predecessors were fixed. But this is a much more targeted way of doing it. Making it targeted is important, because ballooning the set of edges touched prevents LoopRotate from being able to split edges *it* needs to split to preserve loop simplify in a coherent way -- the critical edge splitting would sometimes find the other edges in need of splitting but not others. Many, *many* thanks for help from Nick reducing these test cases mightily. And helping lots with the analysis here as this one was quite tricky to track down. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@200393 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e89e312753
commit
a403ceb205
@ -463,9 +463,24 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
|
||||
NewPH->setName(NewHeader->getName() + ".lr.ph");
|
||||
|
||||
// Preserve canonical loop form, which means that 'Exit' should have only
|
||||
// one predecessor.
|
||||
BasicBlock *ExitSplit = SplitCriticalEdge(L->getLoopLatch(), Exit, this);
|
||||
// one predecessor. Note that Exit could be an exit block for multiple
|
||||
// nested loops, causing both of the edges to now be critical and need to
|
||||
// be split.
|
||||
SmallVector<BasicBlock *, 4> ExitPreds(pred_begin(Exit), pred_end(Exit));
|
||||
bool SplitLatchEdge = false;
|
||||
for (SmallVectorImpl<BasicBlock *>::iterator PI = ExitPreds.begin(),
|
||||
PE = ExitPreds.end();
|
||||
PI != PE; ++PI) {
|
||||
// We only need to split loop exit edges.
|
||||
Loop *PredLoop = LI->getLoopFor(*PI);
|
||||
if (!PredLoop || PredLoop->contains(Exit))
|
||||
continue;
|
||||
SplitLatchEdge |= L->getLoopLatch() == *PI;
|
||||
BasicBlock *ExitSplit = SplitCriticalEdge(*PI, Exit, this);
|
||||
ExitSplit->moveBefore(Exit);
|
||||
}
|
||||
assert(SplitLatchEdge &&
|
||||
"Despite splitting all preds, failed to split latch exit?");
|
||||
} else {
|
||||
// We can fold the conditional branch in the preheader, this makes things
|
||||
// simpler. The first step is to remove the extra edge to the Exit block.
|
||||
|
@ -299,9 +299,8 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
|
||||
P->addBasicBlockToLoop(NewBB, LI->getBase());
|
||||
}
|
||||
}
|
||||
// If TIBB is in a loop and DestBB is outside of that loop, split the
|
||||
// other exit blocks of the loop that also have predecessors outside
|
||||
// the loop, to maintain a LoopSimplify guarantee.
|
||||
// If TIBB is in a loop and DestBB is outside of that loop, we may need
|
||||
// to update LoopSimplify form and LCSSA form.
|
||||
if (!TIL->contains(DestBB) &&
|
||||
P->mustPreserveAnalysisID(LoopSimplifyID)) {
|
||||
assert(!TIL->contains(NewBB) &&
|
||||
@ -311,50 +310,35 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
|
||||
if (P->mustPreserveAnalysisID(LCSSAID))
|
||||
createPHIsForSplitLoopExit(TIBB, NewBB, DestBB);
|
||||
|
||||
// For each unique exit block...
|
||||
// FIXME: This code is functionally equivalent to the corresponding
|
||||
// loop in LoopSimplify.
|
||||
SmallVector<BasicBlock *, 4> ExitBlocks;
|
||||
TIL->getExitBlocks(ExitBlocks);
|
||||
for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) {
|
||||
// Collect all the preds that are inside the loop, and note
|
||||
// whether there are any preds outside the loop.
|
||||
SmallVector<BasicBlock *, 4> Preds;
|
||||
bool HasPredOutsideOfLoop = false;
|
||||
BasicBlock *Exit = ExitBlocks[i];
|
||||
for (pred_iterator I = pred_begin(Exit), E = pred_end(Exit);
|
||||
I != E; ++I) {
|
||||
// The only that we can break LoopSimplify form by splitting a critical
|
||||
// edge is if after the split there exists some edge from TIL to DestBB
|
||||
// *and* the only edge into DestBB from outside of TIL is that of
|
||||
// NewBB. If the first isn't true, then LoopSimplify still holds, NewBB
|
||||
// is the new exit block and it has no non-loop predecessors. If the
|
||||
// second isn't true, then DestBB was not in LoopSimplify form prior to
|
||||
// the split as it had a non-loop predecessor. In both of these cases,
|
||||
// the predecessor must be directly in TIL, not in a subloop, or again
|
||||
// LoopSimplify doesn't hold.
|
||||
SmallVector<BasicBlock *, 4> LoopPreds;
|
||||
for (pred_iterator I = pred_begin(DestBB), E = pred_end(DestBB); I != E;
|
||||
++I) {
|
||||
BasicBlock *P = *I;
|
||||
if (TIL->contains(P)) {
|
||||
if (isa<IndirectBrInst>(P->getTerminator())) {
|
||||
Preds.clear();
|
||||
if (P == NewBB)
|
||||
continue; // The new block is known.
|
||||
if (LI->getLoopFor(P) != TIL) {
|
||||
// No need to re-simplify, it wasn't to start with.
|
||||
LoopPreds.clear();
|
||||
break;
|
||||
}
|
||||
Preds.push_back(P);
|
||||
} else {
|
||||
HasPredOutsideOfLoop = true;
|
||||
LoopPreds.push_back(P);
|
||||
}
|
||||
}
|
||||
// If there are any preds not in the loop, we'll need to split
|
||||
// the edges. The Preds.empty() check is needed because a block
|
||||
// may appear multiple times in the list. We can't use
|
||||
// getUniqueExitBlocks above because that depends on LoopSimplify
|
||||
// form, which we're in the process of restoring!
|
||||
if (!Preds.empty() && HasPredOutsideOfLoop) {
|
||||
if (!Exit->isLandingPad()) {
|
||||
if (!LoopPreds.empty()) {
|
||||
assert(!DestBB->isLandingPad() &&
|
||||
"We don't split edges to landing pads!");
|
||||
BasicBlock *NewExitBB =
|
||||
SplitBlockPredecessors(Exit, Preds, "split", P);
|
||||
SplitBlockPredecessors(DestBB, LoopPreds, "split", P);
|
||||
if (P->mustPreserveAnalysisID(LCSSAID))
|
||||
createPHIsForSplitLoopExit(Preds, NewExitBB, Exit);
|
||||
} else if (SplitLandingPads) {
|
||||
SmallVector<BasicBlock*, 8> NewBBs;
|
||||
SplitLandingPadPredecessors(Exit, Preds,
|
||||
".split1", ".split2",
|
||||
P, NewBBs);
|
||||
if (P->mustPreserveAnalysisID(LCSSAID))
|
||||
createPHIsForSplitLoopExit(Preds, NewBBs[0], Exit);
|
||||
}
|
||||
}
|
||||
createPHIsForSplitLoopExit(LoopPreds, NewExitBB, DestBB);
|
||||
}
|
||||
}
|
||||
// LCSSA form was updated above for the case where LoopSimplify is
|
||||
|
@ -46,7 +46,11 @@ define void @FindFreeHorzSeg(i64 %startCol, i64 %row, i64* %rowStart) {
|
||||
; CHECK-LABEL: define void @FindFreeHorzSeg(
|
||||
; CHECK: %dec = add
|
||||
; CHECK-NEXT: tail call void @llvm.dbg.value
|
||||
; CHECK-NEXT: br i1 %tobool, label %for.cond, label %for.end
|
||||
; CHECK-NEXT: br i1 %tobool, label %for.cond, label %[[LOOP_EXIT:[^,]*]]
|
||||
; CHECK: [[LOOP_EXIT]]:
|
||||
; CHECK-NEXT: phi i64 [ %{{[^,]*}}, %{{[^,]*}} ]
|
||||
; CHECK-NEXT: br label %for.end
|
||||
|
||||
|
||||
entry:
|
||||
br label %for.cond
|
||||
|
65
test/Transforms/LoopRotate/preserve-loop-simplify.ll
Normal file
65
test/Transforms/LoopRotate/preserve-loop-simplify.ll
Normal file
@ -0,0 +1,65 @@
|
||||
; RUN: opt -S -loop-rotate < %s -verify-loop-info | FileCheck %s
|
||||
;
|
||||
; Verify that LoopRotate preserves LoopSimplify form even in very peculiar loop
|
||||
; structures. We manually validate the CFG with FileCheck because currently we
|
||||
; can't cause a failure when LoopSimplify fails to be preserved.
|
||||
|
||||
define void @PR18643() {
|
||||
; CHECK-LABEL: @PR18643(
|
||||
entry:
|
||||
br label %outer.header
|
||||
; CHECK: br label %outer.header
|
||||
|
||||
outer.header:
|
||||
; CHECK: outer.header:
|
||||
br i1 undef, label %inner.header, label %outer.body
|
||||
; CHECK-NEXT: br i1 {{[^,]*}}, label %[[INNER_PREROTATE_PREHEADER:[^,]*]], label %outer.body
|
||||
|
||||
; CHECK: [[INNER_PREROTATE_PREHEADER]]:
|
||||
; CHECK-NEXT: br i1 {{[^,]*}}, label %[[INNER_PREROTATE_PREHEADER_SPLIT_RETURN:[^,]*]], label %[[INNER_ROTATED_PREHEADER:[^,]*]]
|
||||
|
||||
; CHECK: [[INNER_ROTATED_PREHEADER]]:
|
||||
; CHECK-NEXT: br label %inner.body
|
||||
|
||||
inner.header:
|
||||
; Now the latch!
|
||||
; CHECK: inner.header:
|
||||
br i1 undef, label %return, label %inner.body
|
||||
; CHECK-NEXT: br i1 {{[^,]*}}, label %[[INNER_SPLIT_RETURN:[^,]*]], label %inner.body
|
||||
|
||||
inner.body:
|
||||
; Now the header!
|
||||
; CHECK: inner.body:
|
||||
br i1 undef, label %outer.latch, label %inner.latch
|
||||
; CHECK-NEXT: br i1 {{[^,]*}}, label %[[INNER_SPLIT_OUTER_LATCH:[^,]*]], label %inner.header
|
||||
|
||||
inner.latch:
|
||||
; Dead!
|
||||
br label %inner.header
|
||||
|
||||
outer.body:
|
||||
; CHECK: outer.body:
|
||||
br label %outer.latch
|
||||
; CHECK-NEXT: br label %outer.latch
|
||||
|
||||
; L2 -> L1 exit edge needs a simplified exit block.
|
||||
; CHECK: [[INNER_SPLIT_OUTER_LATCH]]:
|
||||
; CHECK-NEXT: br label %outer.latch
|
||||
|
||||
outer.latch:
|
||||
; CHECK: outer.latch:
|
||||
br label %outer.header
|
||||
; CHECK-NEXT: br label %outer.header
|
||||
|
||||
; L1 -> L0 exit edge need sa simplified exit block.
|
||||
; CHECK: [[INNER_PREROTATE_PREHEADER_SPLIT_RETURN]]:
|
||||
; CHECK-NEXT: br label %return
|
||||
|
||||
; L2 -> L0 exit edge needs a simplified exit block.
|
||||
; CHECK: [[INNER_SPLIT_RETURN]]:
|
||||
; CHECK-NEXT: br label %return
|
||||
|
||||
return:
|
||||
; CHECK: return:
|
||||
unreachable
|
||||
}
|
Loading…
Reference in New Issue
Block a user