[polly] r267284 - Simplify the execution context for dereferencable loads

Johannes Doerfert via llvm-commits llvm-commits at lists.llvm.org
Sat Apr 23 05:59:19 PDT 2016


Author: jdoerfert
Date: Sat Apr 23 07:59:18 2016
New Revision: 267284

URL: http://llvm.org/viewvc/llvm-project?rev=267284&view=rev
Log:
Simplify the execution context for dereferencable loads

  If we know it is safe to execute a load we do not need an execution
  context, however only if we are sure it was modeled correctly.


Added:
    polly/trunk/test/ScopInfo/non-precise-inv-load-4.ll
    polly/trunk/test/ScopInfo/non-precise-inv-load-5.ll
Modified:
    polly/trunk/include/polly/ScopInfo.h
    polly/trunk/lib/Analysis/ScopInfo.cpp
    polly/trunk/test/ScopInfo/error-blocks-2.ll
    polly/trunk/test/ScopInfo/invariant_loop_bounds.ll
    polly/trunk/test/ScopInfo/required-invariant-loop-bounds.ll

Modified: polly/trunk/include/polly/ScopInfo.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/include/polly/ScopInfo.h?rev=267284&r1=267283&r2=267284&view=diff
==============================================================================
--- polly/trunk/include/polly/ScopInfo.h (original)
+++ polly/trunk/include/polly/ScopInfo.h Sat Apr 23 07:59:18 2016
@@ -794,6 +794,9 @@ public:
   /// @brief Return the access instruction of this memory access.
   Instruction *getAccessInstruction() const { return AccessInstruction; }
 
+  /// @brief Return the number of access function subscript.
+  unsigned getNumSubscripts() const { return Subscripts.size(); }
+
   /// @brief Return the access function subscript in the dimension @p Dim.
   const SCEV *getSubscript(unsigned Dim) const { return Subscripts[Dim]; }
 

Modified: polly/trunk/lib/Analysis/ScopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/Analysis/ScopInfo.cpp?rev=267284&r1=267283&r2=267284&view=diff
==============================================================================
--- polly/trunk/lib/Analysis/ScopInfo.cpp (original)
+++ polly/trunk/lib/Analysis/ScopInfo.cpp Sat Apr 23 07:59:18 2016
@@ -32,6 +32,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/Loads.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopIterator.h"
 #include "llvm/Analysis/RegionIterator.h"
@@ -3171,12 +3172,37 @@ const InvariantEquivClassTy *Scop::looku
   return nullptr;
 }
 
+/// @brief Check if @p MA can always be hoisted without execution context.
+static bool canAlwaysBeHoisted(MemoryAccess *MA, bool StmtInvalidCtxIsEmpty) {
+  LoadInst *LInst = cast<LoadInst>(MA->getAccessInstruction());
+  const DataLayout &DL = LInst->getParent()->getModule()->getDataLayout();
+  // TODO: We can provide more information for better but more expensive
+  //       results.
+  if (!isDereferenceableAndAlignedPointer(LInst->getPointerOperand(),
+                                          LInst->getAlignment(), DL))
+    return false;
+
+  // If a dereferencable load is in a statement that is modeled precisely we can
+  // hoist it.
+  if (StmtInvalidCtxIsEmpty)
+    return true;
+
+  // Even if the statement is not modeled precisely we can hoist the load if it
+  // does not involve any parameters that might have been specilized by the
+  // statement domain.
+  for (unsigned u = 0, e = MA->getNumSubscripts(); u < e; u++)
+    if (!isa<SCEVConstant>(MA->getSubscript(u)))
+      return false;
+  return true;
+}
+
 void Scop::addInvariantLoads(ScopStmt &Stmt, MemoryAccessList &InvMAs) {
 
   if (InvMAs.empty())
     return;
 
   auto *StmtInvalidCtx = Stmt.getInvalidContext();
+  bool StmtInvalidCtxIsEmpty = isl_set_is_empty(StmtInvalidCtx);
 
   // Get the context under which the statement is executed but remove the error
   // context under which this statement is reached.
@@ -3222,6 +3248,15 @@ void Scop::addInvariantLoads(ScopStmt &S
     Type *Ty = LInst->getType();
     const SCEV *PointerSCEV = SE->getSCEV(LInst->getPointerOperand());
 
+    isl_set *MACtx;
+    // Check if we know that this pointer can be speculatively accessed.
+    if (canAlwaysBeHoisted(MA, StmtInvalidCtxIsEmpty)) {
+      MACtx = isl_set_universe(isl_set_get_space(DomainCtx));
+    } else {
+      MACtx = isl_set_copy(DomainCtx);
+      MACtx = isl_set_gist_params(MACtx, getContext());
+    }
+
     bool Consolidated = false;
     for (auto &IAClass : InvariantEquivClasses) {
       if (PointerSCEV != std::get<0>(IAClass) || Ty != std::get<3>(IAClass))
@@ -3254,10 +3289,10 @@ void Scop::addInvariantLoads(ScopStmt &S
       // Unify the execution context of the class and this statement.
       isl_set *&IAClassDomainCtx = std::get<2>(IAClass);
       if (IAClassDomainCtx)
-        IAClassDomainCtx = isl_set_coalesce(
-            isl_set_union(IAClassDomainCtx, isl_set_copy(DomainCtx)));
+        IAClassDomainCtx =
+            isl_set_coalesce(isl_set_union(IAClassDomainCtx, MACtx));
       else
-        IAClassDomainCtx = isl_set_copy(DomainCtx);
+        IAClassDomainCtx = MACtx;
       break;
     }
 
@@ -3266,8 +3301,8 @@ void Scop::addInvariantLoads(ScopStmt &S
 
     // If we did not consolidate MA, thus did not find an equivalence class
     // for it, we create a new one.
-    InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA},
-                                       isl_set_copy(DomainCtx), Ty);
+    InvariantEquivClasses.emplace_back(PointerSCEV, MemoryAccessList{MA}, MACtx,
+                                       Ty);
   }
 
   isl_set_free(DomainCtx);

Modified: polly/trunk/test/ScopInfo/error-blocks-2.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/error-blocks-2.ll?rev=267284&r1=267283&r2=267284&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/error-blocks-2.ll (original)
+++ polly/trunk/test/ScopInfo/error-blocks-2.ll Sat Apr 23 07:59:18 2016
@@ -6,10 +6,10 @@
 ; CHECK-NEXT:            Execution Context: [N, valid_val] -> {  : N > 0 }
 ; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:                [N, valid_val] -> { Stmt_S[i0] -> MemRef_ptr_addr[0] };
-; CHECK-NEXT:            Execution Context: [N, valid_val] -> {  : N > 0 and (valid_val < 0 or valid_val > 0) }
+; CHECK-NEXT:            Execution Context: [N, valid_val] -> { : }
 ; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:                [N, valid_val] -> { Stmt_S[i0] -> MemRef_tmp2[0] };
-; CHECK-NEXT:            Execution Context: [N, valid_val] -> {  : N > 0 and (valid_val < 0 or valid_val > 0) }
+; CHECK-NEXT:            Execution Context: [N, valid_val] -> { : N > 0 and (valid_val < 0 or valid_val > 0) }
 ; CHECK-NEXT:    }
 ; CHECK-NEXT:    Context:
 ; CHECK-NEXT:    [N, valid_val] -> {  : -2147483648 <= N <= 2147483647 and -2147483648 <= valid_val <= 2147483647 }

Modified: polly/trunk/test/ScopInfo/invariant_loop_bounds.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/invariant_loop_bounds.ll?rev=267284&r1=267283&r2=267284&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/invariant_loop_bounds.ll (original)
+++ polly/trunk/test/ScopInfo/invariant_loop_bounds.ll Sat Apr 23 07:59:18 2016
@@ -6,10 +6,10 @@
 ; CHECK-NEXT:         Execution Context: [bounds2, bounds1, bounds0] -> {  :  }
 ; CHECK-NEXT:         ReadAccess :=    [Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:             [bounds2, bounds1, bounds0] -> { Stmt_for_cond_1[i0, i1] -> MemRef_bounds[1] };
-; CHECK-NEXT:         Execution Context: [bounds2, bounds1, bounds0] -> {  : bounds2 > 0 }
+; CHECK-NEXT:         Execution Context: [bounds2, bounds1, bounds0] -> {  :  }
 ; CHECK-NEXT:         ReadAccess :=    [Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:             [bounds2, bounds1, bounds0] -> { Stmt_for_cond_4[i0, i1, i2] -> MemRef_bounds[0] };
-; CHECK-NEXT:         Execution Context: [bounds2, bounds1, bounds0] -> {  : bounds2 > 0 and bounds1 > 0 }
+; CHECK-NEXT:         Execution Context: [bounds2, bounds1, bounds0] -> {  :  }
 ; CHECK-NEXT: }
 ;
 ; CHECK:      p0: %bounds2

Added: polly/trunk/test/ScopInfo/non-precise-inv-load-4.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/non-precise-inv-load-4.ll?rev=267284&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/non-precise-inv-load-4.ll (added)
+++ polly/trunk/test/ScopInfo/non-precise-inv-load-4.ll Sat Apr 23 07:59:18 2016
@@ -0,0 +1,54 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; Verify we hoist I[0] without execution context even though it
+; is executed in a statement with an invalid domain.
+;
+; 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] -> {  :  }
+; CHECK-NEXT:    }
+;
+;    int I[1];
+;    void f(int *A, unsigned char c) {
+;      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"
+
+ at I = common global [1 x i32] zeroinitializer, align 4
+
+define void @f(i32* %A, i8 zeroext %c) {
+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* getelementptr inbounds ([1 x i32], [1 x i32]* @I, i64 0, i64 0), align 4
+  %arrayidx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %tmp1 = load i32, i32* %arrayidx, align 4
+  %add5 = add nsw i32 %tmp1, %tmp
+  store i32 %add5, i32* %arrayidx, 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
+}

Added: polly/trunk/test/ScopInfo/non-precise-inv-load-5.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/non-precise-inv-load-5.ll?rev=267284&view=auto
==============================================================================
--- polly/trunk/test/ScopInfo/non-precise-inv-load-5.ll (added)
+++ polly/trunk/test/ScopInfo/non-precise-inv-load-5.ll Sat Apr 23 07:59:18 2016
@@ -0,0 +1,56 @@
+; RUN: opt %loadPolly -polly-scops -analyze < %s | FileCheck %s
+;
+; Verify we do not hoist I[c] without execution context because it
+; is executed in a statement with an invalid domain and it depends
+; on a parameter that was specialized by the domain.
+;
+; CHECK:         Invariant Accesses: {
+; CHECK-NEXT:            ReadAccess :=	[Reduction Type: NONE] [Scalar: 0]
+; CHECK-NEXT:                [c] -> { Stmt_if_then[i0] -> MemRef_I[-129] };
+; CHECK-NEXT:            Execution Context: [c] -> {  : 1 = 0 }
+; CHECK-NEXT:    }
+;
+;    int I[1024];
+;    void f(int *A, unsigned char c) {
+;      for (int i = 0; i < 10; i++)
+;        if ((signed char)(c + (unsigned char)1) == 127)
+;          A[i] += I[c];
+;    }
+;
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+ at I = common global [1024 x i32] zeroinitializer, align 16
+
+define void @f(i32* %A, i8 zeroext %c) {
+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 eq i8 %add, 128
+  br i1 %cmp3, label %if.then, label %if.end
+
+if.then:                                          ; preds = %for.body
+  %arrayidx = getelementptr inbounds [1024 x i32], [1024 x i32]* @I, i64 0, i8 %c
+  %tmp = load i32, i32* %arrayidx, align 4
+  %arrayidx6 = getelementptr inbounds i32, i32* %A, i64 %indvars.iv
+  %tmp1 = load i32, i32* %arrayidx6, align 4
+  %add7 = add nsw i32 %tmp1, %tmp
+  store i32 %add7, i32* %arrayidx6, 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
+}

Modified: polly/trunk/test/ScopInfo/required-invariant-loop-bounds.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/ScopInfo/required-invariant-loop-bounds.ll?rev=267284&r1=267283&r2=267284&view=diff
==============================================================================
--- polly/trunk/test/ScopInfo/required-invariant-loop-bounds.ll (original)
+++ polly/trunk/test/ScopInfo/required-invariant-loop-bounds.ll Sat Apr 23 07:59:18 2016
@@ -6,7 +6,7 @@
 ; CHECK-NEXT: Execution Context: [bounds0, bounds1] -> {  :  }
 ; CHECK-NEXT:       ReadAccess := [Reduction Type: NONE] [Scalar: 0]
 ; CHECK-NEXT:         MemRef_bounds[1]
-; CHECK-NEXT: Execution Context: [bounds0, bounds1] -> {  : bounds0 >= 0 }
+; CHECK-NEXT: Execution Context: [bounds0, bounds1] -> {  :  }
 ; CHECK:      }
 
 ;    double A[1000][1000];




More information about the llvm-commits mailing list