[LLE] Use the PredicatedScalarEvolution interface to query SCEVs for dependences

Summary:
LAA uses the PredicatedScalarEvolution interface, so it can produce
forward/backward dependences having SCEVs that are AddRecExprs only after being
transformed by PredicatedScalarEvolution.

Use PredicatedScalarEvolution to get the expected expressions.

Reviewers: anemet

Subscribers: llvm-commits, sanjoy

Differential Revision: http://reviews.llvm.org/D15382

llvm-svn: 255241
This commit is contained in:
Silviu Baranga 2015-12-10 11:07:18 +00:00
parent 7b93d66208
commit 86de80db37
1 changed files with 15 additions and 16 deletions

View File

@ -61,7 +61,7 @@ struct StoreToLoadForwardingCandidate {
/// \brief Return true if the dependence from the store to the load has a /// \brief Return true if the dependence from the store to the load has a
/// distance of one. E.g. A[i+1] = A[i] /// distance of one. E.g. A[i+1] = A[i]
bool isDependenceDistanceOfOne(ScalarEvolution *SE) const { bool isDependenceDistanceOfOne(PredicatedScalarEvolution &PSE) const {
Value *LoadPtr = Load->getPointerOperand(); Value *LoadPtr = Load->getPointerOperand();
Value *StorePtr = Store->getPointerOperand(); Value *StorePtr = Store->getPointerOperand();
Type *LoadPtrType = LoadPtr->getType(); Type *LoadPtrType = LoadPtr->getType();
@ -75,13 +75,13 @@ struct StoreToLoadForwardingCandidate {
auto &DL = Load->getParent()->getModule()->getDataLayout(); auto &DL = Load->getParent()->getModule()->getDataLayout();
unsigned TypeByteSize = DL.getTypeAllocSize(const_cast<Type *>(LoadType)); unsigned TypeByteSize = DL.getTypeAllocSize(const_cast<Type *>(LoadType));
auto *LoadPtrSCEV = cast<SCEVAddRecExpr>(SE->getSCEV(LoadPtr)); auto *LoadPtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(LoadPtr));
auto *StorePtrSCEV = cast<SCEVAddRecExpr>(SE->getSCEV(StorePtr)); auto *StorePtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(StorePtr));
// We don't need to check non-wrapping here because forward/backward // We don't need to check non-wrapping here because forward/backward
// dependence wouldn't be valid if these weren't monotonic accesses. // dependence wouldn't be valid if these weren't monotonic accesses.
auto *Dist = auto *Dist = cast<SCEVConstant>(
cast<SCEVConstant>(SE->getMinusSCEV(StorePtrSCEV, LoadPtrSCEV)); PSE.getSE()->getMinusSCEV(StorePtrSCEV, LoadPtrSCEV));
const APInt &Val = Dist->getValue()->getValue(); const APInt &Val = Dist->getValue()->getValue();
return Val.abs() == TypeByteSize; return Val.abs() == TypeByteSize;
} }
@ -114,8 +114,8 @@ bool doesStoreDominatesAllLatches(BasicBlock *StoreBlock, Loop *L,
class LoadEliminationForLoop { class LoadEliminationForLoop {
public: public:
LoadEliminationForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI, LoadEliminationForLoop(Loop *L, LoopInfo *LI, const LoopAccessInfo &LAI,
DominatorTree *DT, ScalarEvolution *SE) DominatorTree *DT)
: L(L), LI(LI), LAI(LAI), DT(DT), SE(SE) {} : L(L), LI(LI), LAI(LAI), DT(DT), PSE(LAI.PSE) {}
/// \brief Look through the loop-carried and loop-independent dependences in /// \brief Look through the loop-carried and loop-independent dependences in
/// this loop and find store->load dependences. /// this loop and find store->load dependences.
@ -223,8 +223,8 @@ public:
// block so deciding which one forwards is easy. The later one forwards // block so deciding which one forwards is easy. The later one forwards
// as long as they both have a dependence distance of one to the load. // as long as they both have a dependence distance of one to the load.
if (Cand.Store->getParent() == OtherCand->Store->getParent() && if (Cand.Store->getParent() == OtherCand->Store->getParent() &&
Cand.isDependenceDistanceOfOne(SE) && Cand.isDependenceDistanceOfOne(PSE) &&
OtherCand->isDependenceDistanceOfOne(SE)) { OtherCand->isDependenceDistanceOfOne(PSE)) {
// They are in the same block, the later one will forward to the load. // They are in the same block, the later one will forward to the load.
if (getInstrIndex(OtherCand->Store) < getInstrIndex(Cand.Store)) if (getInstrIndex(OtherCand->Store) < getInstrIndex(Cand.Store))
OtherCand = &Cand; OtherCand = &Cand;
@ -372,7 +372,7 @@ public:
// store %y, %gep_i_plus_1 // store %y, %gep_i_plus_1
Value *Ptr = Cand.Load->getPointerOperand(); Value *Ptr = Cand.Load->getPointerOperand();
auto *PtrSCEV = cast<SCEVAddRecExpr>(SE->getSCEV(Ptr)); auto *PtrSCEV = cast<SCEVAddRecExpr>(PSE.getSCEV(Ptr));
auto *PH = L->getLoopPreheader(); auto *PH = L->getLoopPreheader();
Value *InitialPtr = SEE.expandCodeFor(PtrSCEV->getStart(), Ptr->getType(), Value *InitialPtr = SEE.expandCodeFor(PtrSCEV->getStart(), Ptr->getType(),
PH->getTerminator()); PH->getTerminator());
@ -436,7 +436,7 @@ public:
// Check whether the SCEV difference is the same as the induction step, // Check whether the SCEV difference is the same as the induction step,
// thus we load the value in the next iteration. // thus we load the value in the next iteration.
if (!Cand.isDependenceDistanceOfOne(SE)) if (!Cand.isDependenceDistanceOfOne(PSE))
continue; continue;
++NumForwarding; ++NumForwarding;
@ -468,7 +468,7 @@ public:
// Point of no-return, start the transformation. First, version the loop if // Point of no-return, start the transformation. First, version the loop if
// necessary. // necessary.
if (!Checks.empty() || !LAI.PSE.getUnionPredicate().isAlwaysTrue()) { if (!Checks.empty() || !LAI.PSE.getUnionPredicate().isAlwaysTrue()) {
LoopVersioning LV(LAI, L, LI, DT, SE, false); LoopVersioning LV(LAI, L, LI, DT, PSE.getSE(), false);
LV.setAliasChecks(std::move(Checks)); LV.setAliasChecks(std::move(Checks));
LV.setSCEVChecks(LAI.PSE.getUnionPredicate()); LV.setSCEVChecks(LAI.PSE.getUnionPredicate());
LV.versionLoop(); LV.versionLoop();
@ -476,7 +476,7 @@ public:
// Next, propagate the value stored by the store to the users of the load. // Next, propagate the value stored by the store to the users of the load.
// Also for the first iteration, generate the initial value of the load. // Also for the first iteration, generate the initial value of the load.
SCEVExpander SEE(*SE, L->getHeader()->getModule()->getDataLayout(), SCEVExpander SEE(*PSE.getSE(), L->getHeader()->getModule()->getDataLayout(),
"storeforward"); "storeforward");
for (const auto &Cand : Candidates) for (const auto &Cand : Candidates)
propagateStoredValueToLoadUsers(Cand, SEE); propagateStoredValueToLoadUsers(Cand, SEE);
@ -496,7 +496,7 @@ private:
LoopInfo *LI; LoopInfo *LI;
const LoopAccessInfo &LAI; const LoopAccessInfo &LAI;
DominatorTree *DT; DominatorTree *DT;
ScalarEvolution *SE; PredicatedScalarEvolution PSE;
}; };
/// \brief The pass. Most of the work is delegated to the per-loop /// \brief The pass. Most of the work is delegated to the per-loop
@ -511,7 +511,6 @@ public:
auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); auto *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
auto *LAA = &getAnalysis<LoopAccessAnalysis>(); auto *LAA = &getAnalysis<LoopAccessAnalysis>();
auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
auto *SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE();
// Build up a worklist of inner-loops to vectorize. This is necessary as the // Build up a worklist of inner-loops to vectorize. This is necessary as the
// act of distributing a loop creates new loops and can invalidate iterators // act of distributing a loop creates new loops and can invalidate iterators
@ -529,7 +528,7 @@ public:
for (Loop *L : Worklist) { for (Loop *L : Worklist) {
const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap()); const LoopAccessInfo &LAI = LAA->getInfo(L, ValueToValueMap());
// The actual work is performed by LoadEliminationForLoop. // The actual work is performed by LoadEliminationForLoop.
LoadEliminationForLoop LEL(L, LI, LAI, DT, SE); LoadEliminationForLoop LEL(L, LI, LAI, DT);
Changed |= LEL.processLoop(); Changed |= LEL.processLoop();
} }