[polly] 7154413 - [NFC][ScopBuilder] Move RecordedAssumptions vector to ScopBuilder

Dominik Adamski via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 23 15:11:33 PST 2020


Author: Dominik Adamski
Date: 2020-01-24T00:09:01+01:00
New Revision: 71544135673e5d88bd2d2878a2df75969277fab9

URL: https://github.com/llvm/llvm-project/commit/71544135673e5d88bd2d2878a2df75969277fab9
DIFF: https://github.com/llvm/llvm-project/commit/71544135673e5d88bd2d2878a2df75969277fab9.diff

LOG: [NFC][ScopBuilder] Move RecordedAssumptions vector to ScopBuilder

Scope of changes:

1) Moved RecordedAssumptions vector to ScopBuilder. RecordedAssumptions are used only for Scop constructions.
2) Moved definition of RecordedAssumptionsTy to ScopHelper. It is required both by ScopBuilder and SCEVAffinator.
3) Add new function recordAssumption to ScopHelper. One of its argument is a reference to RecordedAssumption vector. This function is used by ScopBuilder and SCEVAffinator.
4) All RecordedAssumptions are created by ScopBuilder. isl::pw_aff
objects for corresponding SCEVs are created inside ScopBuilder. Scop
functions do not record any assumptions. Scop can use isl::pw_aff
objects which were created by ScopBuilder.
5) Removed functions for handling RecordedAssumptions from Scop class.
6) Removed constness from getScopArrayInfo functions.
7) Replaced SCEVVisitor struct from SCEVAffinator with taylored version, which allow to pass pointer to RecordedAssumptions as function argument.

Differential Revision: https://reviews.llvm.org/D68056

Added: 
    

Modified: 
    polly/include/polly/ScopBuilder.h
    polly/include/polly/ScopInfo.h
    polly/include/polly/Support/SCEVAffinator.h
    polly/include/polly/Support/ScopHelper.h
    polly/lib/Analysis/ScopBuilder.cpp
    polly/lib/Analysis/ScopInfo.cpp
    polly/lib/Support/SCEVAffinator.cpp
    polly/lib/Support/ScopHelper.cpp

Removed: 
    


################################################################################
diff  --git a/polly/include/polly/ScopBuilder.h b/polly/include/polly/ScopBuilder.h
index f848378b0e1e..e1d1c7849450 100644
--- a/polly/include/polly/ScopBuilder.h
+++ b/polly/include/polly/ScopBuilder.h
@@ -61,6 +61,18 @@ class ScopBuilder {
   // The Scop
   std::unique_ptr<Scop> scop;
 
+  /// Collection to hold taken assumptions.
+  ///
+  /// There are two reasons why we want to record assumptions first before we
+  /// add them to the assumed/invalid context:
+  ///   1) If the SCoP is not profitable or otherwise invalid without the
+  ///      assumed/invalid context we do not have to compute it.
+  ///   2) Information about the context are gathered rather late in the SCoP
+  ///      construction (basically after we know all parameters), thus the user
+  ///      might see overly complicated assumptions to be taken while they will
+  ///      only be simplified later on.
+  RecordedAssumptionsTy RecordedAssumptions;
+
   // Methods for pattern matching against Fortran code generated by dragonegg.
   // @{
 

diff  --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h
index 50d4d2e4d9e0..1822265c4567 100644
--- a/polly/include/polly/ScopInfo.h
+++ b/polly/include/polly/ScopInfo.h
@@ -19,6 +19,7 @@
 
 #include "polly/ScopDetection.h"
 #include "polly/Support/SCEVAffinator.h"
+#include "polly/Support/ScopHelper.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/SetVector.h"
@@ -54,23 +55,6 @@ extern bool UseInstructionNames;
 // are also unlikely to result in good code.
 extern int const MaxDisjunctsInDomain;
 
-/// Enumeration of assumptions Polly can take.
-enum AssumptionKind {
-  ALIASING,
-  INBOUNDS,
-  WRAPPING,
-  UNSIGNED,
-  PROFITABLE,
-  ERRORBLOCK,
-  COMPLEXITY,
-  INFINITELOOP,
-  INVARIANTLOAD,
-  DELINEARIZATION,
-};
-
-/// Enum to distinguish between assumptions and restrictions.
-enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION };
-
 /// The 
diff erent memory kinds used in Polly.
 ///
 /// We distinguish between arrays and various scalar memory objects. We use
@@ -479,6 +463,8 @@ class MemoryAccess {
     RT_BAND, ///< Bitwise And
   };
 
+  using SubscriptsTy = SmallVector<const SCEV *, 4>;
+
 private:
   /// A unique identifier for this memory access.
   ///
@@ -590,7 +576,7 @@ class MemoryAccess {
   bool IsAffine = true;
 
   /// Subscript expression for each dimension.
-  SmallVector<const SCEV *, 4> Subscripts;
+  SubscriptsTy Subscripts;
 
   /// Relation from statement instances to the accessed array elements.
   ///
@@ -633,7 +619,7 @@ class MemoryAccess {
 
   isl::basic_map createBasicAccessMap(ScopStmt *Statement);
 
-  void assumeNoOutOfBound();
+  isl::set assumeNoOutOfBound();
 
   /// Compute bounds on an over approximated  access relation.
   ///
@@ -894,6 +880,11 @@ class MemoryAccess {
   /// Return the access instruction of this memory access.
   Instruction *getAccessInstruction() const { return AccessInstruction; }
 
+  ///  Return an iterator range containing the subscripts.
+  iterator_range<SubscriptsTy::const_iterator> subscripts() const {
+    return make_range(Subscripts.begin(), Subscripts.end());
+  }
+
   /// Return the number of access function subscript.
   unsigned getNumSubscripts() const { return Subscripts.size(); }
 
@@ -1624,24 +1615,6 @@ class ScopStmt {
 /// Print ScopStmt S to raw_ostream OS.
 raw_ostream &operator<<(raw_ostream &OS, const ScopStmt &S);
 
-/// Helper struct to remember assumptions.
-struct Assumption {
-  /// The kind of the assumption (e.g., WRAPPING).
-  AssumptionKind Kind;
-
-  /// Flag to distinguish assumptions and restrictions.
-  AssumptionSign Sign;
-
-  /// The valid/invalid context if this is an assumption/restriction.
-  isl::set Set;
-
-  /// The location that caused this assumption.
-  DebugLoc Loc;
-
-  /// An optional block whose domain can simplify the assumption.
-  BasicBlock *BB;
-};
-
 /// Build the conditions sets for the branch condition @p Condition in
 /// the @p Domain.
 ///
@@ -1838,19 +1811,6 @@ class Scop {
   /// need to be "false". Otherwise they behave the same.
   isl::set InvalidContext;
 
-  using RecordedAssumptionsTy = SmallVector<Assumption, 8>;
-  /// Collection to hold taken assumptions.
-  ///
-  /// There are two reasons why we want to record assumptions first before we
-  /// add them to the assumed/invalid context:
-  ///   1) If the SCoP is not profitable or otherwise invalid without the
-  ///      assumed/invalid context we do not have to compute it.
-  ///   2) Information about the context are gathered rather late in the SCoP
-  ///      construction (basically after we know all parameters), thus the user
-  ///      might see overly complicated assumptions to be taken while they will
-  ///      only be simplified later on.
-  RecordedAssumptionsTy RecordedAssumptions;
-
   /// The schedule of the SCoP
   ///
   /// The schedule of the SCoP describes the execution order of the statements
@@ -2129,12 +2089,6 @@ class Scop {
                       InvariantEquivClasses.end());
   }
 
-  /// Return an iterator range containing hold assumptions.
-  iterator_range<RecordedAssumptionsTy::const_iterator>
-  recorded_assumptions() const {
-    return make_range(RecordedAssumptions.begin(), RecordedAssumptions.end());
-  }
-
   /// Return an iterator range containing all the MemoryAccess objects of the
   /// Scop.
   iterator_range<AccFuncVector::iterator> access_functions() {
@@ -2297,9 +2251,6 @@ class Scop {
   /// @returns True if the optimized SCoP can be executed.
   bool hasFeasibleRuntimeContext() const;
 
-  /// Clear assumptions which have been already processed.
-  void clearRecordedAssumptions() { return RecordedAssumptions.clear(); }
-
   /// Check if the assumption in @p Set is trivial or not.
   ///
   /// @param Set  The relations between parameters that are assumed to hold.
@@ -2347,24 +2298,6 @@ class Scop {
   void addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
                      AssumptionSign Sign, BasicBlock *BB);
 
-  /// Record an assumption for later addition to the assumed context.
-  ///
-  /// This function will add the assumption to the RecordedAssumptions. This
-  /// collection will be added (@see addAssumption) to the assumed context once
-  /// all paramaters are known and the context is fully built.
-  ///
-  /// @param Kind The assumption kind describing the underlying cause.
-  /// @param Set  The relations between parameters that are assumed to hold.
-  /// @param Loc  The location in the source that caused this assumption.
-  /// @param Sign Enum to indicate if the assumptions in @p Set are positive
-  ///             (needed/assumptions) or negative (invalid/restrictions).
-  /// @param BB   The block in which this assumption was taken. If it is
-  ///             set, the domain of that block will be used to simplify the
-  ///             actual assumption in @p Set once it is added. This is useful
-  ///             if the assumption was created prior to the domain.
-  void recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
-                        AssumptionSign Sign, BasicBlock *BB = nullptr);
-
   /// Mark the scop as invalid.
   ///
   /// This method adds an assumption to the scop that is always invalid. As a
@@ -2504,7 +2437,7 @@ class Scop {
   ///
   /// @returns The ScopArrayInfo pointer or NULL if no such pointer is
   ///          available.
-  const ScopArrayInfo *getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind);
+  ScopArrayInfo *getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind);
 
   /// Return the cached ScopArrayInfo object for @p BasePtr.
   ///
@@ -2513,7 +2446,7 @@ class Scop {
   ///
   /// @returns The ScopArrayInfo pointer (may assert if no such pointer is
   ///          available).
-  const ScopArrayInfo *getScopArrayInfo(Value *BasePtr, MemoryKind Kind);
+  ScopArrayInfo *getScopArrayInfo(Value *BasePtr, MemoryKind Kind);
 
   /// Invalidate ScopArrayInfo object for base address.
   ///
@@ -2589,13 +2522,16 @@ class Scop {
   /// a dummy value of appropriate dimension is returned. This allows to bail
   /// for complex cases without "error handling code" needed on the users side.
   PWACtx getPwAff(const SCEV *E, BasicBlock *BB = nullptr,
-                  bool NonNegative = false);
+                  bool NonNegative = false,
+                  RecordedAssumptionsTy *RecordedAssumptions = nullptr);
 
   /// Compute the isl representation for the SCEV @p E
   ///
   /// This function is like @see Scop::getPwAff() but strips away the invalid
   /// domain part associated with the piecewise affine function.
-  isl::pw_aff getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr);
+  isl::pw_aff
+  getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr,
+               RecordedAssumptionsTy *RecordedAssumptions = nullptr);
 
   /// Check if an <nsw> AddRec for the loop L is cached.
   bool hasNSWAddRecForLoop(Loop *L) { return Affinator.hasNSWAddRecForLoop(L); }

diff  --git a/polly/include/polly/Support/SCEVAffinator.h b/polly/include/polly/Support/SCEVAffinator.h
index 39a25d4001df..018630a0378f 100644
--- a/polly/include/polly/Support/SCEVAffinator.h
+++ b/polly/include/polly/Support/SCEVAffinator.h
@@ -13,6 +13,7 @@
 #ifndef POLLY_SCEV_AFFINATOR_H
 #define POLLY_SCEV_AFFINATOR_H
 
+#include "polly/Support/ScopHelper.h"
 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
 #include "isl/isl-noexceptions.h"
 
@@ -36,10 +37,12 @@ struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, PWACtx> {
   /// @param BB The block in which @p E is executed.
   ///
   /// @returns The isl representation of the SCEV @p E in @p Domain.
-  PWACtx getPwAff(const llvm::SCEV *E, llvm::BasicBlock *BB = nullptr);
+  PWACtx getPwAff(const llvm::SCEV *E, llvm::BasicBlock *BB = nullptr,
+                  RecordedAssumptionsTy *RecordedAssumptions = nullptr);
 
   /// Take the assumption that @p PWAC is non-negative.
-  void takeNonNegativeAssumption(PWACtx &PWAC);
+  void takeNonNegativeAssumption(
+      PWACtx &PWAC, RecordedAssumptionsTy *RecordedAssumptions = nullptr);
 
   /// Interpret the PWA in @p PWAC as an unsigned value.
   void interpretAsUnsigned(PWACtx &PWAC, unsigned Width);
@@ -63,6 +66,7 @@ struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, PWACtx> {
   llvm::ScalarEvolution &SE;
   llvm::LoopInfo &LI;
   llvm::BasicBlock *BB;
+  RecordedAssumptionsTy *RecordedAssumptions = nullptr;
 
   /// Target data for element size computing.
   const llvm::DataLayout &TD;

diff  --git a/polly/include/polly/Support/ScopHelper.h b/polly/include/polly/Support/ScopHelper.h
index 8d794e0bf786..23937b12c47c 100644
--- a/polly/include/polly/Support/ScopHelper.h
+++ b/polly/include/polly/Support/ScopHelper.h
@@ -17,6 +17,7 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/ValueHandle.h"
+#include "isl/isl-noexceptions.h"
 
 namespace llvm {
 class LoopInfo;
@@ -34,6 +35,63 @@ namespace polly {
 class Scop;
 class ScopStmt;
 
+/// Enumeration of assumptions Polly can take.
+enum AssumptionKind {
+  ALIASING,
+  INBOUNDS,
+  WRAPPING,
+  UNSIGNED,
+  PROFITABLE,
+  ERRORBLOCK,
+  COMPLEXITY,
+  INFINITELOOP,
+  INVARIANTLOAD,
+  DELINEARIZATION,
+};
+
+/// Enum to distinguish between assumptions and restrictions.
+enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION };
+
+/// Helper struct to remember assumptions.
+struct Assumption {
+  /// The kind of the assumption (e.g., WRAPPING).
+  AssumptionKind Kind;
+
+  /// Flag to distinguish assumptions and restrictions.
+  AssumptionSign Sign;
+
+  /// The valid/invalid context if this is an assumption/restriction.
+  isl::set Set;
+
+  /// The location that caused this assumption.
+  llvm::DebugLoc Loc;
+
+  /// An optional block whose domain can simplify the assumption.
+  llvm::BasicBlock *BB;
+};
+
+using RecordedAssumptionsTy = llvm::SmallVector<Assumption, 8>;
+
+/// Record an assumption for later addition to the assumed context.
+///
+/// This function will add the assumption to the RecordedAssumptions. This
+/// collection will be added (@see addAssumption) to the assumed context once
+/// all paramaters are known and the context is fully built.
+///
+/// @param RecordedAssumption container which keeps all recorded assumptions.
+/// @param Kind The assumption kind describing the underlying cause.
+/// @param Set  The relations between parameters that are assumed to hold.
+/// @param Loc  The location in the source that caused this assumption.
+/// @param Sign Enum to indicate if the assumptions in @p Set are positive
+///             (needed/assumptions) or negative (invalid/restrictions).
+/// @param BB   The block in which this assumption was taken. If it is
+///             set, the domain of that block will be used to simplify the
+///             actual assumption in @p Set once it is added. This is useful
+///             if the assumption was created prior to the domain.
+void recordAssumption(RecordedAssumptionsTy *RecordedAssumptions,
+                      AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc,
+                      AssumptionSign Sign, llvm::BasicBlock *BB = nullptr);
+
 /// Type to remap values.
 using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>,
                                  llvm::AssertingVH<llvm::Value>>;

diff  --git a/polly/lib/Analysis/ScopBuilder.cpp b/polly/lib/Analysis/ScopBuilder.cpp
index 61efbef96aef..e0635cc8a66b 100644
--- a/polly/lib/Analysis/ScopBuilder.cpp
+++ b/polly/lib/Analysis/ScopBuilder.cpp
@@ -96,6 +96,11 @@ static cl::opt<bool> PollyAllowDereferenceOfAllFunctionParams(
         " their loads. "),
     cl::Hidden, cl::init(false), cl::cat(PollyCategory));
 
+static cl::opt<bool>
+    PollyIgnoreInbounds("polly-ignore-inbounds",
+                        cl::desc("Do not take inbounds assumptions at all"),
+                        cl::Hidden, cl::init(false), cl::cat(PollyCategory));
+
 static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup(
     "polly-rtc-max-arrays-per-group",
     cl::desc("The maximal number of arrays to compare in each alias group."),
@@ -344,7 +349,7 @@ __isl_give isl_pw_aff *
 ScopBuilder::getPwAff(BasicBlock *BB,
                       DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
                       const SCEV *E, bool NonNegative) {
-  PWACtx PWAC = scop->getPwAff(E, BB, NonNegative);
+  PWACtx PWAC = scop->getPwAff(E, BB, NonNegative, &RecordedAssumptions);
   InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
   return PWAC.first.release();
 }
@@ -796,9 +801,8 @@ bool ScopBuilder::addLoopBoundsToHeaderDomain(
     return true;
 
   isl::set UnboundedCtx = Parts.first.params();
-  scop->recordAssumption(INFINITELOOP, UnboundedCtx,
-                         HeaderBB->getTerminator()->getDebugLoc(),
-                         AS_RESTRICTION);
+  recordAssumption(&RecordedAssumptions, INFINITELOOP, UnboundedCtx,
+                   HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
   return true;
 }
 
@@ -1019,9 +1023,8 @@ bool ScopBuilder::propagateInvalidStmtDomains(
     } else {
       InvalidDomain = Domain;
       isl::set DomPar = Domain.params();
-      scop->recordAssumption(ERRORBLOCK, DomPar,
-                             BB->getTerminator()->getDebugLoc(),
-                             AS_RESTRICTION);
+      recordAssumption(&RecordedAssumptions, ERRORBLOCK, DomPar,
+                       BB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
       Domain = isl::set::empty(Domain.get_space());
     }
 
@@ -1488,7 +1491,7 @@ Value *ScopBuilder::findFADAllocationInvisible(MemAccInst Inst) {
 }
 
 void ScopBuilder::addRecordedAssumptions() {
-  for (auto &AS : llvm::reverse(scop->recorded_assumptions())) {
+  for (auto &AS : llvm::reverse(RecordedAssumptions)) {
 
     if (!AS.BB) {
       scop->addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign,
@@ -1518,7 +1521,6 @@ void ScopBuilder::addRecordedAssumptions() {
 
     scop->addAssumption(AS.Kind, isl::manage(S), AS.Loc, AS_RESTRICTION, AS.BB);
   }
-  scop->clearRecordedAssumptions();
 }
 
 void ScopBuilder::addUserAssumptions(
@@ -2502,9 +2504,17 @@ void ScopBuilder::foldAccessRelations() {
 }
 
 void ScopBuilder::assumeNoOutOfBounds() {
+  if (PollyIgnoreInbounds)
+    return;
   for (auto &Stmt : *scop)
-    for (auto &Access : Stmt)
-      Access->assumeNoOutOfBound();
+    for (auto &Access : Stmt) {
+      isl::set Outside = Access->assumeNoOutOfBound();
+      const auto &Loc = Access->getAccessInstruction()
+                            ? Access->getAccessInstruction()->getDebugLoc()
+                            : DebugLoc();
+      recordAssumption(&RecordedAssumptions, INBOUNDS, Outside, Loc,
+                       AS_ASSUMPTION);
+    }
 }
 
 void ScopBuilder::ensureValueWrite(Instruction *Inst) {
@@ -2959,8 +2969,8 @@ bool ScopBuilder::canAlwaysBeHoisted(MemoryAccess *MA,
   // Even if the statement is not modeled precisely we can hoist the load if it
   // does not involve any parameters that might have been specialized by the
   // statement domain.
-  for (unsigned u = 0, e = MA->getNumSubscripts(); u < e; u++)
-    if (!isa<SCEVConstant>(MA->getSubscript(u)))
+  for (const SCEV *Subscript : MA->subscripts())
+    if (!isa<SCEVConstant>(Subscript))
       return false;
   return true;
 }
@@ -3214,8 +3224,26 @@ void ScopBuilder::buildAccessRelations(ScopStmt &Stmt) {
     else
       Ty = MemoryKind::Array;
 
+    // Create isl::pw_aff for SCEVs which describe sizes. Collect all
+    // assumptions which are taken. isl::pw_aff objects are cached internally
+    // and they are used later by scop.
+    for (const SCEV *Size : Access->Sizes) {
+      if (!Size)
+        continue;
+      scop->getPwAff(Size, nullptr, false, &RecordedAssumptions);
+    }
     auto *SAI = scop->getOrCreateScopArrayInfo(Access->getOriginalBaseAddr(),
                                                ElementType, Access->Sizes, Ty);
+
+    // Create isl::pw_aff for SCEVs which describe subscripts. Collect all
+    // assumptions which are taken. isl::pw_aff objects are cached internally
+    // and they are used later by scop.
+    for (const SCEV *Subscript : Access->subscripts()) {
+      if (!Access->isAffine() || !Subscript)
+        continue;
+      scop->getPwAff(Subscript, Stmt.getEntryBlock(), false,
+                     &RecordedAssumptions);
+    }
     Access->buildAccessRelation(SAI);
     scop->addAccessData(Access);
   }
@@ -3768,6 +3796,7 @@ ScopBuilder::ScopBuilder(Region *R, AssumptionCache &AC, AliasAnalysis &AA,
     InfeasibleScops++;
     Msg = "SCoP ends here but was dismissed.";
     LLVM_DEBUG(dbgs() << "SCoP detected but dismissed\n");
+    RecordedAssumptions.clear();
     scop.reset();
   } else {
     Msg = "SCoP ends here.";

diff  --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp
index cb0e2a99ca94..7925f105e84f 100644
--- a/polly/lib/Analysis/ScopInfo.cpp
+++ b/polly/lib/Analysis/ScopInfo.cpp
@@ -133,11 +133,6 @@ static cl::opt<bool> PollyPreciseInbounds(
     cl::desc("Take more precise inbounds assumptions (do not scale well)"),
     cl::Hidden, cl::init(false), cl::cat(PollyCategory));
 
-static cl::opt<bool>
-    PollyIgnoreInbounds("polly-ignore-inbounds",
-                        cl::desc("Do not take inbounds assumptions at all"),
-                        cl::Hidden, cl::init(false), cl::cat(PollyCategory));
-
 static cl::opt<bool> PollyIgnoreParamBounds(
     "polly-ignore-parameter-bounds",
     cl::desc(
@@ -662,9 +657,7 @@ isl::basic_map MemoryAccess::createBasicAccessMap(ScopStmt *Statement) {
 // possibly yield out of bound memory accesses. The complement of these
 // constraints is the set of constraints that needs to be assumed to ensure such
 // statement instances are never executed.
-void MemoryAccess::assumeNoOutOfBound() {
-  if (PollyIgnoreInbounds)
-    return;
+isl::set MemoryAccess::assumeNoOutOfBound() {
   auto *SAI = getScopArrayInfo();
   isl::space Space = getOriginalAccessRelationSpace().range();
   isl::set Outside = isl::set::empty(Space);
@@ -692,13 +685,10 @@ void MemoryAccess::assumeNoOutOfBound() {
   // bail out more often than strictly necessary.
   Outside = Outside.remove_divs();
   Outside = Outside.complement();
-  const auto &Loc = getAccessInstruction()
-                        ? getAccessInstruction()->getDebugLoc()
-                        : DebugLoc();
+
   if (!PollyPreciseInbounds)
     Outside = Outside.gist_params(Statement->getDomain().params());
-  Statement->getParent()->recordAssumption(INBOUNDS, Outside, Loc,
-                                           AS_ASSUMPTION);
+  return Outside;
 }
 
 void MemoryAccess::buildMemIntrinsicAccessRelation() {
@@ -1856,13 +1846,12 @@ ScopArrayInfo *Scop::createScopArrayInfo(Type *ElementType,
   return SAI;
 }
 
-const ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr,
-                                                  MemoryKind Kind) {
+ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind) {
   auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
   return SAI;
 }
 
-const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
+ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
   auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind);
   assert(SAI && "No ScopArrayInfo available for this base pointer");
   return SAI;
@@ -2117,13 +2106,6 @@ void Scop::addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
     InvalidContext = InvalidContext.unite(Set).coalesce();
 }
 
-void Scop::recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
-                            AssumptionSign Sign, BasicBlock *BB) {
-  assert((Set.is_params() || BB) &&
-         "Assumptions without a basic block must be parameter sets");
-  RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB});
-}
-
 void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) {
   LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n");
   addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB);
@@ -2241,13 +2223,14 @@ LLVM_DUMP_METHOD void Scop::dump() const { print(dbgs(), true); }
 isl::ctx Scop::getIslCtx() const { return IslCtx.get(); }
 
 __isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
-                                 bool NonNegative) {
+                                 bool NonNegative,
+                                 RecordedAssumptionsTy *RecordedAssumptions) {
   // First try to use the SCEVAffinator to generate a piecewise defined
   // affine function from @p E in the context of @p BB. If that tasks becomes to
   // complex the affinator might return a nullptr. In such a case we invalidate
   // the SCoP and return a dummy value. This way we do not need to add error
   // handling code to all users of this function.
-  auto PWAC = Affinator.getPwAff(E, BB);
+  auto PWAC = Affinator.getPwAff(E, BB, RecordedAssumptions);
   if (PWAC.first) {
     // TODO: We could use a heuristic and either use:
     //         SCEVAffinator::takeNonNegativeAssumption
@@ -2255,13 +2238,13 @@ __isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
     //         SCEVAffinator::interpretAsUnsigned
     //       to deal with unsigned or "NonNegative" SCEVs.
     if (NonNegative)
-      Affinator.takeNonNegativeAssumption(PWAC);
+      Affinator.takeNonNegativeAssumption(PWAC, RecordedAssumptions);
     return PWAC;
   }
 
   auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
   invalidate(COMPLEXITY, DL, BB);
-  return Affinator.getPwAff(SE->getZero(E->getType()), BB);
+  return Affinator.getPwAff(SE->getZero(E->getType()), BB, RecordedAssumptions);
 }
 
 isl::union_set Scop::getDomains() const {
@@ -2274,8 +2257,9 @@ isl::union_set Scop::getDomains() const {
   return isl::manage(Domain);
 }
 
-isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) {
-  PWACtx PWAC = getPwAff(E, BB);
+isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB,
+                               RecordedAssumptionsTy *RecordedAssumptions) {
+  PWACtx PWAC = getPwAff(E, BB, RecordedAssumptions);
   return PWAC.first;
 }
 

diff  --git a/polly/lib/Support/SCEVAffinator.cpp b/polly/lib/Support/SCEVAffinator.cpp
index fc6e29ce5199..2c7dc8fa415f 100644
--- a/polly/lib/Support/SCEVAffinator.cpp
+++ b/polly/lib/Support/SCEVAffinator.cpp
@@ -95,23 +95,28 @@ void SCEVAffinator::interpretAsUnsigned(PWACtx &PWAC, unsigned Width) {
       NonNegPWA, isl_pw_aff_add(PWAC.first.release(), ExpPWA)));
 }
 
-void SCEVAffinator::takeNonNegativeAssumption(PWACtx &PWAC) {
+void SCEVAffinator::takeNonNegativeAssumption(
+    PWACtx &PWAC, RecordedAssumptionsTy *RecordedAssumptions) {
+  this->RecordedAssumptions = RecordedAssumptions;
+
   auto *NegPWA = isl_pw_aff_neg(PWAC.first.copy());
   auto *NegDom = isl_pw_aff_pos_set(NegPWA);
   PWAC.second =
       isl::manage(isl_set_union(PWAC.second.release(), isl_set_copy(NegDom)));
   auto *Restriction = BB ? NegDom : isl_set_params(NegDom);
   auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
-  S->recordAssumption(UNSIGNED, isl::manage(Restriction), DL, AS_RESTRICTION,
-                      BB);
+  recordAssumption(RecordedAssumptions, UNSIGNED, isl::manage(Restriction), DL,
+                   AS_RESTRICTION, BB);
 }
 
 PWACtx SCEVAffinator::getPWACtxFromPWA(isl::pw_aff PWA) {
   return std::make_pair(PWA, isl::set::empty(isl::space(Ctx, 0, NumIterators)));
 }
 
-PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB) {
+PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB,
+                               RecordedAssumptionsTy *RecordedAssumptions) {
   this->BB = BB;
+  this->RecordedAssumptions = RecordedAssumptions;
 
   if (BB) {
     auto *DC = S->getDomainConditions(BB).release();
@@ -145,7 +150,8 @@ PWACtx SCEVAffinator::checkForWrapping(const SCEV *Expr, PWACtx PWAC) const {
   NotEqualSet = NotEqualSet.coalesce();
 
   if (!NotEqualSet.is_empty())
-    S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB);
+    recordAssumption(RecordedAssumptions, WRAPPING, NotEqualSet, Loc,
+                     AS_RESTRICTION, BB);
 
   return PWAC;
 }
@@ -289,8 +295,8 @@ PWACtx SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
     OutOfBoundsDom = isl_set_params(OutOfBoundsDom);
   }
 
-  S->recordAssumption(UNSIGNED, isl::manage(OutOfBoundsDom), DebugLoc(),
-                      AS_RESTRICTION, BB);
+  recordAssumption(RecordedAssumptions, UNSIGNED, isl::manage(OutOfBoundsDom),
+                   DebugLoc(), AS_RESTRICTION, BB);
 
   return OpPWAC;
 }
@@ -344,7 +350,7 @@ PWACtx SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
 
   // If the width is to big we assume the negative part does not occur.
   if (!computeModuloForExpr(Op)) {
-    takeNonNegativeAssumption(OpPWAC);
+    takeNonNegativeAssumption(OpPWAC, RecordedAssumptions);
     return OpPWAC;
   }
 
@@ -485,7 +491,7 @@ PWACtx SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
   //       precise but therefor a heuristic is needed.
 
   // Assume a non-negative dividend.
-  takeNonNegativeAssumption(DividendPWAC);
+  takeNonNegativeAssumption(DividendPWAC, RecordedAssumptions);
 
   DividendPWAC = combine(DividendPWAC, DivisorPWAC, isl_pw_aff_div);
   DividendPWAC.first = DividendPWAC.first.floor();

diff  --git a/polly/lib/Support/ScopHelper.cpp b/polly/lib/Support/ScopHelper.cpp
index 5f80afd08211..d2a8f3884240 100644
--- a/polly/lib/Support/ScopHelper.cpp
+++ b/polly/lib/Support/ScopHelper.cpp
@@ -221,6 +221,16 @@ void polly::splitEntryBlockForAlloca(BasicBlock *EntryBlock, Pass *P) {
   polly::splitEntryBlockForAlloca(EntryBlock, DT, LI, RI);
 }
 
+void polly::recordAssumption(polly::RecordedAssumptionsTy *RecordedAssumptions,
+                             polly::AssumptionKind Kind, isl::set Set,
+                             DebugLoc Loc, polly::AssumptionSign Sign,
+                             BasicBlock *BB) {
+  assert((Set.is_params() || BB) &&
+         "Assumptions without a basic block must be parameter sets");
+  if (RecordedAssumptions)
+    RecordedAssumptions->push_back({Kind, Sign, Set, Loc, BB});
+}
+
 /// The SCEVExpander will __not__ generate any code for an existing SDiv/SRem
 /// instruction but just use it, if it is referenced as a SCEVUnknown. We want
 /// however to generate new code if the instruction is in the analyzed region


        


More information about the llvm-commits mailing list