[polly] r253951 - ScopInfo: Split hasAffineMemoryAccesses() into multiple functions [NFC]
Tobias Grosser via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 23 21:00:36 PST 2015
Author: grosser
Date: Mon Nov 23 23:00:36 2015
New Revision: 253951
URL: http://llvm.org/viewvc/llvm-project?rev=253951&view=rev
Log:
ScopInfo: Split hasAffineMemoryAccesses() into multiple functions [NFC]
This makes the overall code more readable.
Modified:
polly/trunk/include/polly/ScopDetection.h
polly/trunk/lib/Analysis/ScopDetection.cpp
Modified: polly/trunk/include/polly/ScopDetection.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopDetection.h?rev=253951&r1=253950&r2=253951&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetection.h (original)
+++ polly/trunk/include/polly/ScopDetection.h Mon Nov 23 23:00:36 2015
@@ -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.
Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=253951&r1=253950&r2=253951&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Mon Nov 23 23:00:36 2015
@@ -487,142 +487,170 @@ bool ScopDetection::isInvariant(const Va
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> Terms;
- for (const auto &Pair : Context.Accesses[BasePointer]) {
- // In case the outermost expression is a plain add, we check if any of its
- // terms has the form 4 * %inst * %param * %param ..., aka a term that
- // contains a product between a parameter and an instruction that is
- // inside the scop. Such instructions, if allowed at all, are instructions
- // SCEV can not represent, but Polly is still looking through. As a
- // result, these instructions can depend on induction variables and are
- // most likely no array sizes. However, terms that are multiplied with
- // them are likely candidates for array sizes.
- if (auto *AF = dyn_cast<SCEVAddExpr>(Pair.second)) {
- for (auto Op : AF->operands()) {
- if (auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
- SE->collectParametricTerms(AF2, Terms);
- if (auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
- SmallVector<const SCEV *, 0> Operands;
-
- for (auto *MulOp : AF2->operands()) {
- if (auto *Const = dyn_cast<SCEVConstant>(MulOp))
- Operands.push_back(Const);
- if (auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
- if (auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
- if (!Context.CurRegion.contains(Inst))
- Operands.push_back(MulOp);
-
- } else {
+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
+ // terms has the form 4 * %inst * %param * %param ..., aka a term that
+ // contains a product between a parameter and an instruction that is
+ // inside the scop. Such instructions, if allowed at all, are instructions
+ // SCEV can not represent, but Polly is still looking through. As a
+ // result, these instructions can depend on induction variables and are
+ // most likely no array sizes. However, terms that are multiplied with
+ // them are likely candidates for array sizes.
+ if (auto *AF = dyn_cast<SCEVAddExpr>(Pair.second)) {
+ for (auto Op : AF->operands()) {
+ if (auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
+ SE->collectParametricTerms(AF2, Terms);
+ if (auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
+ SmallVector<const SCEV *, 0> Operands;
+
+ for (auto *MulOp : AF2->operands()) {
+ if (auto *Const = dyn_cast<SCEVConstant>(MulOp))
+ Operands.push_back(Const);
+ if (auto *Unknown = dyn_cast<SCEVUnknown>(MulOp)) {
+ if (auto *Inst = dyn_cast<Instruction>(Unknown->getValue())) {
+ if (!Context.CurRegion.contains(Inst))
Operands.push_back(MulOp);
- }
+
+ } else {
+ Operands.push_back(MulOp);
}
}
- if (Operands.size())
- Terms.push_back(SE->getMulExpr(Operands));
}
+ if (Operands.size())
+ Terms.push_back(SE->getMulExpr(Operands));
}
}
- if (Terms.empty())
- SE->collectParametricTerms(Pair.second, Terms);
}
+ 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) {
- if (!isAffine(DelinearizedSize, Context, nullptr)) {
- Shape->DelinearizedSizes.clear();
- break;
- }
- if (auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
- auto *V = dyn_cast<Value>(Unknown->getValue());
- if (auto *Load = dyn_cast<LoadInst>(V)) {
- if (Context.CurRegion.contains(Load) &&
- isHoistableLoad(Load, CurRegion, *LI, *SE))
- Context.RequiredILS.insert(Load);
- continue;
- }
- }
- if (hasScalarDepsInsideRegion(DelinearizedSize, &CurRegion))
- invalid<ReportNonAffineAccess>(
- Context, /*Assert=*/true, DelinearizedSize,
- Context.Accesses[BasePointer].front().first, BaseValue);
+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)) {
+ Sizes.clear();
+ break;
}
-
- // No array shape derived.
- if (Shape->DelinearizedSizes.empty()) {
- if (AllowNonAffine)
+ if (auto *Unknown = dyn_cast<SCEVUnknown>(DelinearizedSize)) {
+ auto *V = dyn_cast<Value>(Unknown->getValue());
+ if (auto *Load = dyn_cast<LoadInst>(V)) {
+ if (Context.CurRegion.contains(Load) &&
+ isHoistableLoad(Load, CurRegion, *LI, *SE))
+ Context.RequiredILS.insert(Load);
continue;
-
- for (const auto &Pair : Context.Accesses[BasePointer]) {
- const Instruction *Insn = Pair.first;
- const SCEV *AF = Pair.second;
-
- if (!isAffine(AF, Context, BaseValue)) {
- invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF, Insn,
- BaseValue);
- if (!KeepGoing)
- return false;
- }
}
- continue;
}
+ if (hasScalarDepsInsideRegion(DelinearizedSize, &CurRegion))
+ invalid<ReportNonAffineAccess>(
+ Context, /*Assert=*/true, DelinearizedSize,
+ Context.Accesses[BasePointer].front().first, BaseValue);
+ }
+
+ // No array shape derived.
+ if (Sizes.empty()) {
+ if (AllowNonAffine)
+ 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.
- MapInsnToMemAcc TempMemoryAccesses;
for (const auto &Pair : Context.Accesses[BasePointer]) {
const Instruction *Insn = Pair.first;
- auto *AF = Pair.second;
- bool IsNonAffine = false;
- TempMemoryAccesses.insert(std::make_pair(Insn, MemAcc(Insn, Shape)));
- MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
-
- if (!AF) {
- if (isAffine(Pair.second, Context, BaseValue))
- Acc->DelinearizedSubscripts.push_back(Pair.second);
- else
- IsNonAffine = true;
- } else {
- SE->computeAccessFunctions(AF, Acc->DelinearizedSubscripts,
- Shape->DelinearizedSizes);
- if (Acc->DelinearizedSubscripts.size() == 0)
- IsNonAffine = true;
- for (const SCEV *S : Acc->DelinearizedSubscripts)
- if (!isAffine(S, Context, BaseValue))
- IsNonAffine = true;
- }
+ const SCEV *AF = Pair.second;
- // (Possibly) report non affine access
- if (IsNonAffine) {
- BasePtrHasNonAffine = true;
- if (!AllowNonAffine)
- invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, Pair.second,
- Insn, BaseValue);
- if (!KeepGoing && !AllowNonAffine)
+ if (!isAffine(AF, Context, BaseValue)) {
+ invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF, Insn,
+ BaseValue);
+ if (!KeepGoing)
return false;
}
}
+ return false;
+ }
+ return true;
+}
+
+// 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;
+ auto *AF = Pair.second;
+ bool IsNonAffine = false;
+ TempMemoryAccesses.insert(std::make_pair(Insn, MemAcc(Insn, Shape)));
+ MemAcc *Acc = &TempMemoryAccesses.find(Insn)->second;
+
+ if (!AF) {
+ if (isAffine(Pair.second, Context, BaseValue))
+ Acc->DelinearizedSubscripts.push_back(Pair.second);
+ else
+ IsNonAffine = true;
+ } else {
+ SE->computeAccessFunctions(AF, Acc->DelinearizedSubscripts,
+ Shape->DelinearizedSizes);
+ if (Acc->DelinearizedSubscripts.size() == 0)
+ IsNonAffine = true;
+ for (const SCEV *S : Acc->DelinearizedSubscripts)
+ if (!isAffine(S, Context, BaseValue))
+ IsNonAffine = true;
+ }
- if (!BasePtrHasNonAffine)
- InsnToMemAcc.insert(TempMemoryAccesses.begin(), TempMemoryAccesses.end());
+ // (Possibly) report non affine access
+ if (IsNonAffine) {
+ BasePtrHasNonAffine = true;
+ if (!AllowNonAffine)
+ invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, Pair.second,
+ Insn, BaseValue);
+ if (!KeepGoing && !AllowNonAffine)
+ return false;
+ }
}
+
+ 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;
}
More information about the llvm-commits
mailing list