mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-24 19:44:49 +00:00
[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:
parent
b78000e38b
commit
045a03d9a7
@ -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;
|
||||
|
56
test/Transforms/LoopDeletion/update-scev.ll
Normal file
56
test/Transforms/LoopDeletion/update-scev.ll
Normal 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
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user