[polly] r267288 - Translate SCEVs to isl_pw_aff and their invalid domain

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 23 07:31:18 PDT 2016


Author: jdoerfert
Date: Sat Apr 23 09:31:17 2016
New Revision: 267288

URL: http://llvm.org/viewvc/llvm-project?rev=267288&view=rev
Log:
Translate SCEVs to isl_pw_aff and their invalid domain

  The SCEVAffinator will now produce not only the isl representaiton of
  a SCEV but also the domain under which it is invalid. This is used to
  record possible overflows that can happen in the statement domains in
  the statements invalid domain. The result is that invalid loads have
  an accurate execution contexts with regards to the validity of their
  statements domain. While the SCEVAffinator currently is only taking
  "no-wrapping" assumptions, we can add more withouth worrying about the
  execution context of loads that are optimistically hoisted.


Added:
    polly/trunk/test/ScopInfo/non-precise-inv-load-3.ll
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/include/polly/Support/SCEVAffinator.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Support/SCEVAffinator.cpp

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=267288&r1=267287&r2=267288&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Sat Apr 23 09:31:17 2016
@@ -1246,6 +1246,8 @@ public:
   void restrictDomain(__isl_take isl_set *NewDomain);
 
   /// @brief Compute the isl representation for the SCEV @p E in this stmt.
+  ///
+  /// Note that this function will also adjust the invalid context accordingly.
   __isl_give isl_pw_aff *getPwAff(const SCEV *E);
 
   /// @brief Get the loop for a dimension.
@@ -2130,7 +2132,13 @@ public:
   /// the translation of @p E was deemed to complex the SCoP is invalidated and
   /// a dummy value of appropriate dimension is returned. This allows to bail
   /// for complex cases without "error handling code" needed on the users side.
-  __isl_give isl_pw_aff *getPwAff(const SCEV *E, BasicBlock *BB = nullptr);
+  __isl_give PWACtx getPwAff(const SCEV *E, BasicBlock *BB = nullptr);
+
+  /// @brief 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_give isl_pw_aff *getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr);
 
   /// @brief Return the domain of @p Stmt.
   ///

Modified: polly/trunk/include/polly/Support/SCEVAffinator.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/SCEVAffinator.h?rev=267288&r1=267287&r2=267288&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/SCEVAffinator.h (original)
+++ polly/trunk/include/polly/Support/SCEVAffinator.h Sat Apr 23 09:31:17 2016
@@ -43,8 +43,14 @@ namespace polly {
 class Scop;
 class ScopStmt;
 
-/// Translate a SCEV to an isl_pw_aff.
-struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, isl_pw_aff *> {
+/// @brief The result type of the SCEVAffinator.
+///
+/// The first element of the pair is the isl representation of the SCEV, the
+/// second is the domain under which it is __invalid__.
+typedef std::pair<isl_pw_aff *, isl_set *> PWACtx;
+
+/// Translate a SCEV to an isl_pw_aff and the domain on which it is invalid.
+struct SCEVAffinator : public llvm::SCEVVisitor<SCEVAffinator, PWACtx> {
 public:
   SCEVAffinator(Scop *S, llvm::LoopInfo &LI);
   ~SCEVAffinator();
@@ -55,16 +61,8 @@ public:
   /// @param BB The block in which @p E is executed.
   ///
   /// @returns The isl representation of the SCEV @p E in @p Domain.
-  __isl_give isl_pw_aff *getPwAff(const llvm::SCEV *E,
-                                  llvm::BasicBlock *BB = nullptr);
-
-  /// @brief Compute the context in which integer wrapping is happending.
-  ///
-  /// This context contains all parameter configurations for which we
-  /// know that the wrapping and non-wrapping expressions are different.
-  ///
-  /// @returns The context in which integer wrapping is happening.
-  __isl_give isl_set *getWrappingContext() const;
+  __isl_give PWACtx getPwAff(const llvm::SCEV *E,
+                             llvm::BasicBlock *BB = nullptr);
 
   /// @brief Check an <nsw> AddRec for the loop @p L is cached.
   bool hasNSWAddRecForLoop(llvm::Loop *L) const;
@@ -74,7 +72,7 @@ private:
   using CacheKey = std::pair<const llvm::SCEV *, llvm::BasicBlock *>;
 
   /// @brief Map to remembered cached expressions.
-  llvm::DenseMap<CacheKey, isl_pw_aff *> CachedExpressions;
+  llvm::DenseMap<CacheKey, PWACtx> CachedExpressions;
 
   Scop *S;
   isl_ctx *Ctx;
@@ -87,6 +85,9 @@ private:
   /// @brief Target data for element size computing.
   const llvm::DataLayout &TD;
 
+  /// @brief Return a PWACtx for @p PWA that is always valid.
+  __isl_give PWACtx getPWACtxFromPWA(__isl_take isl_pw_aff *PWA);
+
   /// @brief Compute the non-wrapping version of @p PWA for type @p ExprType.
   ///
   /// @param PWA  The piece-wise affine function that might wrap.
@@ -99,26 +100,27 @@ private:
   /// @brief If @p Expr might cause an integer wrap record an assumption.
   ///
   /// @param Expr The SCEV expression that might wrap.
-  /// @param PWA  The isl representation of @p Expr.
-  void checkForWrapping(const llvm::SCEV *Expr,
-                        __isl_keep isl_pw_aff *PWA) const;
-
-  __isl_give isl_pw_aff *visit(const llvm::SCEV *E);
-  __isl_give isl_pw_aff *visitConstant(const llvm::SCEVConstant *E);
-  __isl_give isl_pw_aff *visitTruncateExpr(const llvm::SCEVTruncateExpr *E);
-  __isl_give isl_pw_aff *visitZeroExtendExpr(const llvm::SCEVZeroExtendExpr *E);
-  __isl_give isl_pw_aff *visitSignExtendExpr(const llvm::SCEVSignExtendExpr *E);
-  __isl_give isl_pw_aff *visitAddExpr(const llvm::SCEVAddExpr *E);
-  __isl_give isl_pw_aff *visitMulExpr(const llvm::SCEVMulExpr *E);
-  __isl_give isl_pw_aff *visitUDivExpr(const llvm::SCEVUDivExpr *E);
-  __isl_give isl_pw_aff *visitAddRecExpr(const llvm::SCEVAddRecExpr *E);
-  __isl_give isl_pw_aff *visitSMaxExpr(const llvm::SCEVSMaxExpr *E);
-  __isl_give isl_pw_aff *visitUMaxExpr(const llvm::SCEVUMaxExpr *E);
-  __isl_give isl_pw_aff *visitUnknown(const llvm::SCEVUnknown *E);
-  __isl_give isl_pw_aff *visitSDivInstruction(llvm::Instruction *SDiv);
-  __isl_give isl_pw_aff *visitSRemInstruction(llvm::Instruction *SRem);
+  /// @param PWAC The isl representation of @p Expr with the invalid domain.
+  ///
+  /// @returns The isl representation @p PWAC with a posisbly adjusted domain.
+  __isl_give PWACtx checkForWrapping(const llvm::SCEV *Expr, PWACtx PWAC) const;
+
+  __isl_give PWACtx visit(const llvm::SCEV *E);
+  __isl_give PWACtx visitConstant(const llvm::SCEVConstant *E);
+  __isl_give PWACtx visitTruncateExpr(const llvm::SCEVTruncateExpr *E);
+  __isl_give PWACtx visitZeroExtendExpr(const llvm::SCEVZeroExtendExpr *E);
+  __isl_give PWACtx visitSignExtendExpr(const llvm::SCEVSignExtendExpr *E);
+  __isl_give PWACtx visitAddExpr(const llvm::SCEVAddExpr *E);
+  __isl_give PWACtx visitMulExpr(const llvm::SCEVMulExpr *E);
+  __isl_give PWACtx visitUDivExpr(const llvm::SCEVUDivExpr *E);
+  __isl_give PWACtx visitAddRecExpr(const llvm::SCEVAddRecExpr *E);
+  __isl_give PWACtx visitSMaxExpr(const llvm::SCEVSMaxExpr *E);
+  __isl_give PWACtx visitUMaxExpr(const llvm::SCEVUMaxExpr *E);
+  __isl_give PWACtx visitUnknown(const llvm::SCEVUnknown *E);
+  __isl_give PWACtx visitSDivInstruction(llvm::Instruction *SDiv);
+  __isl_give PWACtx visitSRemInstruction(llvm::Instruction *SRem);
 
-  friend struct llvm::SCEVVisitor<SCEVAffinator, isl_pw_aff *>;
+  friend struct llvm::SCEVVisitor<SCEVAffinator, PWACtx>;
 };
 }
 

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=267288&r1=267287&r2=267288&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sat Apr 23 09:31:17 2016
@@ -225,7 +225,7 @@ bool ScopArrayInfo::updateSizes(ArrayRef
     isl_pw_aff_free(Size);
   DimensionSizesPw.clear();
   for (const SCEV *Expr : DimensionSizes) {
-    isl_pw_aff *Size = S.getPwAff(Expr);
+    isl_pw_aff *Size = S.getPwAffOnly(Expr);
     DimensionSizesPw.push_back(Size);
   }
   return true;
@@ -922,7 +922,7 @@ void MemoryAccess::dump() const { print(
 
 __isl_give isl_pw_aff *MemoryAccess::getPwAff(const SCEV *E) {
   auto *Stmt = getStatement();
-  return Stmt->getParent()->getPwAff(E, Stmt->getEntryBlock());
+  return Stmt->getParent()->getPwAffOnly(E, Stmt->getEntryBlock());
 }
 
 // Create a map in the size of the provided set domain, that maps from the
@@ -1035,7 +1035,9 @@ __isl_give isl_map *ScopStmt::getSchedul
 }
 
 __isl_give isl_pw_aff *ScopStmt::getPwAff(const SCEV *E) {
-  return getParent()->getPwAff(E, getEntryBlock());
+  PWACtx PWAC = getParent()->getPwAff(E, getEntryBlock());
+  InvalidDomain = isl_set_union(InvalidDomain, PWAC.second);
+  return PWAC.first;
 }
 
 void ScopStmt::restrictDomain(__isl_take isl_set *NewDomain) {
@@ -2345,7 +2347,7 @@ void Scop::propagateInvalidStmtDomains(R
     }
 
     if (isl_set_is_empty(InvalidDomain)) {
-      isl_set_free(InvalidDomain);
+      Stmt->setInvalidDomain(InvalidDomain);
       continue;
     }
 
@@ -3711,15 +3713,15 @@ void Scop::dump() const { print(dbgs());
 
 isl_ctx *Scop::getIslCtx() const { return IslCtx.get(); }
 
-__isl_give isl_pw_aff *Scop::getPwAff(const SCEV *E, BasicBlock *BB) {
+__isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB) {
   // 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 cdoe to all users of this function.
-  auto *PWA = Affinator.getPwAff(E, BB);
-  if (PWA)
-    return PWA;
+  auto PWAC = Affinator.getPwAff(E, BB);
+  if (PWAC.first)
+    return PWAC;
 
   auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
   invalidate(COMPLEXITY, DL);
@@ -3735,6 +3737,12 @@ __isl_give isl_union_set *Scop::getDomai
   return Domain;
 }
 
+__isl_give isl_pw_aff *Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) {
+  PWACtx PWAC = getPwAff(E, BB);
+  isl_set_free(PWAC.second);
+  return PWAC.first;
+}
+
 __isl_give isl_union_map *
 Scop::getAccessesOfType(std::function<bool(MemoryAccess &)> Predicate) {
   isl_union_map *Accesses = isl_union_map_empty(getParamSpace());

Modified: polly/trunk/lib/Support/SCEVAffinator.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/SCEVAffinator.cpp?rev=267288&r1=267287&r2=267288&view=diff
==============================================================================
--- polly/trunk/lib/Support/SCEVAffinator.cpp (original)
+++ polly/trunk/lib/Support/SCEVAffinator.cpp Sat Apr 23 09:31:17 2016
@@ -45,16 +45,27 @@ static isl_stat addNumBasicSets(isl_set
   return isl_stat_ok;
 }
 
-/// @brief Determine if @p PWA is to complex to continue
+/// @brief Helper to free a PWACtx object.
+static void freePWACtx(__isl_take PWACtx &PWAC) {
+  isl_pw_aff_free(PWAC.first);
+  isl_set_free(PWAC.second);
+}
+
+/// @brief Helper to copy a PWACtx object.
+static __isl_give PWACtx copyPWACtx(const __isl_keep PWACtx &PWAC) {
+  return std::make_pair(isl_pw_aff_copy(PWAC.first), isl_set_copy(PWAC.second));
+}
+
+/// @brief Determine if @p PWAC is to complex to continue
 ///
-/// Note that @p PWA will be "free" (deallocated) if this function returns true,
-/// but not if this function returns false.
-static bool isToComplex(isl_pw_aff *PWA) {
+/// Note that @p PWAC will be "free" (deallocated) if this function returns
+/// true, but not if this function returns false.
+static bool isToComplex(PWACtx &PWAC) {
   unsigned NumBasicSets = 0;
-  isl_pw_aff_foreach_piece(PWA, addNumBasicSets, &NumBasicSets);
+  isl_pw_aff_foreach_piece(PWAC.first, addNumBasicSets, &NumBasicSets);
   if (NumBasicSets <= MaxConjunctsInPwAff)
     return false;
-  isl_pw_aff_free(PWA);
+  freePWACtx(PWAC);
   return true;
 }
 
@@ -65,17 +76,27 @@ static SCEV::NoWrapFlags getNoWrapFlags(
   return SCEV::NoWrapMask;
 }
 
+static void combine(__isl_keep PWACtx &PWAC0, const __isl_take PWACtx &PWAC1,
+                    isl_pw_aff *(Fn)(isl_pw_aff *, isl_pw_aff *)) {
+  PWAC0.first = Fn(PWAC0.first, PWAC1.first);
+  PWAC0.second = isl_set_union(PWAC0.second, PWAC1.second);
+}
+
 SCEVAffinator::SCEVAffinator(Scop *S, LoopInfo &LI)
     : S(S), Ctx(S->getIslCtx()), R(S->getRegion()), SE(*S->getSE()), LI(LI),
       TD(R.getEntry()->getParent()->getParent()->getDataLayout()) {}
 
 SCEVAffinator::~SCEVAffinator() {
-  for (const auto &CachedPair : CachedExpressions)
-    isl_pw_aff_free(CachedPair.second);
+  for (auto &CachedPair : CachedExpressions)
+    freePWACtx(CachedPair.second);
+}
+
+__isl_give PWACtx SCEVAffinator::getPWACtxFromPWA(__isl_take isl_pw_aff *PWA) {
+  return std::make_pair(
+      PWA, isl_set_empty(isl_space_set_alloc(Ctx, 0, NumIterators)));
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::getPwAff(const SCEV *Expr,
-                                               BasicBlock *BB) {
+__isl_give PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB) {
   this->BB = BB;
 
   if (BB) {
@@ -91,8 +112,8 @@ __isl_give isl_pw_aff *SCEVAffinator::ge
   return visit(Expr);
 }
 
-void SCEVAffinator::checkForWrapping(const SCEV *Expr,
-                                     __isl_keep isl_pw_aff *PWA) const {
+__isl_give PWACtx SCEVAffinator::checkForWrapping(const SCEV *Expr,
+                                                  PWACtx PWAC) const {
   // If the SCEV flags do contain NSW (no signed wrap) then PWA already
   // represents Expr in modulo semantic (it is not allowed to overflow), thus we
   // are done. Otherwise, we will compute:
@@ -101,10 +122,12 @@ void SCEVAffinator::checkForWrapping(con
   //   n = bitwidth(ExprType)
 
   if (IgnoreIntegerWrapping || (getNoWrapFlags(Expr) & SCEV::FlagNSW))
-    return;
+    return PWAC;
 
+  auto *PWA = PWAC.first;
   auto *PWAMod = addModuloSemantic(isl_pw_aff_copy(PWA), Expr->getType());
   auto *NotEqualSet = isl_pw_aff_ne_set(isl_pw_aff_copy(PWA), PWAMod);
+  PWAC.second = isl_set_union(PWAC.second, isl_set_copy(NotEqualSet));
 
   const DebugLoc &Loc = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
   NotEqualSet = BB ? NotEqualSet : isl_set_params(NotEqualSet);
@@ -113,6 +136,8 @@ void SCEVAffinator::checkForWrapping(con
     isl_set_free(NotEqualSet);
   else
     S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB);
+
+  return PWAC;
 }
 
 __isl_give isl_pw_aff *
@@ -152,12 +177,12 @@ bool SCEVAffinator::hasNSWAddRecForLoop(
   return false;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
+__isl_give PWACtx SCEVAffinator::visit(const SCEV *Expr) {
 
   auto Key = std::make_pair(Expr, BB);
-  isl_pw_aff *PWA = CachedExpressions[Key];
-  if (PWA)
-    return isl_pw_aff_copy(PWA);
+  PWACtx PWAC = CachedExpressions[Key];
+  if (PWAC.first)
+    return copyPWACtx(PWAC);
 
   auto ConstantAndLeftOverPair = extractConstantFactor(Expr, *S->getSE());
   auto *Factor = ConstantAndLeftOverPair.first;
@@ -175,24 +200,24 @@ __isl_give isl_pw_aff *SCEVAffinator::vi
     isl_aff *Affine = isl_aff_zero_on_domain(isl_local_space_from_space(Space));
     Affine = isl_aff_add_coefficient_si(Affine, isl_dim_param, 0, 1);
 
-    PWA = isl_pw_aff_alloc(Domain, Affine);
+    PWAC = getPWACtxFromPWA(isl_pw_aff_alloc(Domain, Affine));
   } else {
-    PWA = SCEVVisitor<SCEVAffinator, isl_pw_aff *>::visit(Expr);
-    checkForWrapping(Expr, PWA);
+    PWAC = SCEVVisitor<SCEVAffinator, PWACtx>::visit(Expr);
+    PWAC = checkForWrapping(Expr, PWAC);
   }
 
-  PWA = isl_pw_aff_mul(visitConstant(Factor), PWA);
+  combine(PWAC, visitConstant(Factor), isl_pw_aff_mul);
 
-  // For compile time reasons we need to simplify the PWA before we cache and
+  // For compile time reasons we need to simplify the PWAC before we cache and
   // return it.
-  PWA = isl_pw_aff_coalesce(PWA);
-  checkForWrapping(Key.first, PWA);
+  PWAC.first = isl_pw_aff_coalesce(PWAC.first);
+  PWAC = checkForWrapping(Key.first, PWAC);
 
-  CachedExpressions[Key] = isl_pw_aff_copy(PWA);
-  return PWA;
+  CachedExpressions[Key] = copyPWACtx(PWAC);
+  return PWAC;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
+__isl_give PWACtx SCEVAffinator::visitConstant(const SCEVConstant *Expr) {
   ConstantInt *Value = Expr->getValue();
   isl_val *v;
 
@@ -210,58 +235,55 @@ __isl_give isl_pw_aff *SCEVAffinator::vi
 
   isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
   isl_local_space *ls = isl_local_space_from_space(Space);
-  return isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v));
+  return getPWACtxFromPWA(isl_pw_aff_from_aff(isl_aff_val_on_domain(ls, v)));
 }
 
-__isl_give isl_pw_aff *
+__isl_give PWACtx
 SCEVAffinator::visitTruncateExpr(const SCEVTruncateExpr *Expr) {
   llvm_unreachable("SCEVTruncateExpr not yet supported");
 }
 
-__isl_give isl_pw_aff *
+__isl_give PWACtx
 SCEVAffinator::visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
   llvm_unreachable("SCEVZeroExtendExpr not yet supported");
 }
 
-__isl_give isl_pw_aff *
+__isl_give PWACtx
 SCEVAffinator::visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
   // Assuming the value is signed, a sign extension is basically a noop.
   // TODO: Reconsider this as soon as we support unsigned values.
   return visit(Expr->getOperand());
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
-  isl_pw_aff *Sum = visit(Expr->getOperand(0));
+__isl_give PWACtx SCEVAffinator::visitAddExpr(const SCEVAddExpr *Expr) {
+  PWACtx Sum = visit(Expr->getOperand(0));
 
   for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
-    isl_pw_aff *NextSummand = visit(Expr->getOperand(i));
-    Sum = isl_pw_aff_add(Sum, NextSummand);
+    combine(Sum, visit(Expr->getOperand(i)), isl_pw_aff_add);
     if (isToComplex(Sum))
-      return nullptr;
+      return std::make_pair(nullptr, nullptr);
   }
 
   return Sum;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
-  isl_pw_aff *Prod = visit(Expr->getOperand(0));
+__isl_give PWACtx SCEVAffinator::visitMulExpr(const SCEVMulExpr *Expr) {
+  PWACtx Prod = visit(Expr->getOperand(0));
 
   for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
-    isl_pw_aff *NextFactor = visit(Expr->getOperand(i));
-    Prod = isl_pw_aff_mul(Prod, NextFactor);
+    combine(Prod, visit(Expr->getOperand(i)), isl_pw_aff_mul);
     if (isToComplex(Prod))
-      return nullptr;
+      return std::make_pair(nullptr, nullptr);
   }
 
   return Prod;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
+__isl_give PWACtx SCEVAffinator::visitUDivExpr(const SCEVUDivExpr *Expr) {
   llvm_unreachable("SCEVUDivExpr not yet supported");
 }
 
-__isl_give isl_pw_aff *
-SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
+__isl_give PWACtx SCEVAffinator::visitAddRecExpr(const SCEVAddRecExpr *Expr) {
   assert(Expr->isAffine() && "Only affine AddRecurrences allowed");
 
   auto Flags = Expr->getNoWrapFlags();
@@ -271,7 +293,7 @@ SCEVAffinator::visitAddRecExpr(const SCE
     assert(S->getRegion().contains(Expr->getLoop()) &&
            "Scop does not contain the loop referenced in this AddRec");
 
-    isl_pw_aff *Step = visit(Expr->getOperand(1));
+    PWACtx Step = visit(Expr->getOperand(1));
     isl_space *Space = isl_space_set_alloc(Ctx, 0, NumIterators);
     isl_local_space *LocalSpace = isl_local_space_from_space(Space);
 
@@ -281,7 +303,8 @@ SCEVAffinator::visitAddRecExpr(const SCE
         isl_aff_zero_on_domain(LocalSpace), isl_dim_in, loopDimension, 1);
     isl_pw_aff *LPwAff = isl_pw_aff_from_aff(LAff);
 
-    return isl_pw_aff_mul(Step, LPwAff);
+    Step.first = isl_pw_aff_mul(Step.first, LPwAff);
+    return Step;
   }
 
   // Translate AddRecExpr from '{start, +, inc}' into 'start + {0, +, inc}'
@@ -294,46 +317,46 @@ SCEVAffinator::visitAddRecExpr(const SCE
       SE.getAddRecExpr(SE.getConstant(Expr->getStart()->getType(), 0),
                        Expr->getStepRecurrence(SE), Expr->getLoop(), Flags);
 
-  isl_pw_aff *ZeroStartResult = visit(ZeroStartExpr);
-  isl_pw_aff *Start = visit(Expr->getStart());
-
-  return isl_pw_aff_add(ZeroStartResult, Start);
+  PWACtx Result = visit(ZeroStartExpr);
+  PWACtx Start = visit(Expr->getStart());
+  combine(Result, Start, isl_pw_aff_add);
+  return Result;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) {
-  isl_pw_aff *Max = visit(Expr->getOperand(0));
+__isl_give PWACtx SCEVAffinator::visitSMaxExpr(const SCEVSMaxExpr *Expr) {
+  PWACtx Max = visit(Expr->getOperand(0));
 
   for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) {
-    isl_pw_aff *NextOperand = visit(Expr->getOperand(i));
-    Max = isl_pw_aff_max(Max, NextOperand);
+    combine(Max, visit(Expr->getOperand(i)), isl_pw_aff_max);
     if (isToComplex(Max))
-      return nullptr;
+      return std::make_pair(nullptr, nullptr);
   }
 
   return Max;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
+__isl_give PWACtx SCEVAffinator::visitUMaxExpr(const SCEVUMaxExpr *Expr) {
   llvm_unreachable("SCEVUMaxExpr not yet supported");
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
+__isl_give PWACtx SCEVAffinator::visitSDivInstruction(Instruction *SDiv) {
   assert(SDiv->getOpcode() == Instruction::SDiv && "Assumed SDiv instruction!");
   auto *SE = S->getSE();
 
   auto *Divisor = SDiv->getOperand(1);
   auto *DivisorSCEV = SE->getSCEV(Divisor);
-  auto *DivisorPWA = visit(DivisorSCEV);
+  auto DivisorPWAC = visit(DivisorSCEV);
   assert(isa<ConstantInt>(Divisor) &&
          "SDiv is no parameter but has a non-constant RHS.");
 
   auto *Dividend = SDiv->getOperand(0);
   auto *DividendSCEV = SE->getSCEV(Dividend);
-  auto *DividendPWA = visit(DividendSCEV);
-  return isl_pw_aff_tdiv_q(DividendPWA, DivisorPWA);
+  auto DividendPWAC = visit(DividendSCEV);
+  combine(DividendPWAC, DivisorPWAC, isl_pw_aff_tdiv_q);
+  return DividendPWAC;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
+__isl_give PWACtx SCEVAffinator::visitSRemInstruction(Instruction *SRem) {
   assert(SRem->getOpcode() == Instruction::SRem && "Assumed SRem instruction!");
   auto *SE = S->getSE();
 
@@ -344,12 +367,14 @@ __isl_give isl_pw_aff *SCEVAffinator::vi
 
   auto *Dividend = SRem->getOperand(0);
   auto *DividendSCEV = SE->getSCEV(Dividend);
-  auto *DividendPWA = visit(DividendSCEV);
+  auto DividendPWAC = visit(DividendSCEV);
 
-  return isl_pw_aff_mod_val(DividendPWA, isl_val_abs(DivisorVal));
+  DividendPWAC.first =
+      isl_pw_aff_mod_val(DividendPWAC.first, isl_val_abs(DivisorVal));
+  return DividendPWAC;
 }
 
-__isl_give isl_pw_aff *SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
+__isl_give PWACtx SCEVAffinator::visitUnknown(const SCEVUnknown *Expr) {
   if (Instruction *I = dyn_cast<Instruction>(Expr->getValue())) {
     switch (I->getOpcode()) {
     case Instruction::SDiv:

Added: polly/trunk/test/ScopInfo/non-precise-inv-load-3.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/non-precise-inv-load-3.ll?rev=267288&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/non-precise-inv-load-3.ll (added)
+++ polly/trunk/test/ScopInfo/non-precise-inv-load-3.ll Sat Apr 23 09:31:17 2016
@@ -0,0 +1,48 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; CHECK:        Invariant Accesses: {
+; CHECK-NEXT:     ReadAccess := [Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:       [c] -> { Stmt_if_then[i0] -> MemRef_I[0] };
+; CHECK-NEXT:     Execution Context: [c] -> {  : 0 <= c <= 126 }
+; CHECK-NEXT:   }
+;
+;    void f(int *A, unsigned char c, int *I) {
+;      for (int i = 0; i < 10; i++)
+;        if ((signed char)(c + (unsigned char)1) > 0)
+;          A[i] += I[0];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define void @f(i32* %A, i8 zeroext %c, i32* %I) {
+entry:
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]
+  %exitcond = icmp ne i64 %indvars.iv, 10
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.body:                                         ; preds = %for.cond
+  %add = add i8 %c, 1
+  %cmp3 = icmp sgt i8 %add, 0
+  br i1 %cmp3, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body
+  %tmp = load i32, i32* %I, align 4
+  %arrayidx5 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %tmp1 = load i32, i32* %arrayidx5, align 4
+  %add6 = add nsw i32 %tmp1, %tmp
+  store i32 %add6, i32* %arrayidx5, align 4
+  br label %if.end
+
+if.end:                                           ; preds = %if.then, %for.body
+  br label %for.inc
+
+for.inc:                                          ; preds = %if.end
+  %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end:                                          ; preds = %for.cond
+  ret void
+}




More information about the llvm-commits mailing list