forked from OSchip/llvm-project
ScopInfo: Split hasAffineMemoryAccesses() into multiple functions [NFC]
This makes the overall code more readable. llvm-svn: 253951
This commit is contained in:
parent
919ce23566
commit
d68ba42556
|
@ -222,6 +222,50 @@ private:
|
|||
/// @returns True if the subregion can be over approximated, false otherwise.
|
||||
bool addOverApproximatedRegion(Region *AR, DetectionContext &Context) const;
|
||||
|
||||
/// @brief Find for a given base pointer terms that hint towards dimension
|
||||
/// sizes of a multi-dimensional array.
|
||||
///
|
||||
/// @param Context The current detection context.
|
||||
/// @param BasePointer A base pointer indicating the virtual array we are
|
||||
/// interested in.
|
||||
SmallVector<const SCEV *, 4>
|
||||
getDelinearizationTerms(DetectionContext &Context,
|
||||
const SCEVUnknown *BasePointer) const;
|
||||
|
||||
/// @brief Check if the dimension size of a delinearized array is valid.
|
||||
///
|
||||
/// @param Context The current detection context.
|
||||
/// @param Sizes The sizes of the different array dimensions.
|
||||
/// @param BasePointer The base pointer we are interested in.
|
||||
/// @returns True if one or more array sizes could be derived - meaning: we
|
||||
/// see this array as multi-dimensional.
|
||||
bool hasValidArraySizes(DetectionContext &Context,
|
||||
SmallVectorImpl<const SCEV *> &Sizes,
|
||||
const SCEVUnknown *BasePointer) const;
|
||||
|
||||
/// @brief Derive access functions for a given base pointer.
|
||||
///
|
||||
/// @param Context The current detection context.
|
||||
/// @param Sizes The sizes of the different array dimensions.
|
||||
/// @param BasePointer The base pointer of all the array for which to compute
|
||||
/// access functions.
|
||||
/// @param Shape The shape that describes the derived array sizes and
|
||||
/// which should be filled with newly computed access
|
||||
/// functions.
|
||||
/// @returns True if a set of affine access functions could be derived.
|
||||
bool computeAccessFunctions(DetectionContext &Context,
|
||||
const SCEVUnknown *BasePointer,
|
||||
std::shared_ptr<ArrayShape> Shape) const;
|
||||
|
||||
/// @brief Check if all accesses to a given BasePointer are affine.
|
||||
///
|
||||
/// @param Context The current detection context.
|
||||
/// @param basepointer the base pointer we are interested in.
|
||||
/// @param True if consistent (multi-dimensional) array accesses could be
|
||||
/// derived for this array.
|
||||
bool hasBaseAffineAccesses(DetectionContext &Context,
|
||||
const SCEVUnknown *BasePointer) const;
|
||||
|
||||
// Delinearize all non affine memory accesses and return false when there
|
||||
// exists a non affine memory access that cannot be delinearized. Return true
|
||||
// when all array accesses are affine after delinearization.
|
||||
|
|
|
@ -487,15 +487,9 @@ bool ScopDetection::isInvariant(const Value &Val, const Region &Reg) const {
|
|||
|
||||
MapInsnToMemAcc InsnToMemAcc;
|
||||
|
||||
bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
||||
Region &CurRegion = Context.CurRegion;
|
||||
|
||||
for (const SCEVUnknown *BasePointer : Context.NonAffineAccesses) {
|
||||
Value *BaseValue = BasePointer->getValue();
|
||||
auto Shape = std::shared_ptr<ArrayShape>(new ArrayShape(BasePointer));
|
||||
bool BasePtrHasNonAffine = false;
|
||||
|
||||
// First step: collect parametric terms in all array references.
|
||||
SmallVector<const SCEV *, 4>
|
||||
ScopDetection::getDelinearizationTerms(DetectionContext &Context,
|
||||
const SCEVUnknown *BasePointer) const {
|
||||
SmallVector<const SCEV *, 4> Terms;
|
||||
for (const auto &Pair : Context.Accesses[BasePointer]) {
|
||||
// In case the outermost expression is a plain add, we check if any of its
|
||||
|
@ -534,14 +528,17 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
|||
if (Terms.empty())
|
||||
SE->collectParametricTerms(Pair.second, Terms);
|
||||
}
|
||||
return Terms;
|
||||
}
|
||||
|
||||
// Second step: find array shape.
|
||||
SE->findArrayDimensions(Terms, Shape->DelinearizedSizes,
|
||||
Context.ElementSize[BasePointer]);
|
||||
|
||||
for (const SCEV *DelinearizedSize : Shape->DelinearizedSizes) {
|
||||
bool ScopDetection::hasValidArraySizes(DetectionContext &Context,
|
||||
SmallVectorImpl<const SCEV *> &Sizes,
|
||||
const SCEVUnknown *BasePointer) const {
|
||||
Value *BaseValue = BasePointer->getValue();
|
||||
Region &CurRegion = Context.CurRegion;
|
||||
for (const SCEV *DelinearizedSize : Sizes) {
|
||||
if (!isAffine(DelinearizedSize, Context, nullptr)) {
|
||||
Shape->DelinearizedSizes.clear();
|
||||
Sizes.clear();
|
||||
break;
|
||||
}
|
||||
if (auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
|
||||
|
@ -560,9 +557,9 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
|||
}
|
||||
|
||||
// No array shape derived.
|
||||
if (Shape->DelinearizedSizes.empty()) {
|
||||
if (Sizes.empty()) {
|
||||
if (AllowNonAffine)
|
||||
continue;
|
||||
return true;
|
||||
|
||||
for (const auto &Pair : Context.Accesses[BasePointer]) {
|
||||
const Instruction *Insn = Pair.first;
|
||||
|
@ -575,17 +572,22 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Third step: compute the access functions for each subscript.
|
||||
//
|
||||
// We first store the resulting memory accesses in TempMemoryAccesses. Only
|
||||
// if the access functions for all memory accesses have been successfully
|
||||
// delinearized we continue. Otherwise, we either report a failure or, if
|
||||
// non-affine accesses are allowed, we drop the information. In case the
|
||||
// information is dropped the memory accesses need to be overapproximated
|
||||
// when translated to a polyhedral representation.
|
||||
// We first store the resulting memory accesses in TempMemoryAccesses. Only
|
||||
// if the access functions for all memory accesses have been successfully
|
||||
// delinearized we continue. Otherwise, we either report a failure or, if
|
||||
// non-affine accesses are allowed, we drop the information. In case the
|
||||
// information is dropped the memory accesses need to be overapproximated
|
||||
// when translated to a polyhedral representation.
|
||||
bool ScopDetection::computeAccessFunctions(
|
||||
DetectionContext &Context, const SCEVUnknown *BasePointer,
|
||||
std::shared_ptr<ArrayShape> Shape) const {
|
||||
Value *BaseValue = BasePointer->getValue();
|
||||
bool BasePtrHasNonAffine = false;
|
||||
MapInsnToMemAcc TempMemoryAccesses;
|
||||
for (const auto &Pair : Context.Accesses[BasePointer]) {
|
||||
const Instruction *Insn = Pair.first;
|
||||
|
@ -622,6 +624,32 @@ bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
|||
|
||||
if (!BasePtrHasNonAffine)
|
||||
InsnToMemAcc.insert(TempMemoryAccesses.begin(), TempMemoryAccesses.end());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScopDetection::hasBaseAffineAccesses(
|
||||
DetectionContext &Context, const SCEVUnknown *BasePointer) const {
|
||||
auto Shape = std::shared_ptr<ArrayShape>(new ArrayShape(BasePointer));
|
||||
|
||||
auto Terms = getDelinearizationTerms(Context, BasePointer);
|
||||
|
||||
SE->findArrayDimensions(Terms, Shape->DelinearizedSizes,
|
||||
Context.ElementSize[BasePointer]);
|
||||
|
||||
if (!hasValidArraySizes(Context, Shape->DelinearizedSizes, BasePointer))
|
||||
return false;
|
||||
|
||||
return computeAccessFunctions(Context, BasePointer, Shape);
|
||||
}
|
||||
|
||||
bool ScopDetection::hasAffineMemoryAccesses(DetectionContext &Context) const {
|
||||
for (const SCEVUnknown *BasePointer : Context.NonAffineAccesses)
|
||||
if (!hasBaseAffineAccesses(Context, BasePointer)) {
|
||||
if (KeepGoing)
|
||||
continue;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue