[polly] r208457 - delinearize together all accesses to the same array

Sebastian Pop spop at codeaurora.org
Fri May 9 15:45:16 PDT 2014


Author: spop
Date: Fri May  9 17:45:15 2014
New Revision: 208457

URL: http://llvm.org/viewvc/llvm-project?rev=208457&view=rev
Log:
delinearize together all accesses to the same array

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=208457&r1=208456&r2=208457&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopDetection.h (original)
+++ polly/trunk/include/polly/ScopDetection.h Fri May  9 17:45:15 2014
@@ -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 FunctionPas
     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 FunctionPas
   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);

Modified: polly/trunk/lib/Analysis/ScopDetection.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopDetection.cpp?rev=208457&r1=208456&r2=208457&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopDetection.cpp (original)
+++ polly/trunk/lib/Analysis/ScopDetection.cpp Fri May  9 17:45:15 2014
@@ -337,6 +337,35 @@ bool ScopDetection::isInvariant(const Va
   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(
   } 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(Detec
       if (!isValidInstruction(*I, Context))
         return false;
 
+  if (hasNonAffineMemoryAccesses(Context))
+    return false;
+
   return true;
 }
 





More information about the llvm-commits mailing list