summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorHongbin Zheng <etherzhhb@gmail.com>2017-10-12 02:54:11 +0000
committerHongbin Zheng <etherzhhb@gmail.com>2017-10-12 02:54:11 +0000
commitd36f2030e245da16893e0ef577c9a57deb6642af (patch)
treedfa4ae9d3db4a9dccc443c4cd3a7daed1c8ef2b3 /llvm/lib
parent8d85ced1d1b6f95d7b4fc1f11e9234063ba72966 (diff)
downloadbcm5719-llvm-d36f2030e245da16893e0ef577c9a57deb6642af.tar.gz
bcm5719-llvm-d36f2030e245da16893e0ef577c9a57deb6642af.zip
[SimplifyIndVar] Replace IVUsers with loop invariant whenever possible
Differential Revision: https://reviews.llvm.org/D38415 llvm-svn: 315551
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp3
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyIndVar.cpp86
2 files changed, 56 insertions, 33 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 10782963177..2de1fe7cf6a 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -1759,7 +1759,8 @@ void IndVarSimplify::simplifyAndExtend(Loop *L,
// Information about sign/zero extensions of CurrIV.
IndVarSimplifyVisitor Visitor(CurrIV, SE, TTI, DT);
- Changed |= simplifyUsersOfIV(CurrIV, SE, DT, LI, DeadInsts, &Visitor);
+ Changed |=
+ simplifyUsersOfIV(CurrIV, SE, DT, LI, DeadInsts, Rewriter, &Visitor);
if (Visitor.WI.WidestNativeType) {
WideIVs.push_back(Visitor.WI);
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 96088145bbc..08b84927c67 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -19,7 +19,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
-#include "llvm/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/ScalarEvolutionExpander.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/IRBuilder.h"
@@ -55,15 +55,17 @@ namespace {
LoopInfo *LI;
ScalarEvolution *SE;
DominatorTree *DT;
-
+ SCEVExpander &Rewriter;
SmallVectorImpl<WeakTrackingVH> &DeadInsts;
bool Changed;
public:
SimplifyIndvar(Loop *Loop, ScalarEvolution *SE, DominatorTree *DT,
- LoopInfo *LI, SmallVectorImpl<WeakTrackingVH> &Dead)
- : L(Loop), LI(LI), SE(SE), DT(DT), DeadInsts(Dead), Changed(false) {
+ LoopInfo *LI, SCEVExpander &Rewriter,
+ SmallVectorImpl<WeakTrackingVH> &Dead)
+ : L(Loop), LI(LI), SE(SE), DT(DT), Rewriter(Rewriter), DeadInsts(Dead),
+ Changed(false) {
assert(LI && "IV simplification requires LoopInfo");
}
@@ -77,7 +79,7 @@ namespace {
Value *foldIVUser(Instruction *UseInst, Instruction *IVOperand);
bool eliminateIdentitySCEV(Instruction *UseInst, Instruction *IVOperand);
- bool foldConstantSCEV(Instruction *UseInst);
+ bool replaceIVUserWithLoopInvariant(Instruction *UseInst);
bool eliminateOverflowIntrinsic(CallInst *CI);
bool eliminateIVUser(Instruction *UseInst, Instruction *IVOperand);
@@ -536,31 +538,34 @@ bool SimplifyIndvar::eliminateIVUser(Instruction *UseInst,
return false;
}
-/// Replace the UseInst with a constant if possible
-bool SimplifyIndvar::foldConstantSCEV(Instruction *I) {
+static Instruction *GetLoopInvariantInsertPosition(Loop *L, Instruction *Hint) {
+ if (auto *BB = L->getLoopPreheader())
+ return BB->getTerminator();
+
+ return Hint;
+}
+
+/// Replace the UseInst with a constant if possible.
+bool SimplifyIndvar::replaceIVUserWithLoopInvariant(Instruction *I) {
if (!SE->isSCEVable(I->getType()))
return false;
// Get the symbolic expression for this instruction.
const SCEV *S = SE->getSCEV(I);
- const Loop *L = LI->getLoopFor(I->getParent());
- S = SE->getSCEVAtScope(S, L);
- auto *C = dyn_cast<SCEVConstant>(S);
-
- if (!C)
+ if (!SE->isLoopInvariant(S, L))
return false;
- Constant *V = C->getValue();
- // The SCEV will have a different type than the instruction if the instruction
- // has a pointer type. Skip the replacement
- // TODO: Replace ConstantInt Zero by ConstantPointerNull
- if (V->getType() != I->getType())
+ // Do not generate something ridiculous even if S is loop invariant.
+ if (Rewriter.isHighCostExpansion(S, L, I))
return false;
- I->replaceAllUsesWith(V);
- DEBUG(dbgs() << "INDVARS: Replace IV user: " << *I << " with constant: " << *C
- << '\n');
+ auto *IP = GetLoopInvariantInsertPosition(L, I);
+ auto *Invariant = Rewriter.expandCodeFor(S, I->getType(), IP);
+
+ I->replaceAllUsesWith(Invariant);
+ DEBUG(dbgs() << "INDVARS: Replace IV user: " << *I
+ << " with loop invariant: " << *S << '\n');
++NumFoldedUser;
Changed = true;
DeadInsts.emplace_back(I);
@@ -702,7 +707,7 @@ bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
/// Add all uses of Def to the current IV's worklist.
static void pushIVUsers(
- Instruction *Def,
+ Instruction *Def, Loop *L,
SmallPtrSet<Instruction*,16> &Simplified,
SmallVectorImpl< std::pair<Instruction*,Instruction*> > &SimpleIVUsers) {
@@ -713,8 +718,19 @@ static void pushIVUsers(
// Also ensure unique worklist users.
// If Def is a LoopPhi, it may not be in the Simplified set, so check for
// self edges first.
- if (UI != Def && Simplified.insert(UI).second)
- SimpleIVUsers.push_back(std::make_pair(UI, Def));
+ if (UI == Def)
+ continue;
+
+ // Only change the current Loop, do not change the other parts (e.g. other
+ // Loops).
+ if (!L->contains(UI))
+ continue;
+
+ // Do not push the same instruction more than once.
+ if (!Simplified.insert(UI).second)
+ continue;
+
+ SimpleIVUsers.push_back(std::make_pair(UI, Def));
}
}
@@ -764,7 +780,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
// Push users of the current LoopPhi. In rare cases, pushIVUsers may be
// called multiple times for the same LoopPhi. This is the proper thing to
// do for loop header phis that use each other.
- pushIVUsers(CurrIV, Simplified, SimpleIVUsers);
+ pushIVUsers(CurrIV, L, Simplified, SimpleIVUsers);
while (!SimpleIVUsers.empty()) {
std::pair<Instruction*, Instruction*> UseOper =
@@ -774,8 +790,9 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
// Bypass back edges to avoid extra work.
if (UseInst == CurrIV) continue;
- // Try to replace UseInst with a constant before any other simplifications
- if (foldConstantSCEV(UseInst))
+ // Try to replace UseInst with a loop invariant before any other
+ // simplifications.
+ if (replaceIVUserWithLoopInvariant(UseInst))
continue;
Instruction *IVOperand = UseOper.second;
@@ -791,7 +808,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
continue;
if (eliminateIVUser(UseOper.first, IVOperand)) {
- pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
+ pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
continue;
}
@@ -801,7 +818,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
(isa<ShlOperator>(BO) && strengthenRightShift(BO, IVOperand))) {
// re-queue uses of the now modified binary operator and fall
// through to the checks that remain.
- pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
+ pushIVUsers(IVOperand, L, Simplified, SimpleIVUsers);
}
}
@@ -811,7 +828,7 @@ void SimplifyIndvar::simplifyUsers(PHINode *CurrIV, IVVisitor *V) {
continue;
}
if (isSimpleIVUser(UseOper.first, L, SE)) {
- pushIVUsers(UseOper.first, Simplified, SimpleIVUsers);
+ pushIVUsers(UseOper.first, L, Simplified, SimpleIVUsers);
}
}
}
@@ -824,8 +841,9 @@ void IVVisitor::anchor() { }
/// by using ScalarEvolution to analyze the IV's recurrence.
bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
LoopInfo *LI, SmallVectorImpl<WeakTrackingVH> &Dead,
- IVVisitor *V) {
- SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, Dead);
+ SCEVExpander &Rewriter, IVVisitor *V) {
+ SimplifyIndvar SIV(LI->getLoopFor(CurrIV->getParent()), SE, DT, LI, Rewriter,
+ Dead);
SIV.simplifyUsers(CurrIV, V);
return SIV.hasChanged();
}
@@ -834,9 +852,13 @@ bool simplifyUsersOfIV(PHINode *CurrIV, ScalarEvolution *SE, DominatorTree *DT,
/// loop. This does not actually change or add IVs.
bool simplifyLoopIVs(Loop *L, ScalarEvolution *SE, DominatorTree *DT,
LoopInfo *LI, SmallVectorImpl<WeakTrackingVH> &Dead) {
+ SCEVExpander Rewriter(*SE, SE->getDataLayout(), "indvars");
+#ifndef NDEBUG
+ Rewriter.setDebugType(DEBUG_TYPE);
+#endif
bool Changed = false;
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) {
- Changed |= simplifyUsersOfIV(cast<PHINode>(I), SE, DT, LI, Dead);
+ Changed |= simplifyUsersOfIV(cast<PHINode>(I), SE, DT, LI, Dead, Rewriter);
}
return Changed;
}
OpenPOWER on IntegriCloud