forked from OSchip/llvm-project
[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:
parent
7b93d66208
commit
86de80db37
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue