mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Make LoopSimplify change conditional branches in loop exiting blocks
which branch on undef to branch on a boolean constant for the edge exiting the loop. This helps ScalarEvolution compute trip counts for loops. Teach ScalarEvolution to recognize single-value PHIs, when safe, and ForgetSymbolicName to forget such single-value PHI nodes as apprpriate in ForgetSymbolicName. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@97126 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a5028a6463
commit
8566963713
@ -2549,14 +2549,14 @@ PushDefUseChildren(Instruction *I,
|
||||
/// the Scalars map if they reference SymName. This is used during PHI
|
||||
/// resolution.
|
||||
void
|
||||
ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
|
||||
ScalarEvolution::ForgetSymbolicName(Instruction *PN, const SCEV *SymName) {
|
||||
SmallVector<Instruction *, 16> Worklist;
|
||||
PushDefUseChildren(I, Worklist);
|
||||
PushDefUseChildren(PN, Worklist);
|
||||
|
||||
SmallPtrSet<Instruction *, 8> Visited;
|
||||
Visited.insert(I);
|
||||
Visited.insert(PN);
|
||||
while (!Worklist.empty()) {
|
||||
I = Worklist.pop_back_val();
|
||||
Instruction *I = Worklist.pop_back_val();
|
||||
if (!Visited.insert(I)) continue;
|
||||
|
||||
std::map<SCEVCallbackVH, const SCEV *>::iterator It =
|
||||
@ -2568,12 +2568,15 @@ ScalarEvolution::ForgetSymbolicName(Instruction *I, const SCEV *SymName) {
|
||||
continue;
|
||||
|
||||
// SCEVUnknown for a PHI either means that it has an unrecognized
|
||||
// structure, or it's a PHI that's in the progress of being computed
|
||||
// by createNodeForPHI. In the former case, additional loop trip
|
||||
// count information isn't going to change anything. In the later
|
||||
// case, createNodeForPHI will perform the necessary updates on its
|
||||
// own when it gets to that point.
|
||||
if (!isa<PHINode>(I) || !isa<SCEVUnknown>(It->second)) {
|
||||
// structure, it's a PHI that's in the progress of being computed
|
||||
// by createNodeForPHI, or it's a single-value PHI. In the first case,
|
||||
// additional loop trip count information isn't going to change anything.
|
||||
// In the second case, createNodeForPHI will perform the necessary
|
||||
// updates on its own when it gets to that point. In the third, we do
|
||||
// want to forget the SCEVUnknown.
|
||||
if (!isa<PHINode>(I) ||
|
||||
!isa<SCEVUnknown>(It->second) ||
|
||||
(I != PN && It->second == SymName)) {
|
||||
ValuesAtScopes.erase(It->second);
|
||||
Scalars.erase(It);
|
||||
}
|
||||
@ -2696,9 +2699,21 @@ const SCEV *ScalarEvolution::createNodeForPHI(PHINode *PN) {
|
||||
return SymbolicName;
|
||||
}
|
||||
|
||||
// It's tempting to recognize PHIs with a unique incoming value, however
|
||||
// this leads passes like indvars to break LCSSA form. Fortunately, such
|
||||
// PHIs are rare, as instcombine zaps them.
|
||||
// If the PHI has a single incoming value, follow that value, unless the
|
||||
// PHI's incoming blocks are in a different loop, in which case doing so
|
||||
// risks breaking LCSSA form. Instcombine would normally zap these, but
|
||||
// it doesn't have DominatorTree information, so it may miss cases.
|
||||
if (Value *V = PN->hasConstantValue(DT)) {
|
||||
bool AllSameLoop = true;
|
||||
Loop *PNLoop = LI->getLoopFor(PN->getParent());
|
||||
for (size_t i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
|
||||
if (LI->getLoopFor(PN->getIncomingBlock(i)) != PNLoop) {
|
||||
AllSameLoop = false;
|
||||
break;
|
||||
}
|
||||
if (AllSameLoop)
|
||||
return getSCEV(V);
|
||||
}
|
||||
|
||||
// If it's not a loop phi, we can't handle it yet.
|
||||
return getUnknown(PN);
|
||||
|
@ -384,17 +384,18 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
// in this loop, insert a canonical induction variable of the largest size.
|
||||
Value *IndVar = 0;
|
||||
if (NeedCannIV) {
|
||||
// Check to see if the loop already has a canonical-looking induction
|
||||
// variable. If one is present and it's wider than the planned canonical
|
||||
// induction variable, temporarily remove it, so that the Rewriter
|
||||
// doesn't attempt to reuse it.
|
||||
PHINode *OldCannIV = L->getCanonicalInductionVariable();
|
||||
if (OldCannIV) {
|
||||
// Check to see if the loop already has any canonical-looking induction
|
||||
// variables. If any are present and wider than the planned canonical
|
||||
// induction variable, temporarily remove them, so that the Rewriter
|
||||
// doesn't attempt to reuse them.
|
||||
SmallVector<PHINode *, 2> OldCannIVs;
|
||||
while (PHINode *OldCannIV = L->getCanonicalInductionVariable()) {
|
||||
if (SE->getTypeSizeInBits(OldCannIV->getType()) >
|
||||
SE->getTypeSizeInBits(LargestType))
|
||||
OldCannIV->removeFromParent();
|
||||
else
|
||||
OldCannIV = 0;
|
||||
break;
|
||||
OldCannIVs.push_back(OldCannIV);
|
||||
}
|
||||
|
||||
IndVar = Rewriter.getOrInsertCanonicalInductionVariable(L, LargestType);
|
||||
@ -404,17 +405,21 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
DEBUG(dbgs() << "INDVARS: New CanIV: " << *IndVar << '\n');
|
||||
|
||||
// Now that the official induction variable is established, reinsert
|
||||
// the old canonical-looking variable after it so that the IR remains
|
||||
// consistent. It will be deleted as part of the dead-PHI deletion at
|
||||
// any old canonical-looking variables after it so that the IR remains
|
||||
// consistent. They will be deleted as part of the dead-PHI deletion at
|
||||
// the end of the pass.
|
||||
if (OldCannIV)
|
||||
OldCannIV->insertAfter(cast<Instruction>(IndVar));
|
||||
while (!OldCannIVs.empty()) {
|
||||
PHINode *OldCannIV = OldCannIVs.pop_back_val();
|
||||
OldCannIV->insertBefore(L->getHeader()->getFirstNonPHI());
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a trip count expression, rewrite the loop's exit condition
|
||||
// using it. We can currently only handle loops with a single exit.
|
||||
ICmpInst *NewICmp = 0;
|
||||
if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) && ExitingBlock) {
|
||||
if (!isa<SCEVCouldNotCompute>(BackedgeTakenCount) &&
|
||||
!BackedgeTakenCount->isZero() &&
|
||||
ExitingBlock) {
|
||||
assert(NeedCannIV &&
|
||||
"LinearFunctionTestReplace requires a canonical induction variable");
|
||||
// Can't rewrite non-branch yet.
|
||||
|
@ -159,6 +159,22 @@ ReprocessLoop:
|
||||
}
|
||||
}
|
||||
|
||||
// If there are exiting blocks with branches on undef, resolve the undef in
|
||||
// the direction which will exit the loop. This will help simplify loop
|
||||
// trip count computations.
|
||||
SmallVector<BasicBlock*, 8> ExitingBlocks;
|
||||
L->getExitingBlocks(ExitingBlocks);
|
||||
for (SmallVectorImpl<BasicBlock *>::iterator I = ExitingBlocks.begin(),
|
||||
E = ExitingBlocks.end(); I != E; ++I)
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>((*I)->getTerminator()))
|
||||
if (BI->isConditional()) {
|
||||
if (UndefValue *Cond = dyn_cast<UndefValue>(BI->getCondition())) {
|
||||
BI->setCondition(ConstantInt::get(Cond->getType(),
|
||||
!L->contains(BI->getSuccessor(0))));
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Does the loop already have a preheader? If so, don't insert one.
|
||||
BasicBlock *Preheader = L->getLoopPreheader();
|
||||
if (!Preheader) {
|
||||
@ -250,8 +266,6 @@ ReprocessLoop:
|
||||
break;
|
||||
}
|
||||
if (UniqueExit) {
|
||||
SmallVector<BasicBlock*, 8> ExitingBlocks;
|
||||
L->getExitingBlocks(ExitingBlocks);
|
||||
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
|
||||
BasicBlock *ExitingBlock = ExitingBlocks[i];
|
||||
if (!ExitingBlock->getSinglePredecessor()) continue;
|
||||
|
@ -8,8 +8,7 @@
|
||||
define i64 @hammer_time(i64 %modulep, i64 %physfree) nounwind ssp noredzone noimplicitfloat {
|
||||
; CHECK: hammer_time:
|
||||
; CHECK: movq $Xrsvd, %rax
|
||||
; CHECK: movq $Xrsvd, %rsi
|
||||
; CHECK: movq $Xrsvd, %rdi
|
||||
; CHECK: movq $Xrsvd, %rcx
|
||||
entry:
|
||||
br i1 undef, label %if.then, label %if.end
|
||||
|
||||
|
@ -7,7 +7,7 @@ define i32 @test() {
|
||||
LoopHead: ; preds = %LoopHead, %0, %0
|
||||
%A = phi i32 [ 7, %0 ], [ 7, %0 ], [ %B, %LoopHead ] ; <i32> [#uses=1]
|
||||
%B = add i32 %A, 1 ; <i32> [#uses=2]
|
||||
br i1 undef, label %LoopHead, label %Out
|
||||
br i1 true, label %LoopHead, label %Out
|
||||
|
||||
Out: ; preds = %LoopHead
|
||||
ret i32 %B
|
||||
|
65
test/Transforms/LoopDeletion/simplify-then-delete.ll
Normal file
65
test/Transforms/LoopDeletion/simplify-then-delete.ll
Normal file
@ -0,0 +1,65 @@
|
||||
; RUN: opt < %s -S -indvars -loop-deletion -simplifycfg | FileCheck %s
|
||||
; PR5794
|
||||
|
||||
; Indvars and loop deletion should be able to eliminate all looping
|
||||
; in this testcase.
|
||||
|
||||
; CHECK: define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind {
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
; CHECK-NEXT: }
|
||||
|
||||
target datalayout = "e-p:64:64:64"
|
||||
|
||||
define i32 @pmat(i32 %m, i32 %n, double* %y) nounwind {
|
||||
entry:
|
||||
%cmp4 = icmp sgt i32 %m, 0
|
||||
br i1 %cmp4, label %bb.n10, label %w.e12
|
||||
|
||||
w.c:
|
||||
%cmp = icmp slt i32 %inc11, %m
|
||||
br i1 %cmp, label %w.c2.p, label %w.c.w.e12c
|
||||
|
||||
w.c.w.e12c:
|
||||
br label %w.c.w.e12c.s
|
||||
|
||||
w.c.w.e12c.s:
|
||||
br label %w.e12
|
||||
|
||||
bb.n10:
|
||||
%cmp51 = icmp sgt i32 %n, 0
|
||||
br i1 %cmp51, label %bb.n10.w.c.w.e12c.sc, label %bb.n10.bb.n10.sc
|
||||
|
||||
bb.n10.bb.n10.sc:
|
||||
br label %bb.n10.s
|
||||
|
||||
bb.n10.w.c.w.e12c.sc:
|
||||
br label %w.c.w.e12c.s
|
||||
|
||||
bb.n10.s:
|
||||
br label %w.c2.p
|
||||
|
||||
w.c2.p:
|
||||
%i.05 = phi i32 [ 0, %bb.n10.s ], [ %inc11, %w.c ]
|
||||
br i1 false, label %bb.n, label %w.e
|
||||
|
||||
w.c2:
|
||||
br i1 undef, label %w.b6, label %w.c2.w.ec
|
||||
|
||||
w.c2.w.ec:
|
||||
br label %w.e
|
||||
|
||||
bb.n:
|
||||
br label %w.b6
|
||||
|
||||
w.b6:
|
||||
br label %w.c2
|
||||
|
||||
w.e:
|
||||
%i.08 = phi i32 [ undef, %w.c2.w.ec ], [ %i.05, %w.c2.p ]
|
||||
%inc11 = add nsw i32 %i.08, 1
|
||||
br label %w.c
|
||||
|
||||
w.e12:
|
||||
ret i32 0
|
||||
}
|
Loading…
Reference in New Issue
Block a user