diff options
author | Michael Kruse <llvm@meinersbur.de> | 2017-08-01 20:01:34 +0000 |
---|---|---|
committer | Michael Kruse <llvm@meinersbur.de> | 2017-08-01 20:01:34 +0000 |
commit | bc88a78cb453808ecc0b13c25dae93d2ddcebd7f (patch) | |
tree | 498926acacc5a7531e1b02ac98092e398fa3b942 /polly/test/Simplify | |
parent | a5fcb83bfa18ac02ae30465efb83782988b557d1 (diff) | |
download | bcm5719-llvm-bc88a78cb453808ecc0b13c25dae93d2ddcebd7f.tar.gz bcm5719-llvm-bc88a78cb453808ecc0b13c25dae93d2ddcebd7f.zip |
[Simplify] Rewrite redundant write detection algorithm.
The previous algorithm was to search a writes and the sours of its value
operand, and see whether the write just stores the same read value back,
which includes a search whether there is another write access between
them. This is O(n^2) in the max number of accesses in a statement
(+ the complexity of isl comparing the access functions).
The new algorithm is more similar to the one used for searching for
overwrites and coalescable writes. It scans over all accesses in order
of execution while tracking which array elements still have the same
value since it was read. This is O(n), not counting the complexity
within isl. It should be more reliable than trying to catch all
non-conforming cases in the previous approach. It is also less code.
We now also support if the write is a partial write of the read's
domain, and to some extent non-affine subregions.
Differential Revision: https://reviews.llvm.org/D36137
llvm-svn: 309734
Diffstat (limited to 'polly/test/Simplify')
15 files changed, 594 insertions, 7 deletions
diff --git a/polly/test/Simplify/notredundant_region_loop.ll b/polly/test/Simplify/notredundant_region_loop.ll new file mode 100644 index 00000000000..c8b7ee5ae4f --- /dev/null +++ b/polly/test/Simplify/notredundant_region_loop.ll @@ -0,0 +1,46 @@ +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-allow-nonaffine-loops -polly-simplify -analyze < %s | FileCheck %s -match-full-lines +; +; Do not remove the store in region_entry. It can be executed multiple times +; due to being part of a non-affine loop. +; +define void @notredundant_region_loop(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 %body, label %exit + + + body: + %val = fadd double 21.0, 21.0 + br label %region_entry + + region_entry: + store double %val, double* %A + %sqr = mul i32 %j, %j + %cmp = icmp eq i32 %sqr, 42 + br i1 %cmp, label %region_true, label %region_exit + + region_true: + store double 0.0, double* %A + br label %region_entry + + region_exit: + br label %inc + + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; CHECK: SCoP could not be simplified diff --git a/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop b/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop new file mode 100644 index 00000000000..b86534e7a06 --- /dev/null +++ b/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop @@ -0,0 +1,43 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_val[] }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_val[] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 1] }" + } + ] +} diff --git a/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop.transformed b/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop.transformed new file mode 100644 index 00000000000..9fe65e936fd --- /dev/null +++ b/polly/test/Simplify/notredundant_region_loop___%for---%return.jscop.transformed @@ -0,0 +1,43 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 1] }" + } + ] +} diff --git a/polly/test/Simplify/notredundant_region_middle.ll b/polly/test/Simplify/notredundant_region_middle.ll new file mode 100644 index 00000000000..cadbc1724fc --- /dev/null +++ b/polly/test/Simplify/notredundant_region_middle.ll @@ -0,0 +1,54 @@ +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-simplify -analyze < %s | FileCheck %s -match-full-lines +; +; Do not remove redundant stores in the middle of region statements. +; The store in region_true could be removed, but in practice we do try to +; determine the relative ordering of block in region statements. +; +; for (int j = 0; j < n; j += 1) { +; double val = A[0]; +; if (val == 0.0) +; A[0] = val; +; else +; A[0] = 0.0; +; } +; +define void @notredundant_region(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 %region_entry, label %exit + + + region_entry: + %val = load double, double* %A + %cmp = fcmp oeq double %val, 0.0 + br i1 %cmp, label %region_true, label %region_false + + region_true: + store double %val, double* %A + br label %region_exit + + region_false: + store double 0.0, double* %A + br label %region_exit + + region_exit: + br label %inc + + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; CHECK: SCoP could not be simplified diff --git a/polly/test/Simplify/redundant_differentindex.ll b/polly/test/Simplify/redundant_differentindex.ll index d460f85a09d..3a5e07334cb 100644 --- a/polly/test/Simplify/redundant_differentindex.ll +++ b/polly/test/Simplify/redundant_differentindex.ll @@ -1,6 +1,4 @@ ; RUN: opt %loadPolly -polly-simplify -analyze < %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly -polly-simplify -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines -; REQUIRES: asserts ; ; A store that has a different index than the load it is storing is ; not redundant. @@ -36,5 +34,3 @@ return: ; CHECK: SCoP could not be simplified - -; STATS: 1 polly-simplify - Number of Load-Store pairs NOT removed because of different access relations diff --git a/polly/test/Simplify/redundant_partialwrite.ll b/polly/test/Simplify/redundant_partialwrite.ll new file mode 100644 index 00000000000..71c27bd349e --- /dev/null +++ b/polly/test/Simplify/redundant_partialwrite.ll @@ -0,0 +1,40 @@ +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-simplify -analyze < %s | FileCheck %s -match-full-lines +; +; Remove a redundant store, if its partial domain is a subset of the +; read's domain. +; +define void @redundant_partialwrite(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 %body, label %exit + + body: + %val = load double, double* %A + store double %val, double* %A + br label %inc + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; Check successful import. +; CHECK: new: [n] -> { Stmt_body[i0] -> MemRef_A[0] : i0 <= 15 }; + +; CHECK: Statistics { +; CHECK: Redundant writes removed: 1 +; CHECK: } + +; CHECK: After accesses { +; CHECK-NEXT: } diff --git a/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop b/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop new file mode 100644 index 00000000000..9869237ab63 --- /dev/null +++ b/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop @@ -0,0 +1,28 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop.transformed b/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop.transformed new file mode 100644 index 00000000000..38b730fc4d4 --- /dev/null +++ b/polly/test/Simplify/redundant_partialwrite___%for---%return.jscop.transformed @@ -0,0 +1,28 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] : i0 < 16 }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_region.ll b/polly/test/Simplify/redundant_region.ll new file mode 100644 index 00000000000..c006f4bd3d7 --- /dev/null +++ b/polly/test/Simplify/redundant_region.ll @@ -0,0 +1,49 @@ +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-simplify -analyze < %s | FileCheck %s -match-full-lines +; +; Remove redundant store (a store that writes the same value already +; at the destination) in a region. +; +define void @redundant_region(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 %region_entry, label %exit + + + region_entry: + %val = load double, double* %A + %cmp = fcmp oeq double %val, 0.0 + br i1 %cmp, label %region_true, label %region_exit + + region_true: + br label %region_exit + + region_exit: + br label %body + + body: + store double %val, double* %A + br label %inc + + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Redundant writes removed: 2 +; CHECK: } + +; CHECK: After accesses { +; CHECK-NEXT: } diff --git a/polly/test/Simplify/redundant_region___%for---%return.jscop b/polly/test/Simplify/redundant_region___%for---%return.jscop new file mode 100644 index 00000000000..7517c3e39bc --- /dev/null +++ b/polly/test/Simplify/redundant_region___%for---%return.jscop @@ -0,0 +1,43 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_val[] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_val[] }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0, 1] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_region___%for---%return.jscop.transformed b/polly/test/Simplify/redundant_region___%for---%return.jscop.transformed new file mode 100644 index 00000000000..b416142c358 --- /dev/null +++ b/polly/test/Simplify/redundant_region___%for---%return.jscop.transformed @@ -0,0 +1,43 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_body[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_body[i0] : 0 <= i0 < n }", + "name" : "Stmt_body", + "schedule" : "[n] -> { Stmt_body[i0] -> [i0, 1] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_region_scalar.ll b/polly/test/Simplify/redundant_region_scalar.ll new file mode 100644 index 00000000000..495a4baafee --- /dev/null +++ b/polly/test/Simplify/redundant_region_scalar.ll @@ -0,0 +1,53 @@ +; RUN: opt %loadPolly -polly-import-jscop -polly-import-jscop-postfix=transformed -polly-simplify -analyze < %s | FileCheck %s -match-full-lines +; +; Remove redundant store (a store that writes the same value already +; at the destination) in a region. +; +define void @redundant_region_scalar(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: + %val1 = load double, double* %A + br label %region_entry + + region_entry: + %val2 = load double, double* %A + %cmp = fcmp oeq double %val1, 0.0 + br i1 %cmp, label %region_true, label %region_exit + + region_true: + br label %region_exit + + region_exit: + br label %bodyB + + bodyB: + store double %val2, double* %A + br label %inc + + +inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %for + +exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Redundant writes removed: 3 +; CHECK: } + +; CHECK: After accesses { +; CHECK-NEXT: } diff --git a/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop b/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop new file mode 100644 index 00000000000..7712c264dde --- /dev/null +++ b/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop @@ -0,0 +1,62 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_bodyA[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_bodyA[i0] -> MemRef_val1[] }" + } + ], + "domain" : "[n] -> { Stmt_bodyA[i0] : 0 <= i0 < n }", + "name" : "Stmt_bodyA", + "schedule" : "[n] -> { Stmt_bodyA[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_val1[] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_val2[] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 1] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_bodyB[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_bodyB[i0] -> MemRef_val2[] }" + } + ], + "domain" : "[n] -> { Stmt_bodyB[i0] : 0 <= i0 < n }", + "name" : "Stmt_bodyB", + "schedule" : "[n] -> { Stmt_bodyB[i0] -> [i0, 2] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop.transformed b/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop.transformed new file mode 100644 index 00000000000..9bb0e0c2d71 --- /dev/null +++ b/polly/test/Simplify/redundant_region_scalar___%for---%return.jscop.transformed @@ -0,0 +1,62 @@ +{ + "arrays" : [ + { + "name" : "MemRef_A", + "sizes" : [ "*" ], + "type" : "double" + } + ], + "context" : "[n] -> { : -2147483648 <= n <= 2147483647 }", + "name" : "%for---%return", + "statements" : [ + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_bodyA[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_bodyA[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_bodyA[i0] : 0 <= i0 < n }", + "name" : "Stmt_bodyA", + "schedule" : "[n] -> { Stmt_bodyA[i0] -> [i0, 0] }" + }, + { + "accesses" : [ + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + }, + { + "kind" : "write", + "relation" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] : 0 <= i0 < n }", + "name" : "Stmt_region_entry__TO__region_exit", + "schedule" : "[n] -> { Stmt_region_entry__TO__region_exit[i0] -> [i0, 1] }" + }, + { + "accesses" : [ + { + "kind" : "write", + "relation" : "[n] -> { Stmt_bodyB[i0] -> MemRef_A[0] }" + }, + { + "kind" : "read", + "relation" : "[n] -> { Stmt_bodyB[i0] -> MemRef_A[0] }" + } + ], + "domain" : "[n] -> { Stmt_bodyB[i0] : 0 <= i0 < n }", + "name" : "Stmt_bodyB", + "schedule" : "[n] -> { Stmt_bodyB[i0] -> [i0, 2] }" + } + ] +} diff --git a/polly/test/Simplify/redundant_storebetween.ll b/polly/test/Simplify/redundant_storebetween.ll index 03172b6b0eb..5e1befcb1a4 100644 --- a/polly/test/Simplify/redundant_storebetween.ll +++ b/polly/test/Simplify/redundant_storebetween.ll @@ -1,6 +1,4 @@ ; RUN: opt %loadPolly -polly-simplify -analyze < %s | FileCheck %s -match-full-lines -; RUN: opt %loadPolly -polly-simplify -disable-output -stats < %s 2>&1 | FileCheck %s --check-prefix=STATS -match-full-lines -; REQUIRES: asserts ; ; Don't remove store where there is another store to the same target ; in-between them. @@ -38,4 +36,3 @@ return: ; CHECK: SCoP could not be simplified -; STATS: 1 polly-simplify - Number of Load-Store pairs NOT removed because there is another store between them |