delinearize together all accesses to the same array

llvm-svn: 208457
This commit is contained in:
Sebastian Pop 2014-05-09 22:45:15 +00:00
parent 47fe7de1b5
commit 46e1ecdecc
2 changed files with 52 additions and 11 deletions

View File

@ -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);

View File

@ -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;
}