diff options
author | Adam Nemet <anemet@apple.com> | 2016-03-24 04:28:47 +0000 |
---|---|---|
committer | Adam Nemet <anemet@apple.com> | 2016-03-24 04:28:47 +0000 |
commit | 279784ffc4e48fa7da8bd2c57ee0e31789a1bed1 (patch) | |
tree | ec20b6857461d3d4efec40c558d029cd481220a1 /llvm/lib/Analysis/LoopAccessAnalysis.cpp | |
parent | 972bea8a2e56cd3651e79a6080ad94cfeb8f887f (diff) | |
download | bcm5719-llvm-279784ffc4e48fa7da8bd2c57ee0e31789a1bed1.tar.gz bcm5719-llvm-279784ffc4e48fa7da8bd2c57ee0e31789a1bed1.zip |
[LAA] Support memchecks involving loop-invariant addresses
We used to only allow SCEVAddRecExpr for pointer expressions in order to
be able to compute the bounds. However this is also trivially possible
for loop-invariant addresses (scUnknown) since then the bounds are the
address itself.
Interestingly, we used allow this for the special case when the
loop-invariant address happens to also be an SCEVAddRecExpr (in an outer
loop).
There are a couple more loops that are vectorized in SPEC after this.
My guess is that the main reason we don't see more because for example a
loop-invariant load is vectorized into a splat vector with several
vector-inserts. This is likely to make the vectorization unprofitable.
I.e. we don't notice that a later LICM will move all of this out of the
loop so the cost estimate should really be 0.
llvm-svn: 264243
Diffstat (limited to 'llvm/lib/Analysis/LoopAccessAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/LoopAccessAnalysis.cpp | 48 |
1 files changed, 31 insertions, 17 deletions
diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp index 04a4b1fa5a3..e3d0d25411b 100644 --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -130,26 +130,35 @@ void RuntimePointerChecking::insert(Loop *Lp, Value *Ptr, bool WritePtr, PredicatedScalarEvolution &PSE) { // Get the stride replaced scev. const SCEV *Sc = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); - const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc); - assert(AR && "Invalid addrec expression"); ScalarEvolution *SE = PSE.getSE(); - const SCEV *Ex = SE->getBackedgeTakenCount(Lp); - const SCEV *ScStart = AR->getStart(); - const SCEV *ScEnd = AR->evaluateAtIteration(Ex, *SE); - const SCEV *Step = AR->getStepRecurrence(*SE); + const SCEV *ScStart; + const SCEV *ScEnd; - // For expressions with negative step, the upper bound is ScStart and the - // lower bound is ScEnd. - if (const SCEVConstant *CStep = dyn_cast<const SCEVConstant>(Step)) { - if (CStep->getValue()->isNegative()) - std::swap(ScStart, ScEnd); - } else { - // Fallback case: the step is not constant, but the we can still - // get the upper and lower bounds of the interval by using min/max - // expressions. - ScStart = SE->getUMinExpr(ScStart, ScEnd); - ScEnd = SE->getUMaxExpr(AR->getStart(), ScEnd); + if (SE->isLoopInvariant(Sc, Lp)) { + ScStart = ScEnd = Sc; + } + else { + const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(Sc); + assert(AR && "Invalid addrec expression"); + const SCEV *Ex = SE->getBackedgeTakenCount(Lp); + + ScStart = AR->getStart(); + ScEnd = AR->evaluateAtIteration(Ex, *SE); + const SCEV *Step = AR->getStepRecurrence(*SE); + + // For expressions with negative step, the upper bound is ScStart and the + // lower bound is ScEnd. + if (const SCEVConstant *CStep = dyn_cast<const SCEVConstant>(Step)) { + if (CStep->getValue()->isNegative()) + std::swap(ScStart, ScEnd); + } else { + // Fallback case: the step is not constant, but the we can still + // get the upper and lower bounds of the interval by using min/max + // expressions. + ScStart = SE->getUMinExpr(ScStart, ScEnd); + ScEnd = SE->getUMaxExpr(AR->getStart(), ScEnd); + } } Pointers.emplace_back(Ptr, ScStart, ScEnd, WritePtr, DepSetId, ASId, Sc); @@ -524,6 +533,11 @@ static bool hasComputableBounds(PredicatedScalarEvolution &PSE, const ValueToValueMap &Strides, Value *Ptr, Loop *L) { const SCEV *PtrScev = replaceSymbolicStrideSCEV(PSE, Strides, Ptr); + + // The bounds for loop-invariant pointer is trivial. + if (PSE.getSE()->isLoopInvariant(PtrScev, L)) + return true; + const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(PtrScev); if (!AR) return false; |