summaryrefslogtreecommitdiffstats
path: root/llvm/test/Transforms/SimplifyCFG/switch_create.ll
diff options
context:
space:
mode:
authorChuang-Yu Cheng <cycheng@multicorewareinc.com>2016-06-16 04:44:25 +0000
committerChuang-Yu Cheng <cycheng@multicorewareinc.com>2016-06-16 04:44:25 +0000
commitdbe00d51b4c7053b144e3552806aedcdb02eebf4 (patch)
tree34e772db491cbfeb4172cdd0e1c38f5cf87e7f9f /llvm/test/Transforms/SimplifyCFG/switch_create.ll
parent97b1fc92e895f0facaa59f5cd79cd9e71cbf3fa9 (diff)
downloadbcm5719-llvm-dbe00d51b4c7053b144e3552806aedcdb02eebf4.tar.gz
bcm5719-llvm-dbe00d51b4c7053b144e3552806aedcdb02eebf4.zip
SimplifyCFG is able to detect the pattern:
(i == 5334 || i == 5335) to: ((i & -2) == 5334) This transformation has some incorrect side conditions. Specifically, the transformation is only applied when the right-hand side constant (5334 in the example) is a power of two not equal and not equal to the negated mask. These side conditions were added in r258904 to fix PR26323. The correct side condition is that: ((Constant & Mask) == Constant)[(5334 & -2) == 5334]. It's a little bit hard to see why these transformations are correct and what the side conditions ought to be. Here is a CVC3 program to verify them for 64-bit values: ONE : BITVECTOR(64) = BVZEROEXTEND(0bin1, 63); x : BITVECTOR(64); y : BITVECTOR(64); z : BITVECTOR(64); mask : BITVECTOR(64) = BVSHL(ONE, z); QUERY( (y & ~mask = y) => ((x & ~mask = y) <=> (x = y OR x = (y | mask))) ); Please note that each pattern must be a dual implication (<--> or iff). One directional implication can create spurious matches. If the implication is only one-way, an unsatisfiable condition on the left side can imply a satisfiable condition on the right side. Dual implication ensures that satisfiable conditions are transformed to other satisfiable conditions and unsatisfiable conditions are transformed to other unsatisfiable conditions. Here is a concrete example of a unsatisfiable condition on the left implying a satisfiable condition on the right: mask = (1 << z) (x & ~mask) == y --> (x == y || x == (y | mask)) Substituting y = 3, z = 0 yields: (x & -2) == 3 --> (x == 3 || x == 2) The version of this code before r258904 had no side-conditions and incorrectly justified itself in comments through one-directional implication. Thanks to Chandler for the suggestion! Author: Thomas Jablin (tjablin) Reviewers: chandlerc majnemer hfinkel cycheng http://reviews.llvm.org/D21417 llvm-svn: 272873
Diffstat (limited to 'llvm/test/Transforms/SimplifyCFG/switch_create.ll')
-rw-r--r--llvm/test/Transforms/SimplifyCFG/switch_create.ll40
1 files changed, 40 insertions, 0 deletions
diff --git a/llvm/test/Transforms/SimplifyCFG/switch_create.ll b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
index 60802d8599b..75498faaa29 100644
--- a/llvm/test/Transforms/SimplifyCFG/switch_create.ll
+++ b/llvm/test/Transforms/SimplifyCFG/switch_create.ll
@@ -579,3 +579,43 @@ if.end29: ; preds = %entry
; CHECK: %or.cond = and i1 %tobool5, %tobool23
; CHECK: %or.cond1 = and i1 %cmp17, %or.cond
; CHECK: br i1 %or.cond1, label %if.end29, label %if.then27
+
+; Form a switch when and'ing a negated power of two
+; CHECK-LABEL: define void @test19
+; CHECK: switch i32 %arg, label %else [
+; CHECK: i32 32, label %if
+; CHECK: i32 13, label %if
+; CHECK: i32 12, label %if
+define void @test19(i32 %arg) {
+ %and = and i32 %arg, -2
+ %cmp1 = icmp eq i32 %and, 12
+ %cmp2 = icmp eq i32 %arg, 32
+ %pred = or i1 %cmp1, %cmp2
+ br i1 %pred, label %if, label %else
+
+if:
+ call void @foo1()
+ ret void
+
+else:
+ ret void
+}
+
+; Since %cmp1 is always false, a switch is never formed
+; CHECK-LABEL: define void @test20
+; CHECK-NOT: switch
+; CHECK: ret void
+define void @test20(i32 %arg) {
+ %and = and i32 %arg, -2
+ %cmp1 = icmp eq i32 %and, 13
+ %cmp2 = icmp eq i32 %arg, 32
+ %pred = or i1 %cmp1, %cmp2
+ br i1 %pred, label %if, label %else
+
+if:
+ call void @foo1()
+ ret void
+
+else:
+ ret void
+} \ No newline at end of file
OpenPOWER on IntegriCloud