[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