[LoopDeletion] Clear SCEV loop dispositions

`Loop::makeLoopInvariant` can hoist instructions out of loops, so loop
dispositions for the loop it operated on may need to be cleared.  We can
be smarter here (especially around how `forgetLoopDispositions` is
implemented), but let's be correct first.

Fixes PR27570.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268406 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjoy Das 2016-05-03 17:50:02 +00:00
parent b78000e38b
commit 045a03d9a7
2 changed files with 83 additions and 11 deletions

View File

@ -44,10 +44,10 @@ namespace {
}
private:
bool isLoopDead(Loop *L, SmallVectorImpl<BasicBlock *> &exitingBlocks,
SmallVectorImpl<BasicBlock *> &exitBlocks,
bool &Changed, BasicBlock *Preheader);
bool isLoopDead(Loop *L, ScalarEvolution &SE,
SmallVectorImpl<BasicBlock *> &exitingBlocks,
SmallVectorImpl<BasicBlock *> &exitBlocks, bool &Changed,
BasicBlock *Preheader);
};
}
@ -65,7 +65,7 @@ Pass *llvm::createLoopDeletionPass() {
/// isLoopDead - Determined if a loop is dead. This assumes that we've already
/// checked for unique exit and exiting blocks, and that the code is in LCSSA
/// form.
bool LoopDeletion::isLoopDead(Loop *L,
bool LoopDeletion::isLoopDead(Loop *L, ScalarEvolution &SE,
SmallVectorImpl<BasicBlock *> &exitingBlocks,
SmallVectorImpl<BasicBlock *> &exitBlocks,
bool &Changed, BasicBlock *Preheader) {
@ -77,6 +77,8 @@ bool LoopDeletion::isLoopDead(Loop *L,
// sufficient to guarantee that no loop-variant values are used outside
// of the loop.
BasicBlock::iterator BI = exitBlock->begin();
bool AllEntriesInvariant = true;
bool AllOutgoingValuesSame = true;
while (PHINode *P = dyn_cast<PHINode>(BI)) {
Value *incoming = P->getIncomingValueForBlock(exitingBlocks[0]);
@ -85,17 +87,30 @@ bool LoopDeletion::isLoopDead(Loop *L,
// blocks, then it is impossible to statically determine which value should
// be used.
for (unsigned i = 1, e = exitingBlocks.size(); i < e; ++i) {
if (incoming != P->getIncomingValueForBlock(exitingBlocks[i]))
return false;
if (incoming != P->getIncomingValueForBlock(exitingBlocks[i])) {
AllOutgoingValuesSame = false;
break;
}
}
if (!AllOutgoingValuesSame)
break;
if (Instruction *I = dyn_cast<Instruction>(incoming))
if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator()))
return false;
if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) {
AllEntriesInvariant = false;
break;
}
++BI;
}
if (Changed)
SE.forgetLoopDispositions(L);
if (!AllEntriesInvariant || !AllOutgoingValuesSame)
return false;
// Make sure that no instructions in the block have potential side-effects.
// This includes instructions that could write to memory, and loads that are
// marked volatile. This could be made more aggressive by using aliasing
@ -153,14 +168,15 @@ bool LoopDeletion::runOnLoop(Loop *L, LPPassManager &) {
if (exitBlocks.size() != 1)
return false;
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
// Finally, we have to check that the loop really is dead.
bool Changed = false;
if (!isLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader))
if (!isLoopDead(L, SE, exitingBlocks, exitBlocks, Changed, preheader))
return Changed;
// Don't remove loops for which we can't solve the trip count.
// They could be infinite, in which case we'd be changing program behavior.
ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE();
const SCEV *S = SE.getMaxBackedgeTakenCount(L);
if (isa<SCEVCouldNotCompute>(S))
return Changed;

View File

@ -0,0 +1,56 @@
; RUN: opt -S -analyze -scalar-evolution -loop-deletion -scalar-evolution < %s | FileCheck %s --check-prefix=SCEV-EXPRS
; RUN: opt -S -loop-deletion < %s | FileCheck %s --check-prefix=IR-AFTER-TRANSFORM
; RUN: opt -S -indvars -loop-deletion -indvars < %s | FileCheck %s --check-prefix=ORIGINAL-CRASH
; Checking for a crash. Loop-deletion would change the loop
; disposition of an instruction, but not update SCEV.
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.11.0"
define void @pr27570() {
; IR-AFTER-TRANSFORM-LABEL: @pr27570(
; ORIGINAL-CRASH: @pr27570(
entry:
br label %for.cond
for.cond: ; preds = %for.cond14, %entry
%f.0 = phi i32 [ 20, %entry ], [ 0, %for.cond14 ]
br label %for.body
for.body: ; preds = %for.inc11, %for.cond
; IR-AFTER-TRANSFORM: for.body:
; IR-AFTER-TRANSFORM: %cmp = icmp eq i32 %val, -1
; IR-AFTER-TRANSFORM: %conv7 = zext i1 %cmp to i32
; IR-AFTER-TRANSFORM: for.body6:
; SCEV-EXPRS: %conv7 = zext i1 %cmp to i32
; SCEV-EXPRS: %conv7 = zext i1 %cmp to i32
; SCEV-EXPRS-NEXT: --> {{.*}} LoopDispositions: { %for.body: Variant, %for.cond: Variant, %for.body6: Invariant }
%val = phi i32 [ -20, %for.cond ], [ %inc12, %for.inc11 ]
%g.040 = phi i32 [ -20, %for.cond ], [ %and.lcssa, %for.inc11 ]
br label %for.body6
for.body6: ; preds = %for.body6, %for.body
%h.039 = phi i32 [ 1, %for.body ], [ %inc, %for.body6 ]
%g.138 = phi i32 [ %g.040, %for.body ], [ %and, %for.body6 ]
%cmp = icmp eq i32 %val, -1
%conv7 = zext i1 %cmp to i32
%add.i = add nsw i32 %conv7, %h.039
%sext = shl i32 %add.i, 24
%conv8 = ashr exact i32 %sext, 24
%cmp9 = icmp eq i32 %conv8, %f.0
%conv10 = zext i1 %cmp9 to i32
%and = and i32 %conv10, %g.138
%inc = add i32 %h.039, 1
br i1 undef, label %for.inc11, label %for.body6
for.inc11: ; preds = %for.body6
%and.lcssa = phi i32 [ %and, %for.body6 ]
%inc12 = add nsw i32 %val, 1
%tobool = icmp eq i32 %inc12, 0
br i1 %tobool, label %for.cond14, label %for.body
for.cond14: ; preds = %for.cond14, %for.inc11
br i1 undef, label %for.cond, label %for.cond14
}