diff options
author | Sebastian Pop <spop@codeaurora.org> | 2014-05-09 22:45:15 +0000 |
---|---|---|
committer | Sebastian Pop <spop@codeaurora.org> | 2014-05-09 22:45:15 +0000 |
commit | 46e1ecdecc9b6e6809fd85d9a2f7ae707e1aadd0 (patch) | |
tree | bf4cdd0b1402d3077f587fe8e84d33a32614ead9 | |
parent | 47fe7de1b517161d1c162ead1ec6e1143dd99372 (diff) | |
download | bcm5719-llvm-46e1ecdecc9b6e6809fd85d9a2f7ae707e1aadd0.tar.gz bcm5719-llvm-46e1ecdecc9b6e6809fd85d9a2f7ae707e1aadd0.zip |
delinearize together all accesses to the same array
llvm-svn: 208457
-rw-r--r-- | polly/include/polly/ScopDetection.h | 13 | ||||
-rw-r--r-- | polly/lib/Analysis/ScopDetection.cpp | 50 |
2 files changed, 52 insertions, 11 deletions
diff --git a/polly/include/polly/ScopDetection.h b/polly/include/polly/ScopDetection.h index 452eb09e49b..a5a93a4a966 100644 --- a/polly/include/polly/ScopDetection.h +++ b/polly/include/polly/ScopDetection.h @@ -63,6 +63,7 @@ class Loop; class ScalarEvolution; class SCEV; class SCEVAddRecExpr; +class SCEVUnknown; class CallInst; class Instruction; class AliasAnalysis; @@ -72,6 +73,9 @@ class Value; namespace polly { typedef std::set<const SCEV *> ParamSetType; +typedef std::vector<const SCEVAddRecExpr *> AFs; +typedef std::map<const SCEVUnknown *, AFs> BaseToAFs; + extern bool PollyTrackFailures; extern bool PollyDelinearize; @@ -96,6 +100,10 @@ class ScopDetection : public FunctionPass { Region &CurRegion; // The region to check. AliasSetTracker AST; // The AliasSetTracker to hold the alias information. bool Verifying; // If we are in the verification phase? + + // Map a base pointer to all access functions accessing it. + BaseToAFs NonAffineAccesses; + DetectionContext(Region &R, AliasAnalysis &AA, bool Verify) : CurRegion(R), AST(AA), Verifying(Verify) {} }; @@ -112,6 +120,11 @@ class ScopDetection : public FunctionPass { FunctionSet InvalidFunctions; mutable std::string LastFailure; + // Delinearize all non affine memory accesses and return true when there + // exists a non affine memory access that cannot be delinearized. Return + // false when all array accesses are affine after delinearization. + bool hasNonAffineMemoryAccesses(DetectionContext &Context) const; + // Try to expand the region R. If R can be expanded return the expanded // region, NULL otherwise. Region *expandRegion(Region &R); diff --git a/polly/lib/Analysis/ScopDetection.cpp b/polly/lib/Analysis/ScopDetection.cpp index 62b9c2a24d0..c512463ce95 100644 --- a/polly/lib/Analysis/ScopDetection.cpp +++ b/polly/lib/Analysis/ScopDetection.cpp @@ -337,6 +337,35 @@ bool ScopDetection::isInvariant(const Value &Val, const Region &Reg) const { return true; } +bool +ScopDetection::hasNonAffineMemoryAccesses(DetectionContext &Context) const { + for (auto P : Context.NonAffineAccesses) { + const SCEVUnknown *BasePointer = P.first; + Value *BaseValue = BasePointer->getValue(); + + // First step: collect parametric terms in all array references. + SmallVector<const SCEV *, 4> Terms; + for (const SCEVAddRecExpr *AF : Context.NonAffineAccesses[BasePointer]) + AF->collectParametricTerms(*SE, Terms); + + // Second step: find array shape. + SmallVector<const SCEV *, 4> Sizes; + SE->findArrayDimensions(Terms, Sizes); + + // Third step: compute the access functions for each subscript. + for (const SCEVAddRecExpr *AF : Context.NonAffineAccesses[BasePointer]) { + SmallVector<const SCEV *, 4> Subscripts; + AF->computeAccessFunctions(*SE, Subscripts, Sizes); + + // Check that the delinearized subscripts are affine. + for (const SCEV *S : Subscripts) + if (!isAffineExpr(&Context.CurRegion, S, *SE, BaseValue)) + return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF); + } + } + return false; +} + bool ScopDetection::isValidMemoryAccess(Instruction &Inst, DetectionContext &Context) const { Value *Ptr = getPointerOperand(Inst); @@ -370,21 +399,17 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst, } else if (!isAffineExpr(&Context.CurRegion, AccessFunction, *SE, BaseValue)) { const SCEVAddRecExpr *AF = dyn_cast<SCEVAddRecExpr>(AccessFunction); + if (!PollyDelinearize || !AF) return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AccessFunction); - // Try to delinearize AccessFunction only when the expression is known to - // not be affine: as all affine functions can be represented without - // problems in Polly, we do not have to delinearize them. - SmallVector<const SCEV *, 4> Subscripts, Sizes; - AF->delinearize(*SE, Subscripts, Sizes); - int size = Subscripts.size(); - - for (int i = 0; i < size; ++i) - if (!isAffineExpr(&Context.CurRegion, Subscripts[i], *SE, BaseValue)) - return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, - AccessFunction); + // Collect all non affine memory accesses, and check whether they are linear + // at the end of scop detection. That way we can delinearize all the memory + // accesses to the same array in a unique step. + if (Context.NonAffineAccesses[BasePointer].size() == 0) + Context.NonAffineAccesses[BasePointer] = AFs(); + Context.NonAffineAccesses[BasePointer].push_back(AF); } // FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions @@ -609,6 +634,9 @@ bool ScopDetection::allBlocksValid(DetectionContext &Context) const { if (!isValidInstruction(*I, Context)) return false; + if (hasNonAffineMemoryAccesses(Context)) + return false; + return true; } |