summaryrefslogtreecommitdiff
path: root/test/Transforms/SimplifyCFG
diff options
context:
space:
mode:
Diffstat (limited to 'test/Transforms/SimplifyCFG')
-rw-r--r--test/Transforms/SimplifyCFG/implied-and-or.ll183
-rw-r--r--test/Transforms/SimplifyCFG/sink-common-code.ll24
2 files changed, 207 insertions, 0 deletions
diff --git a/test/Transforms/SimplifyCFG/implied-and-or.ll b/test/Transforms/SimplifyCFG/implied-and-or.ll
new file mode 100644
index 000000000000..e615f302feef
--- /dev/null
+++ b/test/Transforms/SimplifyCFG/implied-and-or.ll
@@ -0,0 +1,183 @@
+; RUN: opt %s -S -simplifycfg | FileCheck %s
+
+declare void @foo()
+declare void @bar()
+
+
+; CHECK-LABEL: @test_and1
+; CHECK: taken:
+; CHECK-NOT: cmp3
+; CHECK: call void @bar()
+; CHECK-NEXT: call void @foo()
+; CHECK: ret
+define void @test_and1(i32 %a, i32 %b) {
+entry:
+ %cmp1 = icmp eq i32 %a, 0
+ %cmp2 = icmp eq i32 %b, 0
+ %and = and i1 %cmp1, %cmp2
+ br i1 %and, label %taken, label %end
+
+taken:
+ call void @bar()
+ %cmp3 = icmp eq i32 %a, 0 ;; <-- implied true
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
+
+; We can't infer anything if the result of the 'and' is false
+; CHECK-LABEL: @test_and2
+; CHECK: taken:
+; CHECK: call void @bar()
+; CHECK: %cmp3
+; CHECK: br i1 %cmp3
+; CHECK: if.then:
+; CHECK: call void @foo()
+; CHECK: ret
+define void @test_and2(i32 %a, i32 %b) {
+entry:
+ %cmp1 = icmp eq i32 %a, 0
+ %cmp2 = icmp eq i32 %b, 0
+ %and = and i1 %cmp1, %cmp2
+ br i1 %and, label %end, label %taken
+
+taken:
+ call void @bar()
+ %cmp3 = icmp eq i32 %a, 0
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
+
+; CHECK-LABEL: @test_or1
+; CHECK: taken:
+; CHECK-NOT: cmp3
+; CHECK: call void @bar()
+; CHECK-NEXT: call void @foo()
+; CHECK: ret
+define void @test_or1(i32 %a, i32 %b) {
+entry:
+ %cmp1 = icmp eq i32 %a, 0
+ %cmp2 = icmp eq i32 %b, 0
+ %or = or i1 %cmp1, %cmp2
+ br i1 %or, label %end, label %taken
+
+taken:
+ call void @bar()
+ %cmp3 = icmp ne i32 %a, 0 ;; <-- implied true
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
+
+; We can't infer anything if the result of the 'or' is true
+; CHECK-LABEL: @test_or2
+; CHECK: call void @bar()
+; CHECK: %cmp3
+; CHECK: br i1 %cmp3
+; CHECK: if.then:
+; CHECK: call void @foo()
+; CHECK: ret
+define void @test_or2(i32 %a, i32 %b) {
+entry:
+ %cmp1 = icmp eq i32 %a, 0
+ %cmp2 = icmp eq i32 %b, 0
+ %or = or i1 %cmp1, %cmp2
+ br i1 %or, label %taken, label %end
+
+taken:
+ call void @bar()
+ %cmp3 = icmp eq i32 %a, 0
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
+
+; We can recurse a tree of 'and' or 'or's.
+; CHECK-LABEL: @test_and_recurse1
+; CHECK: taken:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: call void @foo()
+; CHECK-NEXT: br label %end
+; CHECK: ret
+define void @test_and_recurse1(i32 %a, i32 %b, i32 %c) {
+entry:
+ %cmpa = icmp eq i32 %a, 0
+ %cmpb = icmp eq i32 %b, 0
+ %cmpc = icmp eq i32 %c, 0
+ %and1 = and i1 %cmpa, %cmpb
+ %and2 = and i1 %and1, %cmpc
+ br i1 %and2, label %taken, label %end
+
+taken:
+ call void @bar()
+ %cmp3 = icmp eq i32 %a, 0
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
+
+; Check to make sure we don't recurse too deep.
+; CHECK-LABEL: @test_and_recurse2
+; CHECK: taken:
+; CHECK-NEXT: call void @bar()
+; CHECK-NEXT: %cmp3 = icmp eq i32 %a, 0
+; CHECK-NEXT: br i1 %cmp3, label %if.then, label %end
+; CHECK: ret
+define void @test_and_recurse2(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f,
+ i32 %g, i32 %h) {
+entry:
+ %cmpa = icmp eq i32 %a, 0
+ %cmpb = icmp eq i32 %b, 0
+ %cmpc = icmp eq i32 %c, 0
+ %cmpd = icmp eq i32 %d, 0
+ %cmpe = icmp eq i32 %e, 0
+ %cmpf = icmp eq i32 %f, 0
+ %cmpg = icmp eq i32 %g, 0
+ %cmph = icmp eq i32 %h, 0
+ %and1 = and i1 %cmpa, %cmpb
+ %and2 = and i1 %and1, %cmpc
+ %and3 = and i1 %and2, %cmpd
+ %and4 = and i1 %and3, %cmpe
+ %and5 = and i1 %and4, %cmpf
+ %and6 = and i1 %and5, %cmpg
+ %and7 = and i1 %and6, %cmph
+ br i1 %and7, label %taken, label %end
+
+taken:
+ call void @bar()
+ %cmp3 = icmp eq i32 %a, 0 ; <-- can be implied true
+ br i1 %cmp3, label %if.then, label %end
+
+if.then:
+ call void @foo()
+ br label %end
+
+end:
+ ret void
+}
diff --git a/test/Transforms/SimplifyCFG/sink-common-code.ll b/test/Transforms/SimplifyCFG/sink-common-code.ll
index 0f7bfa8516c9..513da477607b 100644
--- a/test/Transforms/SimplifyCFG/sink-common-code.ll
+++ b/test/Transforms/SimplifyCFG/sink-common-code.ll
@@ -818,6 +818,30 @@ merge:
; CHECK: right:
; CHECK-NEXT: %val1 = call i32 @call_target() [ "deopt"(i32 20) ]
+%T = type {i32, i32}
+
+define i32 @test_insertvalue(i1 zeroext %flag, %T %P) {
+entry:
+ br i1 %flag, label %if.then, label %if.else
+
+if.then:
+ %t1 = insertvalue %T %P, i32 0, 0
+ br label %if.end
+
+if.else:
+ %t2 = insertvalue %T %P, i32 1, 0
+ br label %if.end
+
+if.end:
+ %t = phi %T [%t1, %if.then], [%t2, %if.else]
+ ret i32 1
+}
+
+; CHECK-LABEL: @test_insertvalue
+; CHECK: select
+; CHECK: insertvalue
+; CHECK-NOT: insertvalue
+
; CHECK: ![[TBAA]] = !{![[TYPE:[0-9]]], ![[TYPE]], i64 0}
; CHECK: ![[TYPE]] = !{!"float", ![[TEXT:[0-9]]]}
; CHECK: ![[TEXT]] = !{!"an example type tree"}