[polly] r230329 - Allow non-affine control flow -- SCoP Modeling

Johannes Doerfert doerfert at cs.uni-saarland.de
Tue Feb 24 04:00:51 PST 2015


Author: jdoerfert
Date: Tue Feb 24 06:00:50 2015
New Revision: 230329

URL: http://llvm.org/viewvc/llvm-project?rev=230329&view=rev
Log:
Allow non-affine control flow -- SCoP Modeling

  This allows us to model non-affine regions in the SCoP representation.
  SCoP statements can now describe either basic blocks or non-affine
  regions. In the latter case all accesses in the region are accumulated
  for the statement and write accesses, except in the entry, have to be
  marked as may-write.

Differential Revision: http://reviews.llvm.org/D7846

Added:
    polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll
    polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/include/polly/TempScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Analysis/TempScopInfo.cpp

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Tue Feb 24 06:00:50 2015
@@ -429,9 +429,21 @@ class ScopStmt {
 
   //@}
 
-  /// The BasicBlock represented by this statement.
+  /// @brief A SCoP statement represents either a basic block (affine/precise
+  ///        case) or a whole region (non-affine case). Only one of the
+  ///        following two members will therefore be set and indicate which
+  ///        kind of statement this is.
+  ///
+  ///{
+
+  /// @brief The BasicBlock represented by this statement (in the affine case).
   BasicBlock *BB;
 
+  /// @brief The region represented by this statement (in the non-affine case).
+  Region *R;
+
+  ///}
+
   /// @brief The isl AST build for the new generated AST.
   isl_ast_build *Build;
 
@@ -449,7 +461,17 @@ class ScopStmt {
                                             TempScop &tempScop);
   __isl_give isl_set *buildDomain(TempScop &tempScop, const Region &CurRegion);
   void buildScattering(SmallVectorImpl<unsigned> &Scatter);
-  void buildAccesses(TempScop &tempScop);
+
+  /// @brief Create the accesses for instructions in @p Block.
+  ///
+  /// @param tempScop       The template SCoP.
+  /// @param Block          The basic block for which accesses should be
+  ///                       created.
+  /// @param isApproximated Flag to indicate blocks that might not be executed,
+  ///                       hence for which write accesses need to be modelt as
+  ///                       may-write accesses.
+  void buildAccesses(TempScop &tempScop, BasicBlock *Block,
+                     bool isApproximated = false);
 
   /// @brief Detect and mark reductions in the ScopStmt
   void checkForReductions();
@@ -489,14 +511,19 @@ class ScopStmt {
   /// or non-optimal run-time checks.
   void deriveAssumptionsFromGEP(GetElementPtrInst *Inst);
 
-  /// @brief Scan the scop and derive assumptions about parameter values.
-  void deriveAssumptions();
+  /// @brief Scan @p Block and derive assumptions about parameter values.
+  void deriveAssumptions(BasicBlock *Block);
 
   /// Create the ScopStmt from a BasicBlock.
   ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
            BasicBlock &bb, SmallVectorImpl<Loop *> &NestLoops,
            SmallVectorImpl<unsigned> &Scatter);
 
+  /// Create an overapproximating ScopStmt for the region @p R.
+  ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion, Region &R,
+           SmallVectorImpl<Loop *> &NestLoops,
+           SmallVectorImpl<unsigned> &Scatter);
+
   friend class Scop;
 
 public:
@@ -532,11 +559,24 @@ public:
   /// @brief Get an isl string representing this scattering.
   std::string getScatteringStr() const;
 
-  /// @brief Get the BasicBlock represented by this ScopStmt.
+  /// @brief Get the BasicBlock represented by this ScopStmt (if any).
   ///
-  /// @return The BasicBlock represented by this ScopStmt.
+  /// @return The BasicBlock represented by this ScopStmt, or null if the
+  ///         statement represents a region.
   BasicBlock *getBasicBlock() const { return BB; }
 
+  /// @brief Return true if this statement represents a single basic block.
+  bool isBlockStmt() const { return BB != nullptr; }
+
+  /// @brief Get the region represented by this ScopStmt (if any).
+  ///
+  /// @return The region represented by this ScopStmt, or null if the statement
+  ///         represents a basic block.
+  Region *getRegion() const { return R; }
+
+  /// @brief Return true if this statement represents a whole region.
+  bool isRegionStmt() const { return R != nullptr; }
+
   const MemoryAccess &getAccessFor(const Instruction *Inst) const {
     MemoryAccess *A = lookupAccessFor(Inst);
     assert(A && "Cannot get memory access because it does not exist!");
@@ -549,7 +589,12 @@ public:
     return at == InstructionToAccess.end() ? NULL : at->second;
   }
 
-  void setBasicBlock(BasicBlock *Block) { BB = Block; }
+  void setBasicBlock(BasicBlock *Block) {
+    // TODO: Handle the case where the statement is a region statement, thus
+    //       the entry block was split and needs to be changed in the region R.
+    assert(BB && "Cannot set a block for a region statement");
+    BB = Block;
+  }
 
   typedef MemoryAccessVec::iterator iterator;
   typedef MemoryAccessVec::const_iterator const_iterator;
@@ -697,7 +742,8 @@ private:
 
   /// Create the static control part with a region, max loop depth of this
   /// region and parameters used in this region.
-  Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, isl_ctx *ctx);
+  Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, ScopDetection &SD,
+       isl_ctx *ctx);
 
   /// @brief Check if a basic block is trivial.
   ///
@@ -719,12 +765,28 @@ private:
   /// @brief Simplify the assumed context.
   void simplifyAssumedContext();
 
+  /// @brief Create a new SCoP statement for either @p BB or @p R.
+  ///
+  /// Either @p BB or @p R should be non-null. A new statement for the non-null
+  /// argument will be created and added to the statement vector and map.
+  ///
+  /// @param BB         The basic block we build the statement for (or null)
+  /// @param R          The region we build the statement for (or null).
+  /// @param tempScop   The temp SCoP we use as model.
+  /// @param CurRegion  The SCoP region.
+  /// @param NestLoops  A vector of all surrounding loops.
+  /// @param Scatter    The position of the new statement as scattering.
+  void addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop,
+                   const Region &CurRegion, SmallVectorImpl<Loop *> &NestLoops,
+                   SmallVectorImpl<unsigned> &Scatter);
+
   /// Build the Scop and Statement with precalculated scop information.
   void buildScop(TempScop &TempScop, const Region &CurRegion,
                  // Loops in Scop containing CurRegion
                  SmallVectorImpl<Loop *> &NestLoops,
                  // The scattering numbers
-                 SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI);
+                 SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI,
+                 ScopDetection &SD);
 
   /// @name Helper function for printing the Scop.
   ///

Modified: polly/trunk/include/polly/TempScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/TempScopInfo.h?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/include/polly/TempScopInfo.h (original)
+++ polly/trunk/include/polly/TempScopInfo.h Tue Feb 24 06:00:50 2015
@@ -80,6 +80,8 @@ public:
 
   bool isWrite() const { return Type == MUST_WRITE; }
 
+  void setMayWrite() { Type = MAY_WRITE; }
+
   bool isMayWrite() const { return Type == MAY_WRITE; }
 
   bool isScalar() const { return Subscripts.size() == 0; }
@@ -136,7 +138,7 @@ class TempScop {
   const BBCondMapType &BBConds;
 
   // Access function of bbs.
-  const AccFuncMapType &AccFuncMap;
+  AccFuncMapType &AccFuncMap;
 
   friend class TempScopInfo;
 
@@ -169,8 +171,8 @@ public:
   ///
   /// @return All access functions in BB
   ///
-  const AccFuncSetType *getAccessFunctions(const BasicBlock *BB) const {
-    AccFuncMapType::const_iterator at = AccFuncMap.find(BB);
+  AccFuncSetType *getAccessFunctions(const BasicBlock *BB) {
+    AccFuncMapType::iterator at = AccFuncMap.find(BB);
     return at != AccFuncMap.end() ? &(at->second) : 0;
   }
   //@}
@@ -239,10 +241,9 @@ class TempScopInfo : public FunctionPass
 
   /// @brief Build condition constrains to BBs in a valid Scop.
   ///
-  /// @param BB           The BasicBlock to build condition constrains
-  /// @param RegionEntry  The entry block of the Smallest Region that containing
-  ///                     BB
-  void buildCondition(BasicBlock *BB, BasicBlock *RegionEntry);
+  /// @param BB The BasicBlock to build condition constrains
+  /// @param R  The region for the current TempScop.
+  void buildCondition(BasicBlock *BB, Region &R);
 
   // Build the affine function of the given condition
   void buildAffineCondition(Value &V, bool inverted, Comparison **Comp) const;

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Tue Feb 24 06:00:50 2015
@@ -797,15 +797,23 @@ void ScopStmt::buildScattering(SmallVect
   Scattering = isl_map_align_params(Scattering, Parent.getParamSpace());
 }
 
-void ScopStmt::buildAccesses(TempScop &tempScop) {
-  for (const auto &AccessPair : *tempScop.getAccessFunctions(BB)) {
-    const IRAccess &Access = AccessPair.first;
+void ScopStmt::buildAccesses(TempScop &tempScop, BasicBlock *Block,
+                             bool isApproximated) {
+  AccFuncSetType *AFS = tempScop.getAccessFunctions(Block);
+  if (!AFS)
+    return;
+
+  for (auto &AccessPair : *AFS) {
+    IRAccess &Access = AccessPair.first;
     Instruction *AccessInst = AccessPair.second;
 
     Type *AccessType = getAccessInstType(AccessInst)->getPointerTo();
     const ScopArrayInfo *SAI = getParent()->getOrCreateScopArrayInfo(
         Access.getBase(), AccessType, Access.Sizes);
 
+    if (isApproximated && Access.isWrite())
+      Access.setMayWrite();
+
     MemAccs.push_back(new MemoryAccess(Access, AccessInst, this, SAI));
 
     // We do not track locations for scalar memory accesses at the moment.
@@ -894,7 +902,7 @@ __isl_give isl_set *ScopStmt::addConditi
                                                     const Region &CurRegion) {
   const Region *TopRegion = tempScop.getMaxRegion().getParent(),
                *CurrentRegion = &CurRegion;
-  const BasicBlock *BranchingBB = BB;
+  const BasicBlock *BranchingBB = BB ? BB : R->getEntry();
 
   do {
     if (BranchingBB != CurrentRegion->getEntry()) {
@@ -978,16 +986,39 @@ void ScopStmt::deriveAssumptionsFromGEP(
   isl_local_space_free(LSpace);
 }
 
-void ScopStmt::deriveAssumptions() {
-  for (Instruction &Inst : *BB)
+void ScopStmt::deriveAssumptions(BasicBlock *Block) {
+  for (Instruction &Inst : *Block)
     if (auto *GEP = dyn_cast<GetElementPtrInst>(&Inst))
       deriveAssumptionsFromGEP(GEP);
 }
 
 ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
+                   Region &R, SmallVectorImpl<Loop *> &Nest,
+                   SmallVectorImpl<unsigned> &Scatter)
+    : Parent(parent), BB(nullptr), R(&R), Build(nullptr),
+      NestLoops(Nest.size()) {
+  // Setup the induction variables.
+  for (unsigned i = 0, e = Nest.size(); i < e; ++i)
+    NestLoops[i] = Nest[i];
+
+  BaseName = getIslCompatibleName("Stmt_(", R.getNameStr(), ")");
+
+  Domain = buildDomain(tempScop, CurRegion);
+  buildScattering(Scatter);
+
+  BasicBlock *EntryBB = R.getEntry();
+  for (BasicBlock *Block : R.blocks()) {
+    buildAccesses(tempScop, Block, Block != EntryBB);
+    deriveAssumptions(Block);
+  }
+  checkForReductions();
+}
+
+ScopStmt::ScopStmt(Scop &parent, TempScop &tempScop, const Region &CurRegion,
                    BasicBlock &bb, SmallVectorImpl<Loop *> &Nest,
                    SmallVectorImpl<unsigned> &Scatter)
-    : Parent(parent), BB(&bb), Build(nullptr), NestLoops(Nest.size()) {
+    : Parent(parent), BB(&bb), R(nullptr), Build(nullptr),
+      NestLoops(Nest.size()) {
   // Setup the induction variables.
   for (unsigned i = 0, e = Nest.size(); i < e; ++i)
     NestLoops[i] = Nest[i];
@@ -996,20 +1027,23 @@ ScopStmt::ScopStmt(Scop &parent, TempSco
 
   Domain = buildDomain(tempScop, CurRegion);
   buildScattering(Scatter);
-  buildAccesses(tempScop);
+  buildAccesses(tempScop, BB);
+  deriveAssumptions(BB);
   checkForReductions();
-  deriveAssumptions();
 }
 
 /// @brief Collect loads which might form a reduction chain with @p StoreMA
 ///
-/// Check if the stored value for @p StoreMA is a binary operator with one or
-/// two loads as operands. If the binary operand is commutative & associative,
+/// Check if the stored value for @p StoreMA is a binary operator with one
+/// or
+/// two loads as operands. If the binary operand is commutative &
+/// associative,
 /// used only once (by @p StoreMA) and its load operands are also used only
 /// once, we have found a possible reduction chain. It starts at an operand
 /// load and includes the binary operator and @p StoreMA.
 ///
-/// Note: We allow only one use to ensure the load and binary operator cannot
+/// Note: We allow only one use to ensure the load and binary operator
+/// cannot
 ///       escape this block or into any other store except @p StoreMA.
 void ScopStmt::collectCandiateReductionLoads(
     MemoryAccess *StoreMA, SmallVectorImpl<MemoryAccess *> &Loads) {
@@ -1026,7 +1060,8 @@ void ScopStmt::collectCandiateReductionL
   if (BinOp->getNumUses() != 1)
     return;
 
-  // Skip if the opcode of the binary operator is not commutative/associative
+  // Skip if the opcode of the binary operator is not
+  // commutative/associative
   if (!BinOp->isCommutative() || !BinOp->isAssociative())
     return;
 
@@ -1057,11 +1092,16 @@ void ScopStmt::collectCandiateReductionL
 
 /// @brief Check for reductions in this ScopStmt
 ///
-/// Iterate over all store memory accesses and check for valid binary reduction
-/// like chains. For all candidates we check if they have the same base address
-/// and there are no other accesses which overlap with them. The base address
-/// check rules out impossible reductions candidates early. The overlap check,
-/// together with the "only one user" check in collectCandiateReductionLoads,
+/// Iterate over all store memory accesses and check for valid binary
+/// reduction
+/// like chains. For all candidates we check if they have the same base
+/// address
+/// and there are no other accesses which overlap with them. The base
+/// address
+/// check rules out impossible reductions candidates early. The overlap
+/// check,
+/// together with the "only one user" check in
+/// collectCandiateReductionLoads,
 /// guarantees that none of the intermediate results will escape during
 /// execution of the loop nest. We basically check here that no other memory
 /// access can access the same memory as the potential reduction.
@@ -1069,7 +1109,8 @@ void ScopStmt::checkForReductions() {
   SmallVector<MemoryAccess *, 2> Loads;
   SmallVector<std::pair<MemoryAccess *, MemoryAccess *>, 4> Candidates;
 
-  // First collect candidate load-store reduction chains by iterating over all
+  // First collect candidate load-store reduction chains by iterating over
+  // all
   // stores and collecting possible reduction loads.
   for (MemoryAccess *StoreMA : MemAccs) {
     if (StoreMA->isRead())
@@ -1282,10 +1323,13 @@ void Scop::simplifyAssumedContext() {
   // WARNING: This only holds if the assumptions we have taken do not reduce
   //          the set of statement instances that are executed. Otherwise we
   //          may run into a case where the iteration domains suggest that
-  //          for a certain set of parameter constraints no code is executed,
+  //          for a certain set of parameter constraints no code is
+  //          executed,
   //          but in the original program some computation would have been
-  //          performed. In such a case, modifying the run-time conditions and
-  //          possibly influencing the run-time check may cause certain scops
+  //          performed. In such a case, modifying the run-time conditions
+  //          and
+  //          possibly influencing the run-time check may cause certain
+  //          scops
   //          to not be executed.
   //
   // Example:
@@ -1297,7 +1341,8 @@ void Scop::simplifyAssumedContext() {
   //         A[i+p][j] = 1.0;
   //
   //   we assume that the condition m <= 0 or (m >= 1 and p >= 0) holds as
-  //   otherwise we would access out of bound data. Now, knowing that code is
+  //   otherwise we would access out of bound data. Now, knowing that code
+  //   is
   //   only executed for the case m >= 0, it is sufficient to assume p >= 0.
   AssumedContext =
       isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
@@ -1374,18 +1419,22 @@ static __isl_give isl_set *getAccessDoma
 
 bool Scop::buildAliasGroups(AliasAnalysis &AA) {
   // To create sound alias checks we perform the following steps:
-  //   o) Use the alias analysis and an alias set tracker to build alias sets
+  //   o) Use the alias analysis and an alias set tracker to build alias
+  //   sets
   //      for all memory accesses inside the SCoP.
   //   o) For each alias set we then map the aliasing pointers back to the
-  //      memory accesses we know, thus obtain groups of memory accesses which
+  //      memory accesses we know, thus obtain groups of memory accesses
+  //      which
   //      might alias.
   //   o) We divide each group based on the domains of the minimal/maximal
-  //      accesses. That means two minimal/maximal accesses are only in a group
+  //      accesses. That means two minimal/maximal accesses are only in a
+  //      group
   //      if their access domains intersect, otherwise they are in different
   //      ones.
   //   o) We split groups such that they contain at most one read only base
   //      address.
-  //   o) For each group with more than one base pointer we then compute minimal
+  //   o) For each group with more than one base pointer we then compute
+  //   minimal
   //      and maximal accesses to each array in this group.
   using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
 
@@ -1485,7 +1534,8 @@ bool Scop::buildAliasGroups(AliasAnalysi
     }
 
     // If we have both read only and non read only base pointers we combine
-    // the non read only ones with exactly one read only one at a time into a
+    // the non read only ones with exactly one read only one at a time into
+    // a
     // new alias group and clear the old alias group in the end.
     for (const auto &ReadOnlyPair : ReadOnlyPairs) {
       AliasGroupTy AGNonReadOnly = AG;
@@ -1582,10 +1632,11 @@ void Scop::dropConstantScheduleDims() {
 }
 
 Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
-           isl_ctx *Context)
+           ScopDetection &SD, isl_ctx *Context)
     : SE(&ScalarEvolution), R(tempScop.getMaxRegion()), IsOptimized(false),
       MaxLoopDepth(getMaxLoopDepthInRegion(tempScop.getMaxRegion(), LI)) {
   IslCtx = Context;
+
   buildContext();
 
   SmallVector<Loop *, 8> NestLoops;
@@ -1595,7 +1646,7 @@ Scop::Scop(TempScop &tempScop, LoopInfo
 
   // Build the iteration domain, access functions and scattering functions
   // traversing the region tree.
-  buildScop(tempScop, getRegion(), NestLoops, Scatter, LI);
+  buildScop(tempScop, getRegion(), NestLoops, Scatter, LI, SD);
 
   realignParams();
   addParameterBounds();
@@ -1866,9 +1917,39 @@ bool Scop::isTrivialBB(BasicBlock *BB, T
   return true;
 }
 
+void Scop::addScopStmt(BasicBlock *BB, Region *R, TempScop &tempScop,
+                       const Region &CurRegion,
+                       SmallVectorImpl<Loop *> &NestLoops,
+                       SmallVectorImpl<unsigned> &Scatter) {
+  ScopStmt *Stmt;
+
+  if (BB) {
+    Stmt = new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter);
+    StmtMap[BB] = Stmt;
+  } else {
+    assert(R && "Either a basic block or a region is needed to "
+                "create a new SCoP stmt.");
+    Stmt = new ScopStmt(*this, tempScop, CurRegion, *R, NestLoops, Scatter);
+    for (BasicBlock *BB : R->blocks())
+      StmtMap[BB] = Stmt;
+  }
+
+  // Insert all statements into the statement map and the statement vector.
+  Stmts.push_back(Stmt);
+
+  // Increasing the Scattering function is OK for the moment, because
+  // we are using a depth first iterator and the program is well structured.
+  ++Scatter[NestLoops.size()];
+}
+
 void Scop::buildScop(TempScop &tempScop, const Region &CurRegion,
                      SmallVectorImpl<Loop *> &NestLoops,
-                     SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI) {
+                     SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI,
+                     ScopDetection &SD) {
+  if (SD.isNonAffineSubRegion(&CurRegion, &getRegion()))
+    return addScopStmt(nullptr, const_cast<Region *>(&CurRegion), tempScop,
+                       CurRegion, NestLoops, Scatter);
+
   Loop *L = castToLoop(CurRegion, LI);
 
   if (L)
@@ -1880,24 +1961,15 @@ void Scop::buildScop(TempScop &tempScop,
   for (Region::const_element_iterator I = CurRegion.element_begin(),
                                       E = CurRegion.element_end();
        I != E; ++I)
-    if (I->isSubRegion())
-      buildScop(tempScop, *(I->getNodeAs<Region>()), NestLoops, Scatter, LI);
-    else {
+    if (I->isSubRegion()) {
+      buildScop(tempScop, *I->getNodeAs<Region>(), NestLoops, Scatter, LI, SD);
+    } else {
       BasicBlock *BB = I->getNodeAs<BasicBlock>();
 
       if (isTrivialBB(BB, tempScop))
         continue;
 
-      ScopStmt *Stmt =
-          new ScopStmt(*this, tempScop, CurRegion, *BB, NestLoops, Scatter);
-
-      // Insert all statements into the statement map and the statement vector.
-      StmtMap[BB] = Stmt;
-      Stmts.push_back(Stmt);
-
-      // Increasing the Scattering function is OK for the moment, because
-      // we are using a depth first iterator and the program is well structured.
-      ++Scatter[loopDepth];
+      addScopStmt(BB, nullptr, tempScop, CurRegion, NestLoops, Scatter);
     }
 
   if (!L)
@@ -1931,6 +2003,7 @@ void ScopInfo::getAnalysisUsage(Analysis
   AU.addRequired<LoopInfoWrapperPass>();
   AU.addRequired<RegionInfoPass>();
   AU.addRequired<ScalarEvolution>();
+  AU.addRequired<ScopDetection>();
   AU.addRequired<TempScopInfo>();
   AU.addRequired<AliasAnalysis>();
   AU.setPreservesAll();
@@ -1939,6 +2012,7 @@ void ScopInfo::getAnalysisUsage(Analysis
 bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
   LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
   AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
+  ScopDetection &SD = getAnalysis<ScopDetection>();
   ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
 
   TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
@@ -1949,7 +2023,7 @@ bool ScopInfo::runOnRegion(Region *R, RG
     return false;
   }
 
-  scop = new Scop(*tempScop, LI, SE, ctx);
+  scop = new Scop(*tempScop, LI, SE, SD, ctx);
 
   if (!PollyUseRuntimeAliasChecks) {
     // Statistics.
@@ -1971,10 +2045,12 @@ bool ScopInfo::runOnRegion(Region *R, RG
 
   DEBUG(dbgs()
         << "\n\nNOTE: Run time checks for " << scop->getNameStr()
-        << " could not be created as the number of parameters involved is too "
+        << " could not be created as the number of parameters involved is "
+           "too "
            "high. The SCoP will be "
            "dismissed.\nUse:\n\t--polly-rtc-max-parameters=X\nto adjust the "
-           "maximal number of parameters but be advised that the compile time "
+           "maximal number of parameters but be advised that the compile "
+           "time "
            "might increase exponentially.\n\n");
 
   delete scop;
@@ -1993,6 +2069,7 @@ INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
 INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass);
 INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
 INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
+INITIALIZE_PASS_DEPENDENCY(ScopDetection);
 INITIALIZE_PASS_DEPENDENCY(TempScopInfo);
 INITIALIZE_PASS_END(ScopInfo, "polly-scops",
                     "Polly - Create polyhedral description of Scops", false,

Modified: polly/trunk/lib/Analysis/TempScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/TempScopInfo.cpp?rev=230329&r1=230328&r2=230329&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/TempScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/TempScopInfo.cpp Tue Feb 24 06:00:50 2015
@@ -310,15 +310,17 @@ void TempScopInfo::buildAffineCondition(
   *Comp = new Comparison(LHS, RHS, Pred);
 }
 
-void TempScopInfo::buildCondition(BasicBlock *BB, BasicBlock *RegionEntry) {
+void TempScopInfo::buildCondition(BasicBlock *BB, Region &R) {
+  BasicBlock *RegionEntry = R.getEntry();
   BBCond Cond;
 
   DomTreeNode *BBNode = DT->getNode(BB), *EntryNode = DT->getNode(RegionEntry);
   assert(BBNode && EntryNode && "Get null node while building condition!");
 
-  // Walk up the dominance tree until reaching the entry node. Add all
-  // conditions on the path to BB except if BB postdominates the block
+  // Walk up the dominance tree until reaching the entry node. Collect all
+  // branching blocks on the path to BB except if BB postdominates the block
   // containing the condition.
+  SmallVector<BasicBlock *, 4> DominatorBrBlocks;
   while (BBNode != EntryNode) {
     BasicBlock *CurBB = BBNode->getBlock();
     BBNode = BBNode->getIDom();
@@ -333,6 +335,24 @@ void TempScopInfo::buildCondition(BasicB
     if (Br->isUnconditional())
       continue;
 
+    DominatorBrBlocks.push_back(BBNode->getBlock());
+  }
+
+  RegionInfo *RI = R.getRegionInfo();
+  // Iterate in reverse order over the dominating blocks.  Until a non-affine
+  // branch was encountered add all conditions collected. If a non-affine branch
+  // was encountered, stop as we overapproximate from here on anyway.
+  for (auto BIt = DominatorBrBlocks.rbegin(), BEnd = DominatorBrBlocks.rend();
+       BIt != BEnd; BIt++) {
+
+    BasicBlock *BBNode = *BIt;
+    BranchInst *Br = dyn_cast<BranchInst>(BBNode->getTerminator());
+    assert(Br && "A Valid Scop should only contain branch instruction");
+    assert(Br->isConditional() && "Assumed a conditional branch");
+
+    if (SD->isNonAffineSubRegion(RI->getRegionFor(BBNode), &R))
+      break;
+
     BasicBlock *TrueBB = Br->getSuccessor(0), *FalseBB = Br->getSuccessor(1);
 
     // Is BB on the ELSE side of the branch?
@@ -365,7 +385,7 @@ TempScop *TempScopInfo::buildTempScop(Re
 
   for (const auto &BB : R.blocks()) {
     buildAccessFunctions(R, *BB);
-    buildCondition(BB, R.getEntry());
+    buildCondition(BB, R);
   }
 
   return TScop;

Added: polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll?rev=230329&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll (added)
+++ polly/trunk/test/ScopInfo/NonAffine/non_affine_conditional_nested.ll Tue Feb 24 06:00:50 2015
@@ -0,0 +1,72 @@
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine-branches -analyze < %s | FileCheck %s
+;
+;    void f(int *A) {
+;      for (int i = 0; i < 1024; i++)
+;        if (A[i])
+;          if (A[i - 1])
+;            A[i] = A[i - 2];
+;    }
+;
+; CHECK:    Region: %bb1---%bb18
+; CHECK:    Max Loop Depth:  1
+; CHECK:    Statements {
+; CHECK:      Stmt_(bb2 => bb16)
+; CHECK:            Domain :=
+; CHECK:                { Stmt_(bb2 => bb16)[i0] : i0 >= 0 and i0 <= 1023 };
+; CHECK:            Scattering :=
+; CHECK:                { Stmt_(bb2 => bb16)[i0] -> [i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb16)[i0] -> MemRef_A[i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb16)[i0] -> MemRef_A[-1 + i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb16)[i0] -> MemRef_A[-2 + i0] };
+; CHECK:            MayWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb16)[i0] -> MemRef_A[i0] };
+; CHECK:    }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A) {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb17, %bb
+  %indvars.iv = phi i64 [ %indvars.iv.next, %bb17 ], [ 0, %bb ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %bb2, label %bb18
+
+bb2:                                              ; preds = %bb1
+  %tmp = getelementptr inbounds i32* %A, i64 %indvars.iv
+  %tmp3 = load i32* %tmp, align 4
+  %tmp4 = icmp eq i32 %tmp3, 0
+  br i1 %tmp4, label %bb16, label %bb5
+
+bb5:                                              ; preds = %bb2
+  %tmp6 = add nsw i64 %indvars.iv, -1
+  %tmp7 = getelementptr inbounds i32* %A, i64 %tmp6
+  %tmp8 = load i32* %tmp7, align 4
+  %tmp9 = icmp eq i32 %tmp8, 0
+  br i1 %tmp9, label %bb15, label %bb10
+
+bb10:                                             ; preds = %bb5
+  %tmp11 = add nsw i64 %indvars.iv, -2
+  %tmp12 = getelementptr inbounds i32* %A, i64 %tmp11
+  %tmp13 = load i32* %tmp12, align 4
+  %tmp14 = getelementptr inbounds i32* %A, i64 %indvars.iv
+  store i32 %tmp13, i32* %tmp14, align 4
+  br label %bb15
+
+bb15:                                             ; preds = %bb5, %bb10
+  br label %bb16
+
+bb16:                                             ; preds = %bb2, %bb15
+  br label %bb17
+
+bb17:                                             ; preds = %bb16
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %bb1
+
+bb18:                                             ; preds = %bb1
+  ret void
+}

Added: polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll?rev=230329&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll (added)
+++ polly/trunk/test/ScopInfo/NonAffine/non_affine_float_compare.ll Tue Feb 24 06:00:50 2015
@@ -0,0 +1,63 @@
+; RUN: opt %loadPolly -polly-scops -polly-allow-nonaffine-branches -analyze < %s | FileCheck %s
+;
+;    void f(float *A) {
+;      for (int i = 0; i < 1024; i++)
+;        if (A[i] == A[i - 1])
+;          A[i]++;
+;    }
+;
+; CHECK:    Function: f
+; CHECK:    Region: %bb1---%bb14
+; CHECK:    Max Loop Depth:  1
+; CHECK:    Statements {
+; CHECK:      Stmt_(bb2 => bb12)
+; CHECK:            Domain :=
+; CHECK:                { Stmt_(bb2 => bb12)[i0] : i0 >= 0 and i0 <= 1023 };
+; CHECK:            Scattering :=
+; CHECK:                { Stmt_(bb2 => bb12)[i0] -> [i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb12)[i0] -> MemRef_A[-1 + i0] };
+; CHECK:            ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK:            MayWriteAccess :=  [Reduction Type: NONE] [Scalar: 0]
+; CHECK:                { Stmt_(bb2 => bb12)[i0] -> MemRef_A[i0] };
+; CHECK:    }
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(float* %A) {
+bb:
+  br label %bb1
+
+bb1:                                              ; preds = %bb13, %bb
+  %indvars.iv = phi i64 [ %indvars.iv.next, %bb13 ], [ 0, %bb ]
+  %exitcond = icmp ne i64 %indvars.iv, 1024
+  br i1 %exitcond, label %bb2, label %bb14
+
+bb2:                                              ; preds = %bb1
+  %tmp = getelementptr inbounds float* %A, i64 %indvars.iv
+  %tmp3 = load float* %tmp, align 4
+  %tmp4 = add nsw i64 %indvars.iv, -1
+  %tmp5 = getelementptr inbounds float* %A, i64 %tmp4
+  %tmp6 = load float* %tmp5, align 4
+  %tmp7 = fcmp oeq float %tmp3, %tmp6
+  br i1 %tmp7, label %bb8, label %bb12
+
+bb8:                                              ; preds = %bb2
+  %tmp9 = getelementptr inbounds float* %A, i64 %indvars.iv
+  %tmp10 = load float* %tmp9, align 4
+  %tmp11 = fadd float %tmp10, 1.000000e+00
+  store float %tmp11, float* %tmp9, align 4
+  br label %bb12
+
+bb12:                                             ; preds = %bb8, %bb2
+  br label %bb13
+
+bb13:                                             ; preds = %bb12
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %bb1
+
+bb14:                                             ; preds = %bb1
+  ret void
+}





More information about the llvm-commits mailing list