delinearize together all accesses to the same array
llvm-svn: 208457
This commit is contained in:
parent
47fe7de1b5
commit
46e1ecdecc
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue