summaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
authorSebastian Pop <spop@codeaurora.org>2014-05-27 22:41:45 +0000
committerSebastian Pop <spop@codeaurora.org>2014-05-27 22:41:45 +0000
commit421b2c571cfbd4cad3a6b7834792ae45c87d9c64 (patch)
tree911052ad99894373f49c6c5b23ce15d061180c28 /lib/Analysis
parent50adf380805c0c239be0e3806b568f1af8cdff45 (diff)
downloadllvm-421b2c571cfbd4cad3a6b7834792ae45c87d9c64.tar.gz
llvm-421b2c571cfbd4cad3a6b7834792ae45c87d9c64.tar.bz2
llvm-421b2c571cfbd4cad3a6b7834792ae45c87d9c64.tar.xz
remove constant terms
The delinearization is needed only to remove the non linearity induced by expressions involving multiplications of parameters and induction variables. There is no problem in dealing with constant times parameters, or constant times an induction variable. For this reason, the current patch discards all constant terms and multipliers before running the delinearization algorithm on the terms. The only thing remaining in the term expressions are parameters and multiply expressions of parameters: these simplified term expressions are passed to the array shape recognizer that will not recognize constant dimensions anymore: these will be recognized as different strides in parametric subscripts. The only important special case of a constant dimension is the size of elements. Instead of relying on the delinearization to infer the size of an element, compute the element size from the base address type. This is a much more precise way of computing the element size than before, as we would have mixed together the size of an element with the strides of the innermost dimension. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209691 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/Delinearization.cpp4
-rw-r--r--lib/Analysis/DependenceAnalysis.cpp13
-rw-r--r--lib/Analysis/ScalarEvolution.cpp88
3 files changed, 80 insertions, 25 deletions
diff --git a/lib/Analysis/Delinearization.cpp b/lib/Analysis/Delinearization.cpp
index 1a588211a2..6c8702787d 100644
--- a/lib/Analysis/Delinearization.cpp
+++ b/lib/Analysis/Delinearization.cpp
@@ -108,8 +108,8 @@ void Delinearization::print(raw_ostream &O, const Module *) const {
O << "AddRec: " << *AR << "\n";
SmallVector<const SCEV *, 3> Subscripts, Sizes;
- const SCEV *Res = AR->delinearize(*SE, Subscripts, Sizes);
- if (Res == AR || Subscripts.size() == 0 || Sizes.size() == 0 ||
+ const SCEV *Res = AR->delinearize(*SE, Subscripts, Sizes, SE->getElementSize(Inst));
+ if (Subscripts.size() == 0 || Sizes.size() == 0 ||
Subscripts.size() != Sizes.size()) {
O << "failed to delinearize\n";
continue;
diff --git a/lib/Analysis/DependenceAnalysis.cpp b/lib/Analysis/DependenceAnalysis.cpp
index 57231b8325..33cb20685c 100644
--- a/lib/Analysis/DependenceAnalysis.cpp
+++ b/lib/Analysis/DependenceAnalysis.cpp
@@ -3180,9 +3180,10 @@ void DependenceAnalysis::updateDirection(Dependence::DVEntry &Level,
/// source and destination array references are recurrences on a nested loop,
/// this function flattens the nested recurrences into separate recurrences
/// for each loop level.
-bool
-DependenceAnalysis::tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV,
- SmallVectorImpl<Subscript> &Pair) const {
+bool DependenceAnalysis::tryDelinearize(const SCEV *SrcSCEV,
+ const SCEV *DstSCEV,
+ SmallVectorImpl<Subscript> &Pair,
+ const SCEV *ElementSize) const {
const SCEVAddRecExpr *SrcAR = dyn_cast<SCEVAddRecExpr>(SrcSCEV);
const SCEVAddRecExpr *DstAR = dyn_cast<SCEVAddRecExpr>(DstSCEV);
if (!SrcAR || !DstAR || !SrcAR->isAffine() || !DstAR->isAffine())
@@ -3195,7 +3196,7 @@ DependenceAnalysis::tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV,
// Second step: find subscript sizes.
SmallVector<const SCEV *, 4> Sizes;
- SE->findArrayDimensions(Terms, Sizes);
+ SE->findArrayDimensions(Terms, Sizes, ElementSize);
// Third step: compute the access functions for each subscript.
SmallVector<const SCEV *, 4> SrcSubscripts, DstSubscripts;
@@ -3353,7 +3354,7 @@ Dependence *DependenceAnalysis::depends(Instruction *Src,
}
if (Delinearize && Pairs == 1 && CommonLevels > 1 &&
- tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair)) {
+ tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair, SE->getElementSize(Src))) {
DEBUG(dbgs() << " delinerized GEP\n");
Pairs = Pair.size();
}
@@ -3777,7 +3778,7 @@ const SCEV *DependenceAnalysis::getSplitIteration(const Dependence *Dep,
}
if (Delinearize && Pairs == 1 && CommonLevels > 1 &&
- tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair)) {
+ tryDelinearize(Pair[0].Src, Pair[0].Dst, Pair, SE->getElementSize(Src))) {
DEBUG(dbgs() << " delinerized GEP\n");
Pairs = Pair.size();
}
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index 1087e5df16..4e4eb21433 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -6944,7 +6944,7 @@ struct SCEVCollectTerms {
: Terms(T) {}
bool follow(const SCEV *S) {
- if (isa<SCEVUnknown>(S) || isa<SCEVConstant>(S) || isa<SCEVMulExpr>(S)) {
+ if (isa<SCEVUnknown>(S) || isa<SCEVMulExpr>(S)) {
if (!containsUndefs(S))
Terms.push_back(S);
@@ -7356,13 +7356,46 @@ static inline int numberOfTerms(const SCEV *S) {
return 1;
}
+static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
+ if (isa<SCEVConstant>(T))
+ return nullptr;
+
+ if (isa<SCEVUnknown>(T))
+ return T;
+
+ if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
+ SmallVector<const SCEV *, 2> Factors;
+ for (const SCEV *Op : M->operands())
+ if (!isa<SCEVConstant>(Op))
+ Factors.push_back(Op);
+
+ return SE.getMulExpr(Factors);
+ }
+
+ return T;
+}
+
+/// Return the size of an element read or written by Inst.
+const SCEV *ScalarEvolution::getElementSize(Instruction *Inst) {
+ Type *Ty;
+ if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
+ Ty = Store->getValueOperand()->getType();
+ else if (LoadInst *Load = dyn_cast<LoadInst>(Inst))
+ Ty = Load->getPointerOperand()->getType();
+ else
+ return nullptr;
+
+ Type *ETy = getEffectiveSCEVType(PointerType::getUnqual(Ty));
+ return getSizeOfExpr(ETy, Ty);
+}
+
/// Second step of delinearization: compute the array dimensions Sizes from the
/// set of Terms extracted from the memory access function of this SCEVAddRec.
-void ScalarEvolution::findArrayDimensions(
- SmallVectorImpl<const SCEV *> &Terms,
- SmallVectorImpl<const SCEV *> &Sizes) const {
+void ScalarEvolution::findArrayDimensions(SmallVectorImpl<const SCEV *> &Terms,
+ SmallVectorImpl<const SCEV *> &Sizes,
+ const SCEV *ElementSize) const {
- if (Terms.size() < 2)
+ if (Terms.size() < 1)
return;
// Early return when Terms do not contain parameters: we do not delinearize
@@ -7385,20 +7418,37 @@ void ScalarEvolution::findArrayDimensions(
return numberOfTerms(LHS) > numberOfTerms(RHS);
});
+ ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this);
+
+ // Divide all terms by the element size.
+ for (const SCEV *&Term : Terms) {
+ const SCEV *Q, *R;
+ SCEVDivision::divide(SE, Term, ElementSize, &Q, &R);
+ Term = Q;
+ }
+
+ SmallVector<const SCEV *, 4> NewTerms;
+
+ // Remove constant factors.
+ for (const SCEV *T : Terms)
+ if (const SCEV *NewT = removeConstantFactors(SE, T))
+ NewTerms.push_back(NewT);
+
DEBUG({
dbgs() << "Terms after sorting:\n";
- for (const SCEV *T : Terms)
+ for (const SCEV *T : NewTerms)
dbgs() << *T << "\n";
});
- ScalarEvolution &SE = *const_cast<ScalarEvolution *>(this);
- bool Res = findArrayDimensionsRec(SE, Terms, Sizes);
-
- if (!Res) {
+ if (NewTerms.empty() ||
+ !findArrayDimensionsRec(SE, NewTerms, Sizes)) {
Sizes.clear();
return;
}
+ // The last element to be pushed into Sizes is the size of an element.
+ Sizes.push_back(ElementSize);
+
DEBUG({
dbgs() << "Sizes:\n";
for (const SCEV *S : Sizes)
@@ -7433,9 +7483,14 @@ const SCEV *SCEVAddRecExpr::computeAccessFunctions(
Res = Q;
+ // Do not record the last subscript corresponding to the size of elements in
+ // the array.
if (i == Last) {
- // Do not record the last subscript corresponding to the size of elements
- // in the array.
+
+ // Bail out if the remainder is too complex.
+ if (isa<SCEVAddRecExpr>(R))
+ return nullptr;
+
Remainder = R;
continue;
}
@@ -7507,10 +7562,9 @@ const SCEV *SCEVAddRecExpr::computeAccessFunctions(
/// asking for the SCEV of the memory access with respect to all enclosing
/// loops, calling SCEV->delinearize on that and printing the results.
-const SCEV *
-SCEVAddRecExpr::delinearize(ScalarEvolution &SE,
- SmallVectorImpl<const SCEV *> &Subscripts,
- SmallVectorImpl<const SCEV *> &Sizes) const {
+const SCEV *SCEVAddRecExpr::delinearize(
+ ScalarEvolution &SE, SmallVectorImpl<const SCEV *> &Subscripts,
+ SmallVectorImpl<const SCEV *> &Sizes, const SCEV *ElementSize) const {
// First step: collect parametric terms.
SmallVector<const SCEV *, 4> Terms;
collectParametricTerms(SE, Terms);
@@ -7519,7 +7573,7 @@ SCEVAddRecExpr::delinearize(ScalarEvolution &SE,
return nullptr;
// Second step: find subscript sizes.
- SE.findArrayDimensions(Terms, Sizes);
+ SE.findArrayDimensions(Terms, Sizes, ElementSize);
if (Sizes.empty())
return nullptr;