diff options
author | Sebastian Pop <sebpop@gmail.com> | 2018-03-06 21:55:59 +0000 |
---|---|---|
committer | Sebastian Pop <sebpop@gmail.com> | 2018-03-06 21:55:59 +0000 |
commit | bf6e1c26cf185445d2150580106afee9f7131907 (patch) | |
tree | 7041db09f530711d309b5906ddbeb14421d19fe6 /llvm/lib/Analysis/DependenceAnalysis.cpp | |
parent | 4289f4cecf673808f870f66074bfc7a24eb5f580 (diff) | |
download | bcm5719-llvm-bf6e1c26cf185445d2150580106afee9f7131907.tar.gz bcm5719-llvm-bf6e1c26cf185445d2150580106afee9f7131907.zip |
DA: remove uses of GEP, only ask SCEV
It's been quite some time the Dependence Analysis (DA) is broken,
as it uses the GEP representation to "identify" multi-dimensional arrays.
It even wrongly detects multi-dimensional arrays in single nested loops:
from test/Analysis/DependenceAnalysis/Coupled.ll, example @couple6
;; for (long int i = 0; i < 50; i++) {
;; A[i][3*i - 6] = i;
;; *B++ = A[i][i];
DA used to detect two subscripts, which makes no sense in the LLVM IR
or in C/C++ semantics, as there are no guarantees as in Fortran of
subscripts not overlapping into a next array dimension:
maximum nesting levels = 1
SrcPtrSCEV = %A
DstPtrSCEV = %A
using GEPs
subscript 0
src = {0,+,1}<nuw><nsw><%for.body>
dst = {0,+,1}<nuw><nsw><%for.body>
class = 1
loops = {1}
subscript 1
src = {-6,+,3}<nsw><%for.body>
dst = {0,+,1}<nuw><nsw><%for.body>
class = 1
loops = {1}
Separable = {}
Coupled = {1}
With the current patch, DA will correctly work on only one dimension:
maximum nesting levels = 1
SrcSCEV = {(-2424 + %A)<nsw>,+,1212}<%for.body>
DstSCEV = {%A,+,404}<%for.body>
subscript 0
src = {(-2424 + %A)<nsw>,+,1212}<%for.body>
dst = {%A,+,404}<%for.body>
class = 1
loops = {1}
Separable = {0}
Coupled = {}
This change removes all uses of GEP from DA, and we now only rely
on the SCEV representation.
The patch does not turn on -da-delinearize by default, and so the DA analysis
will be more conservative in the case of multi-dimensional memory accesses in
nested loops.
I disabled some interchange tests, as the DA is not able to disambiguate
the dependence anymore. To make DA stronger, we may need to
compute a bound on the number of iterations based on the access functions
and array dimensions.
The patch cleans up all the CHECKs in test/Transforms/LoopInterchange/*.ll to
avoid checking for snippets of LLVM IR: this form of checking is very hard to
maintain. Instead, we now check for output of the pass that are more meaningful
than dozens of lines of LLVM IR. Some tests now require -debug messages and thus
only enabled with asserts.
Patch written by Sebastian Pop and Aditya Kumar.
Differential Revision: https://reviews.llvm.org/D35430
llvm-svn: 326837
Diffstat (limited to 'llvm/lib/Analysis/DependenceAnalysis.cpp')
-rw-r--r-- | llvm/lib/Analysis/DependenceAnalysis.cpp | 96 |
1 files changed, 19 insertions, 77 deletions
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp index 34eccc07f26..0d89bbd4eba 100644 --- a/llvm/lib/Analysis/DependenceAnalysis.cpp +++ b/llvm/lib/Analysis/DependenceAnalysis.cpp @@ -24,8 +24,7 @@ // Both of these are conservative weaknesses; // that is, not a source of correctness problems. // -// The implementation depends on the GEP instruction to differentiate -// subscripts. Since Clang linearizes some array subscripts, the dependence +// Since Clang linearizes some array subscripts, the dependence // analysis is using SCEV->delinearize to recover the representation of multiple // subscripts, and thus avoid the more expensive and less precise MIV tests. The // delinearization is controlled by the flag -da-delinearize. @@ -3329,50 +3328,18 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst, FullDependence Result(Src, Dst, PossiblyLoopIndependent, CommonLevels); ++TotalArrayPairs; - // See if there are GEPs we can use. - bool UsefulGEP = false; - GEPOperator *SrcGEP = dyn_cast<GEPOperator>(SrcPtr); - GEPOperator *DstGEP = dyn_cast<GEPOperator>(DstPtr); - if (SrcGEP && DstGEP && - SrcGEP->getPointerOperandType() == DstGEP->getPointerOperandType()) { - const SCEV *SrcPtrSCEV = SE->getSCEV(SrcGEP->getPointerOperand()); - const SCEV *DstPtrSCEV = SE->getSCEV(DstGEP->getPointerOperand()); - DEBUG(dbgs() << " SrcPtrSCEV = " << *SrcPtrSCEV << "\n"); - DEBUG(dbgs() << " DstPtrSCEV = " << *DstPtrSCEV << "\n"); - - UsefulGEP = isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) && - isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent())) && - (SrcGEP->getNumOperands() == DstGEP->getNumOperands()) && - isKnownPredicate(CmpInst::ICMP_EQ, SrcPtrSCEV, DstPtrSCEV); - } - unsigned Pairs = UsefulGEP ? SrcGEP->idx_end() - SrcGEP->idx_begin() : 1; - SmallVector<Subscript, 4> Pair(Pairs); - if (UsefulGEP) { - DEBUG(dbgs() << " using GEPs\n"); - unsigned P = 0; - for (GEPOperator::const_op_iterator SrcIdx = SrcGEP->idx_begin(), - SrcEnd = SrcGEP->idx_end(), - DstIdx = DstGEP->idx_begin(); - SrcIdx != SrcEnd; - ++SrcIdx, ++DstIdx, ++P) { - Pair[P].Src = SE->getSCEV(*SrcIdx); - Pair[P].Dst = SE->getSCEV(*DstIdx); - unifySubscriptType(&Pair[P]); - } - } - else { - DEBUG(dbgs() << " ignoring GEPs\n"); - const SCEV *SrcSCEV = SE->getSCEV(SrcPtr); - const SCEV *DstSCEV = SE->getSCEV(DstPtr); - DEBUG(dbgs() << " SrcSCEV = " << *SrcSCEV << "\n"); - DEBUG(dbgs() << " DstSCEV = " << *DstSCEV << "\n"); - Pair[0].Src = SrcSCEV; - Pair[0].Dst = DstSCEV; - } + unsigned Pairs = 1; + SmallVector<Subscript, 2> Pair(Pairs); + const SCEV *SrcSCEV = SE->getSCEV(SrcPtr); + const SCEV *DstSCEV = SE->getSCEV(DstPtr); + DEBUG(dbgs() << " SrcSCEV = " << *SrcSCEV << "\n"); + DEBUG(dbgs() << " DstSCEV = " << *DstSCEV << "\n"); + Pair[0].Src = SrcSCEV; + Pair[0].Dst = DstSCEV; - if (Delinearize && CommonLevels > 1) { + if (Delinearize) { if (tryDelinearize(Src, Dst, Pair)) { - DEBUG(dbgs() << " delinearized GEP\n"); + DEBUG(dbgs() << " delinearized\n"); Pairs = Pair.size(); } } @@ -3763,41 +3730,16 @@ const SCEV *DependenceInfo::getSplitIteration(const Dependence &Dep, FullDependence Result(Src, Dst, false, CommonLevels); - // See if there are GEPs we can use. - bool UsefulGEP = false; - GEPOperator *SrcGEP = dyn_cast<GEPOperator>(SrcPtr); - GEPOperator *DstGEP = dyn_cast<GEPOperator>(DstPtr); - if (SrcGEP && DstGEP && - SrcGEP->getPointerOperandType() == DstGEP->getPointerOperandType()) { - const SCEV *SrcPtrSCEV = SE->getSCEV(SrcGEP->getPointerOperand()); - const SCEV *DstPtrSCEV = SE->getSCEV(DstGEP->getPointerOperand()); - UsefulGEP = isLoopInvariant(SrcPtrSCEV, LI->getLoopFor(Src->getParent())) && - isLoopInvariant(DstPtrSCEV, LI->getLoopFor(Dst->getParent())) && - (SrcGEP->getNumOperands() == DstGEP->getNumOperands()); - } - unsigned Pairs = UsefulGEP ? SrcGEP->idx_end() - SrcGEP->idx_begin() : 1; - SmallVector<Subscript, 4> Pair(Pairs); - if (UsefulGEP) { - unsigned P = 0; - for (GEPOperator::const_op_iterator SrcIdx = SrcGEP->idx_begin(), - SrcEnd = SrcGEP->idx_end(), - DstIdx = DstGEP->idx_begin(); - SrcIdx != SrcEnd; - ++SrcIdx, ++DstIdx, ++P) { - Pair[P].Src = SE->getSCEV(*SrcIdx); - Pair[P].Dst = SE->getSCEV(*DstIdx); - } - } - else { - const SCEV *SrcSCEV = SE->getSCEV(SrcPtr); - const SCEV *DstSCEV = SE->getSCEV(DstPtr); - Pair[0].Src = SrcSCEV; - Pair[0].Dst = DstSCEV; - } + unsigned Pairs = 1; + SmallVector<Subscript, 2> Pair(Pairs); + const SCEV *SrcSCEV = SE->getSCEV(SrcPtr); + const SCEV *DstSCEV = SE->getSCEV(DstPtr); + Pair[0].Src = SrcSCEV; + Pair[0].Dst = DstSCEV; - if (Delinearize && CommonLevels > 1) { + if (Delinearize) { if (tryDelinearize(Src, Dst, Pair)) { - DEBUG(dbgs() << " delinearized GEP\n"); + DEBUG(dbgs() << " delinearized\n"); Pairs = Pair.size(); } } |