Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ScopBuilder] Introduce -polly-stmt-granularity=scalar-indep option.
The option splits BasicBlocks into minimal statements such that no additional scalar dependencies are introduced. The algorithm is based on a union-find structure, and unites sets if putting them into separate statements would introduce a scalar dependencies. As a consequence, instructions may be split into separate statements such their relative order is different than the statements they are in. This is accounted for instructions whose relative order matters (e.g. memory accesses). The algorithm is generic in that heuristic changes can be made relatively easily. We might relax the order requirement for read-reads or accesses to different base pointers. Forwardable instructions can be made to not cause a join. This implementation gives us a speed-up of 82% in SPEC 2006 456.hmmer benchmark by allowing loop-distribution in a hot loop such that one of the loops can be vectorized. Differential Revision: https://reviews.llvm.org/D38403 llvm-svn: 314983
- Loading branch information
1 parent
fc50004
commit cc345e6
Showing
7 changed files
with
517 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-scops -analyze < %s | FileCheck %s -match-full-lines | ||
; | ||
; Split a block into two independent statements that share no scalar. | ||
; This case has the instructions of the two statements interleaved, such that | ||
; splitting the BasicBlock in the middle would cause a scalar dependency. | ||
; | ||
; for (int j = 0; j < n; j += 1) { | ||
; body: | ||
; double valA = A[0]; | ||
; double valB = 21.0 + 21.0; | ||
; A[0] = valA; | ||
; B[0] = valB; | ||
; } | ||
; | ||
define void @func(i32 %n, double* noalias nonnull %A, double* noalias nonnull %B) { | ||
entry: | ||
br label %for | ||
|
||
for: | ||
%j = phi i32 [0, %entry], [%j.inc, %inc] | ||
%j.cmp = icmp slt i32 %j, %n | ||
br i1 %j.cmp, label %body, label %exit | ||
|
||
body: | ||
%valA = load double, double* %A | ||
%valB = fadd double 21.0, 21.0 | ||
store double %valA, double* %A | ||
store double %valB, double* %B | ||
br label %inc | ||
|
||
inc: | ||
%j.inc = add nuw nsw i32 %j, 1 | ||
br label %for | ||
|
||
exit: | ||
br label %return | ||
|
||
return: | ||
ret void | ||
} | ||
|
||
|
||
; CHECK: Statements { | ||
; CHECK-NEXT: Stmt_body | ||
; CHECK-NEXT: Domain := | ||
; CHECK-NEXT: [n] -> { Stmt_body[i0] : 0 <= i0 < n }; | ||
; CHECK-NEXT: Schedule := | ||
; CHECK-NEXT: [n] -> { Stmt_body[i0] -> [i0, 0] }; | ||
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] | ||
; CHECK-NEXT: [n] -> { Stmt_body[i0] -> MemRef_A[0] }; | ||
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] | ||
; CHECK-NEXT: [n] -> { Stmt_body[i0] -> MemRef_A[0] }; | ||
; CHECK-NEXT: Instructions { | ||
; CHECK-NEXT: %valA = load double, double* %A | ||
; CHECK-NEXT: store double %valA, double* %A | ||
; CHECK-NEXT: } | ||
; CHECK-NEXT: Stmt_body1 | ||
; CHECK-NEXT: Domain := | ||
; CHECK-NEXT: [n] -> { Stmt_body1[i0] : 0 <= i0 < n }; | ||
; CHECK-NEXT: Schedule := | ||
; CHECK-NEXT: [n] -> { Stmt_body1[i0] -> [i0, 1] }; | ||
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] | ||
; CHECK-NEXT: [n] -> { Stmt_body1[i0] -> MemRef_B[0] }; | ||
; CHECK-NEXT: Instructions { | ||
; CHECK-NEXT: %valB = fadd double 2.100000e+01, 2.100000e+01 | ||
; CHECK-NEXT: store double %valB, double* %B | ||
; CHECK-NEXT: } | ||
; CHECK-NEXT: } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
; RUN: opt %loadPolly -polly-stmt-granularity=scalar-indep -polly-print-instructions -polly-scops -analyze < %s | FileCheck %s -match-full-lines | ||
; | ||
; Split a block into two independent statements that share no scalar. | ||
; This case has an independent statement just for PHI writes. | ||
; | ||
; for (int j = 0; j < n; j += 1) { | ||
; bodyA: | ||
; double valA = A[0]; | ||
; A[0] = valA; | ||
; | ||
; bodyB: | ||
; phi = 42.0; | ||
; } | ||
; | ||
define void @func(i32 %n, double* noalias nonnull %A) { | ||
entry: | ||
br label %for | ||
|
||
for: | ||
%j = phi i32 [0, %entry], [%j.inc, %inc] | ||
%j.cmp = icmp slt i32 %j, %n | ||
br i1 %j.cmp, label %bodyA, label %exit | ||
|
||
bodyA: | ||
%valA = load double, double* %A | ||
store double %valA, double* %A | ||
br label %bodyB | ||
|
||
bodyB: | ||
%phi = phi double [42.0, %bodyA] | ||
br label %inc | ||
|
||
inc: | ||
%j.inc = add nuw nsw i32 %j, 1 | ||
br label %for | ||
|
||
exit: | ||
br label %return | ||
|
||
return: | ||
ret void | ||
} | ||
|
||
|
||
; CHECK: Statements { | ||
; CHECK-NEXT: Stmt_bodyA | ||
; CHECK-NEXT: Domain := | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] : 0 <= i0 < n }; | ||
; CHECK-NEXT: Schedule := | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> [i0, 0] }; | ||
; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 0] | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_A[0] }; | ||
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 0] | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA[i0] -> MemRef_A[0] }; | ||
; CHECK-NEXT: Instructions { | ||
; CHECK-NEXT: %valA = load double, double* %A | ||
; CHECK-NEXT: store double %valA, double* %A | ||
; CHECK-NEXT: } | ||
; CHECK-NEXT: Stmt_bodyA1 | ||
; CHECK-NEXT: Domain := | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] : 0 <= i0 < n }; | ||
; CHECK-NEXT: Schedule := | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] -> [i0, 1] }; | ||
; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] | ||
; CHECK-NEXT: [n] -> { Stmt_bodyA1[i0] -> MemRef_phi__phi[] }; | ||
; CHECK-NEXT: Instructions { | ||
; CHECK-NEXT: } | ||
; CHECK-NEXT: } |
Oops, something went wrong.