[polly] r248128 - Use <nsw> AddRecs in the affinator to avoid bounded assumptions

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 20 09:59:23 PDT 2015


Author: jdoerfert
Date: Sun Sep 20 11:59:23 2015
New Revision: 248128

URL: http://llvm.org/viewvc/llvm-project?rev=248128&view=rev
Log:
Use <nsw> AddRecs in the affinator to avoid bounded assumptions

  If we encounter a <nsw> tagged AddRec for a loop we know the trip count of
  that loop has to be bounded or the semantics is undefined anyway. Hence, we
  only need to add unbounded assumptions if no such AddRec is known.


Added:
    polly/trunk/test/ScopInfo/bounded_loop_assumptions.ll
Modified:
    polly/trunk/include/polly/Support/SCEVAffinator.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/lib/Support/SCEVAffinator.cpp
    polly/trunk/test/ScopInfo/phi_scalar_simple_1.ll

Modified: polly/trunk/include/polly/Support/SCEVAffinator.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/Support/SCEVAffinator.h?rev=248128&r1=248127&r2=248128&view=diff
==============================================================================
--- polly/trunk/include/polly/Support/SCEVAffinator.h (original)
+++ polly/trunk/include/polly/Support/SCEVAffinator.h Sun Sep 20 11:59:23 2015
@@ -66,6 +66,9 @@ public:
   /// @returns The context in which integer wrapping is happening.
   __isl_give isl_set *getWrappingContext() const;
 
+  /// @brief Check an <nsw> AddRec for the loop @p L is cached.
+  bool hasNSWAddRecForLoop(llvm::Loop *L) const;
+
 private:
   /// @brief Key to identify cached expressions.
   using CacheKey = std::pair<const llvm::SCEV *, llvm::BasicBlock *>;

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=248128&r1=248127&r2=248128&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sun Sep 20 11:59:23 2015
@@ -1925,6 +1925,14 @@ void Scop::addLoopBoundsToHeaderDomain(L
   auto Parts = partitionSetParts(HeaderBBDom, LoopDepth);
   HeaderBBDom = Parts.second;
 
+  // Check if there is a <nsw> tagged AddRec for this loop and if so do not add
+  // the bounded assumptions to the context as they are already implied by the
+  // <nsw> tag.
+  if (Affinator.hasNSWAddRecForLoop(L)) {
+    isl_set_free(Parts.first);
+    return;
+  }
+
   isl_set *UnboundedCtx = isl_set_params(Parts.first);
   isl_set *BoundedCtx = isl_set_complement(UnboundedCtx);
   addAssumption(BoundedCtx);

Modified: polly/trunk/lib/Support/SCEVAffinator.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Support/SCEVAffinator.cpp?rev=248128&r1=248127&r2=248128&view=diff
==============================================================================
--- polly/trunk/lib/Support/SCEVAffinator.cpp (original)
+++ polly/trunk/lib/Support/SCEVAffinator.cpp Sun Sep 20 11:59:23 2015
@@ -139,6 +139,20 @@ SCEVAffinator::addModuloSemantic(__isl_t
   return PWA;
 }
 
+bool SCEVAffinator::hasNSWAddRecForLoop(Loop *L) const {
+  for (const auto &CachedPair : CachedExpressions) {
+    auto *AddRec = dyn_cast<SCEVAddRecExpr>(CachedPair.first.first);
+    if (!AddRec)
+      continue;
+    if (AddRec->getLoop() != L)
+      continue;
+    if (AddRec->getNoWrapFlags() & SCEV::FlagNSW)
+      return true;
+  }
+
+  return false;
+}
+
 __isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) {
 
   auto Key = std::make_pair(Expr, BB);

Added: polly/trunk/test/ScopInfo/bounded_loop_assumptions.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/bounded_loop_assumptions.ll?rev=248128&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/bounded_loop_assumptions.ll (added)
+++ polly/trunk/test/ScopInfo/bounded_loop_assumptions.ll Sun Sep 20 11:59:23 2015
@@ -0,0 +1,61 @@
+; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
+;
+; The assumed context is tricky here as the equality test for the inner loop
+; allows an "unbounded" loop trip count. We assume that does not happen, thus
+; if N <= 1 the outer loop is not executed and we are done, if N >= 3 the
+; equality test in the inner exit condition will trigger at some point and,
+; finally, if N == 2 we would have an unbounded inner loop.
+;
+; CHECK:      Assumed Context:
+; CHECK-NEXT:   [N] -> {  : N >= 3 or N <= 1 }
+;
+;    int jd(int *restrict A, int x, int N) {
+;      for (int i = 1; i < N; i++)
+;        for (int j = 3; j < N; j++)
+;          x += A[i];
+;      return x;
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+define i32 @jd(i32* noalias %A, i32 %x, i32 %N) {
+entry:
+  %tmp = sext i32 %N to i64
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc4, %entry
+  %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc4 ], [ 1, %entry ]
+  %x.addr.0 = phi i32 [ %x, %entry ], [ %x.addr.1.lcssa, %for.inc4 ]
+  %cmp = icmp slt i64 %indvars.iv, %tmp
+  br i1 %cmp, label %for.body, label %for.end6
+
+for.body:                                         ; preds = %for.cond
+  br label %for.cond1
+
+for.cond1:                                        ; preds = %for.inc, %for.body
+  %x.addr.1 = phi i32 [ %x.addr.0, %for.body ], [ %add, %for.inc ]
+  %j.0 = phi i32 [ 3, %for.body ], [ %inc, %for.inc ]
+  %exitcond = icmp ne i32 %j.0, %N
+  br i1 %exitcond, label %for.body3, label %for.end
+
+for.body3:                                        ; preds = %for.cond1
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body3
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %tmp1 = load i32, i32* %arrayidx, align 4
+  %add = add nsw i32 %x.addr.1, %tmp1
+  %inc = add i32 %j.0, 1
+  br label %for.cond1
+
+for.end:                                          ; preds = %for.cond1
+  %x.addr.1.lcssa = phi i32 [ %x.addr.1, %for.cond1 ]
+  br label %for.inc4
+
+for.inc4:                                         ; preds = %for.end
+  %indvars.iv.next = add i64 %indvars.iv, 1
+  br label %for.cond
+
+for.end6:                                         ; preds = %for.cond
+  ret i32 %x.addr.0
+}

Modified: polly/trunk/test/ScopInfo/phi_scalar_simple_1.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/phi_scalar_simple_1.ll?rev=248128&r1=248127&r2=248128&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/phi_scalar_simple_1.ll (original)
+++ polly/trunk/test/ScopInfo/phi_scalar_simple_1.ll Sun Sep 20 11:59:23 2015
@@ -1,13 +1,11 @@
 ; RUN: opt %loadPolly -polly-detect-unprofitable -polly-scops -analyze < %s | FileCheck %s
 ;
-; The assumed context is tricky here as the equality test for the inner loop
-; allows an "unbounded" loop trip count. We assume that does not happen, thus
-; if N <= 1 the outer loop is not executed and we are done, if N >= 3 the
-; equality test in the inner exit condition will trigger at some point and,
-; finally, if N == 2 we would have an unbounded inner loop.
+; The assumed context should be empty since the <nsw> flags on the IV
+; increments already guarantee that there is no wrap in the loop trip
+; count.
 ;
 ; CHECK:      Assumed Context:
-; CHECK-NEXT:   [N] -> {  : N >= 3 or N <= 1 }
+; CHECK-NEXT:   [N] -> {  :  }
 ;
 ;    int jd(int *restrict A, int x, int N) {
 ;      for (int i = 1; i < N; i++)




More information about the llvm-commits mailing list