forked from OSchip/llvm-project
Revert "Revert r275883 and r275891. They seem to cause PR28608."
This reverts commit r276064, and thus reapplies r275891 and r275883 with a fix for PR28608. llvm-svn: 276077
This commit is contained in:
parent
73118fd10e
commit
6bc56d552a
|
@ -64,6 +64,7 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
|
||||||
DominatorTree &DT, LoopInfo &LI) {
|
DominatorTree &DT, LoopInfo &LI) {
|
||||||
SmallVector<Use *, 16> UsesToRewrite;
|
SmallVector<Use *, 16> UsesToRewrite;
|
||||||
SmallVector<BasicBlock *, 8> ExitBlocks;
|
SmallVector<BasicBlock *, 8> ExitBlocks;
|
||||||
|
SmallSetVector<PHINode *, 16> PHIsToRemove;
|
||||||
PredIteratorCache PredCache;
|
PredIteratorCache PredCache;
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
|
@ -115,7 +116,8 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
|
||||||
SmallVector<PHINode *, 16> AddedPHIs;
|
SmallVector<PHINode *, 16> AddedPHIs;
|
||||||
SmallVector<PHINode *, 8> PostProcessPHIs;
|
SmallVector<PHINode *, 8> PostProcessPHIs;
|
||||||
|
|
||||||
SSAUpdater SSAUpdate;
|
SmallVector<PHINode *, 4> InsertedPHIs;
|
||||||
|
SSAUpdater SSAUpdate(&InsertedPHIs);
|
||||||
SSAUpdate.Initialize(I->getType(), I->getName());
|
SSAUpdate.Initialize(I->getType(), I->getName());
|
||||||
|
|
||||||
// Insert the LCSSA phi's into all of the exit blocks dominated by the
|
// Insert the LCSSA phi's into all of the exit blocks dominated by the
|
||||||
|
@ -184,6 +186,14 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
|
||||||
|
|
||||||
// Otherwise, do full PHI insertion.
|
// Otherwise, do full PHI insertion.
|
||||||
SSAUpdate.RewriteUse(*UseToRewrite);
|
SSAUpdate.RewriteUse(*UseToRewrite);
|
||||||
|
|
||||||
|
// SSAUpdater might have inserted phi-nodes inside other loops. We'll need
|
||||||
|
// to post-process them to keep LCSSA form.
|
||||||
|
for (PHINode *InsertedPN : InsertedPHIs) {
|
||||||
|
if (auto *OtherLoop = LI.getLoopFor(InsertedPN->getParent()))
|
||||||
|
if (!L->contains(OtherLoop))
|
||||||
|
PostProcessPHIs.push_back(InsertedPN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Post process PHI instructions that were inserted into another disjoint
|
// Post process PHI instructions that were inserted into another disjoint
|
||||||
|
@ -196,13 +206,19 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
|
||||||
Worklist.push_back(PostProcessPN);
|
Worklist.push_back(PostProcessPN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove PHI nodes that did not have any uses rewritten.
|
// Keep track of PHI nodes that we want to remove because they did not have
|
||||||
|
// any uses rewritten.
|
||||||
for (PHINode *PN : AddedPHIs)
|
for (PHINode *PN : AddedPHIs)
|
||||||
if (PN->use_empty())
|
if (PN->use_empty())
|
||||||
PN->eraseFromParent();
|
PHIsToRemove.insert(PN);
|
||||||
|
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
|
// Remove PHI nodes that did not have any uses rewritten.
|
||||||
|
for (PHINode *PN : PHIsToRemove) {
|
||||||
|
assert (PN->use_empty() && "Trying to remove a phi with uses.");
|
||||||
|
PN->eraseFromParent();
|
||||||
|
}
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,8 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
|
||||||
else
|
else
|
||||||
NewOuter->addChildLoop(L->removeChildLoop(SubLoops.begin() + I));
|
NewOuter->addChildLoop(L->removeChildLoop(SubLoops.begin() + I));
|
||||||
|
|
||||||
|
SmallVector<BasicBlock *, 8> OuterLoopBlocks;
|
||||||
|
OuterLoopBlocks.push_back(NewBB);
|
||||||
// Now that we know which blocks are in L and which need to be moved to
|
// Now that we know which blocks are in L and which need to be moved to
|
||||||
// OuterLoop, move any blocks that need it.
|
// OuterLoop, move any blocks that need it.
|
||||||
for (unsigned i = 0; i != L->getBlocks().size(); ++i) {
|
for (unsigned i = 0; i != L->getBlocks().size(); ++i) {
|
||||||
|
@ -334,12 +336,53 @@ static Loop *separateNestedLoop(Loop *L, BasicBlock *Preheader,
|
||||||
if (!BlocksInL.count(BB)) {
|
if (!BlocksInL.count(BB)) {
|
||||||
// Move this block to the parent, updating the exit blocks sets
|
// Move this block to the parent, updating the exit blocks sets
|
||||||
L->removeBlockFromLoop(BB);
|
L->removeBlockFromLoop(BB);
|
||||||
if ((*LI)[BB] == L)
|
if ((*LI)[BB] == L) {
|
||||||
LI->changeLoopFor(BB, NewOuter);
|
LI->changeLoopFor(BB, NewOuter);
|
||||||
|
OuterLoopBlocks.push_back(BB);
|
||||||
|
}
|
||||||
--i;
|
--i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split edges to exit blocks from the inner loop, if they emerged in the
|
||||||
|
// process of separating the outer one.
|
||||||
|
SmallVector<BasicBlock *, 8> ExitBlocks;
|
||||||
|
L->getExitBlocks(ExitBlocks);
|
||||||
|
SmallSetVector<BasicBlock *, 8> ExitBlockSet(ExitBlocks.begin(),
|
||||||
|
ExitBlocks.end());
|
||||||
|
for (BasicBlock *ExitBlock : ExitBlockSet) {
|
||||||
|
if (any_of(predecessors(ExitBlock),
|
||||||
|
[L](BasicBlock *BB) { return !L->contains(BB); })) {
|
||||||
|
rewriteLoopExitBlock(L, ExitBlock, DT, LI, PreserveLCSSA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PreserveLCSSA) {
|
||||||
|
// Fix LCSSA form for L. Some values, which previously were only used inside
|
||||||
|
// L, can now be used in NewOuter loop. We need to insert phi-nodes for them
|
||||||
|
// in corresponding exit blocks.
|
||||||
|
|
||||||
|
// Go through all instructions in OuterLoopBlocks and check if they are
|
||||||
|
// using operands from the inner loop. In this case we'll need to fix LCSSA
|
||||||
|
// for these instructions.
|
||||||
|
SmallSetVector<Instruction *, 8> WorklistSet;
|
||||||
|
for (BasicBlock *OuterBB: OuterLoopBlocks) {
|
||||||
|
for (Instruction &I : *OuterBB) {
|
||||||
|
for (Value *Op : I.operands()) {
|
||||||
|
Instruction *OpI = dyn_cast<Instruction>(Op);
|
||||||
|
if (!OpI || !L->contains(OpI))
|
||||||
|
continue;
|
||||||
|
WorklistSet.insert(OpI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SmallVector<Instruction *, 8> Worklist(WorklistSet.begin(),
|
||||||
|
WorklistSet.end());
|
||||||
|
formLCSSAForInstructions(Worklist, *DT, *LI);
|
||||||
|
assert(NewOuter->isRecursivelyLCSSAForm(*DT) &&
|
||||||
|
"LCSSA is broken after separating nested loops!");
|
||||||
|
}
|
||||||
|
|
||||||
return NewOuter;
|
return NewOuter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,17 +584,12 @@ ReprocessLoop:
|
||||||
SmallSetVector<BasicBlock *, 8> ExitBlockSet(ExitBlocks.begin(),
|
SmallSetVector<BasicBlock *, 8> ExitBlockSet(ExitBlocks.begin(),
|
||||||
ExitBlocks.end());
|
ExitBlocks.end());
|
||||||
for (BasicBlock *ExitBlock : ExitBlockSet) {
|
for (BasicBlock *ExitBlock : ExitBlockSet) {
|
||||||
for (pred_iterator PI = pred_begin(ExitBlock), PE = pred_end(ExitBlock);
|
if (any_of(predecessors(ExitBlock),
|
||||||
PI != PE; ++PI)
|
[L](BasicBlock *BB) { return !L->contains(BB); })) {
|
||||||
// Must be exactly this loop: no subloops, parent loops, or non-loop preds
|
rewriteLoopExitBlock(L, ExitBlock, DT, LI, PreserveLCSSA);
|
||||||
// allowed.
|
++NumInserted;
|
||||||
if (!L->contains(*PI)) {
|
Changed = true;
|
||||||
if (rewriteLoopExitBlock(L, ExitBlock, DT, LI, PreserveLCSSA)) {
|
}
|
||||||
++NumInserted;
|
|
||||||
Changed = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the header has more than two predecessors at this point (from the
|
// If the header has more than two predecessors at this point (from the
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
; RUN: opt < %s -lcssa -S -o - | FileCheck %s
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
; PR28424
|
||||||
|
; Here LCSSA adds phi-nodes for %x into the loop exits. Then, SSAUpdater needs
|
||||||
|
; to insert phi-nodes to merge these values. That creates a new def, which in
|
||||||
|
; its turn needs another LCCSA phi-node, and this test ensures that we insert
|
||||||
|
; it.
|
||||||
|
|
||||||
|
; CHECK-LABEL: @foo1
|
||||||
|
define internal i32 @foo1() {
|
||||||
|
entry:
|
||||||
|
br label %header
|
||||||
|
|
||||||
|
header:
|
||||||
|
%x = add i32 0, 1
|
||||||
|
br i1 undef, label %if, label %loopexit1
|
||||||
|
|
||||||
|
if:
|
||||||
|
br i1 undef, label %latch, label %loopexit2
|
||||||
|
|
||||||
|
latch:
|
||||||
|
br i1 undef, label %header, label %loopexit3
|
||||||
|
|
||||||
|
; CHECK: loopexit1:
|
||||||
|
; CHECK: %x.lcssa = phi i32 [ %x, %header ]
|
||||||
|
loopexit1:
|
||||||
|
br label %loop_with_insert_point
|
||||||
|
|
||||||
|
; CHECK: loopexit2:
|
||||||
|
; CHECK: %x.lcssa1 = phi i32 [ %x, %if ]
|
||||||
|
loopexit2:
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
; CHECK: loopexit3:
|
||||||
|
; CHECK: %x.lcssa2 = phi i32 [ %x, %latch ]
|
||||||
|
loopexit3:
|
||||||
|
br label %loop_with_insert_point
|
||||||
|
|
||||||
|
; CHECK: loop_with_insert_point:
|
||||||
|
; CHECK: %x4 = phi i32 [ %x4, %loop_with_insert_point ], [ %x.lcssa2, %loopexit3 ], [ %x.lcssa, %loopexit1 ]
|
||||||
|
loop_with_insert_point:
|
||||||
|
br i1 undef, label %loop_with_insert_point, label %bb
|
||||||
|
|
||||||
|
; CHECK: bb:
|
||||||
|
; CHECK: %x4.lcssa = phi i32 [ %x4, %loop_with_insert_point ]
|
||||||
|
bb:
|
||||||
|
br label %exit
|
||||||
|
|
||||||
|
; CHECK: exit:
|
||||||
|
; CHECK: %x3 = phi i32 [ %x4.lcssa, %bb ], [ %x.lcssa1, %loopexit2 ]
|
||||||
|
exit:
|
||||||
|
ret i32 %x
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @foo2
|
||||||
|
define internal i32 @foo2() {
|
||||||
|
entry:
|
||||||
|
br label %header
|
||||||
|
|
||||||
|
header:
|
||||||
|
%x = add i32 0, 1
|
||||||
|
br i1 undef, label %latch, label %loopexit1
|
||||||
|
|
||||||
|
latch:
|
||||||
|
br i1 undef, label %header, label %loopexit2
|
||||||
|
|
||||||
|
; CHECK: loopexit1:
|
||||||
|
; CHECK: %x.lcssa = phi i32 [ %x, %header ]
|
||||||
|
loopexit1:
|
||||||
|
br label %loop_with_insert_point
|
||||||
|
|
||||||
|
; CHECK: loopexit2:
|
||||||
|
; CHECK: %x.lcssa1 = phi i32 [ %x, %latch ]
|
||||||
|
loopexit2:
|
||||||
|
br label %loop_with_insert_point
|
||||||
|
|
||||||
|
; CHECK: loop_with_insert_point:
|
||||||
|
; CHECK: %x2 = phi i32 [ %x2, %loop_with_insert_point ], [ %x.lcssa1, %loopexit2 ], [ %x.lcssa, %loopexit1 ]
|
||||||
|
loop_with_insert_point:
|
||||||
|
br i1 undef, label %loop_with_insert_point, label %exit
|
||||||
|
|
||||||
|
; CHECK: exit:
|
||||||
|
; CHECK: %x2.lcssa = phi i32 [ %x2, %loop_with_insert_point ]
|
||||||
|
exit:
|
||||||
|
ret i32 %x
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
; RUN: opt < %s -lcssa -disable-output
|
||||||
|
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
; PR28608
|
||||||
|
; Check that we don't crash on this test.
|
||||||
|
|
||||||
|
define void @foo() {
|
||||||
|
entry:
|
||||||
|
br label %bb1
|
||||||
|
|
||||||
|
bb1:
|
||||||
|
br label %bb2
|
||||||
|
|
||||||
|
bb2:
|
||||||
|
%x = phi i32 [ undef, %bb5 ], [ undef, %bb1 ]
|
||||||
|
br i1 undef, label %bb3, label %bb6
|
||||||
|
|
||||||
|
bb3:
|
||||||
|
br i1 undef, label %bb5, label %bb4
|
||||||
|
|
||||||
|
bb4:
|
||||||
|
br label %bb6
|
||||||
|
|
||||||
|
bb5:
|
||||||
|
br label %bb2
|
||||||
|
|
||||||
|
bb6:
|
||||||
|
br label %bb1
|
||||||
|
|
||||||
|
exit:
|
||||||
|
%y = add i32 0, %x
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
; RUN: opt < %s -lcssa -loop-unroll -S | FileCheck %s
|
||||||
|
target triple = "x86_64-unknown-linux-gnu"
|
||||||
|
|
||||||
|
; PR28272
|
||||||
|
; When LoopSimplify separates nested loops, it might break LCSSA form: values
|
||||||
|
; from the original loop might be used in the outer loop. This test invokes
|
||||||
|
; loop-unroll, which calls loop-simplify before itself. If LCSSA is broken
|
||||||
|
; after loop-simplify, we crash on assertion.
|
||||||
|
|
||||||
|
; CHECK-LABEL: @foo
|
||||||
|
define void @foo() {
|
||||||
|
entry:
|
||||||
|
br label %header
|
||||||
|
|
||||||
|
header:
|
||||||
|
br label %loop1
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
br i1 true, label %loop1, label %bb43
|
||||||
|
|
||||||
|
bb43:
|
||||||
|
%a = phi i32 [ undef, %loop1 ], [ 0, %bb45 ], [ %a, %bb54 ]
|
||||||
|
%b = phi i32 [ 0, %loop1 ], [ 1, %bb54 ], [ %c, %bb45 ]
|
||||||
|
br i1 true, label %bb114, label %header
|
||||||
|
|
||||||
|
bb114:
|
||||||
|
%c = add i32 0, 1
|
||||||
|
%d = add i32 0, 1
|
||||||
|
br i1 true, label %bb45, label %bb54
|
||||||
|
|
||||||
|
bb45:
|
||||||
|
%x = add i32 %d, 0
|
||||||
|
br label %bb43
|
||||||
|
|
||||||
|
bb54:
|
||||||
|
br label %bb43
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK-LABEL: @foo2
|
||||||
|
define void @foo2() {
|
||||||
|
entry:
|
||||||
|
br label %outer
|
||||||
|
|
||||||
|
outer.loopexit:
|
||||||
|
br label %outer
|
||||||
|
|
||||||
|
outer:
|
||||||
|
br label %loop1
|
||||||
|
|
||||||
|
loop1:
|
||||||
|
br i1 true, label %loop1, label %loop2.preheader
|
||||||
|
|
||||||
|
loop2.preheader:
|
||||||
|
%a.ph = phi i32 [ undef, %loop1 ]
|
||||||
|
%b.ph = phi i32 [ 0, %loop1 ]
|
||||||
|
br label %loop2
|
||||||
|
|
||||||
|
loop2:
|
||||||
|
%a = phi i32 [ 0, %loop2.if.true ], [ %a, %loop2.if.false ], [ %a.ph, %loop2.preheader ], [0, %bb]
|
||||||
|
%b = phi i32 [ 1, %loop2.if.false ], [ %c, %loop2.if.true ], [ %b.ph, %loop2.preheader ], [%c, %bb]
|
||||||
|
br i1 true, label %loop2.if, label %outer.loopexit
|
||||||
|
|
||||||
|
loop2.if:
|
||||||
|
%c = add i32 0, 1
|
||||||
|
switch i32 undef, label %loop2.if.false [i32 0, label %loop2.if.true
|
||||||
|
i32 1, label %bb]
|
||||||
|
|
||||||
|
loop2.if.true:
|
||||||
|
br i1 undef, label %loop2, label %bb
|
||||||
|
|
||||||
|
loop2.if.false:
|
||||||
|
br label %loop2
|
||||||
|
|
||||||
|
bb:
|
||||||
|
br label %loop2
|
||||||
|
}
|
Loading…
Reference in New Issue