1; RUN: opt -correlated-propagation -S < %s | FileCheck %s
2
3declare void @llvm.experimental.guard(i1,...)
4
5define i1 @test1(i32 %a) {
6; CHECK-LABEL: @test1(
7; CHECK: %alive = icmp eq i32 %a, 8
8; CHECK-NEXT: %result = or i1 false, %alive
9  %cmp = icmp ult i32 %a, 16
10  call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
11  %dead = icmp eq i32 %a, 16
12  %alive = icmp eq i32 %a, 8
13  %result = or i1 %dead, %alive
14  ret i1 %result
15}
16
17define i1 @test2(i32 %a) {
18; CHECK-LABEL: @test2(
19; CHECK: continue:
20; CHECK-NEXT: %alive = icmp eq i32 %a, 8
21; CHECK-NEXT: %result = or i1 false, %alive
22  %cmp = icmp ult i32 %a, 16
23  call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
24  br label %continue
25
26continue:
27  %dead = icmp eq i32 %a, 16
28  %alive = icmp eq i32 %a, 8
29  %result = or i1 %dead, %alive
30  ret i1 %result
31}
32
33define i1 @test3(i32 %a, i1 %flag) {
34; CHECK-LABEL: @test3(
35; CHECK: continue:
36; CHECK-NEXT: %alive.1 = icmp eq i32 %a, 16
37; CHECK-NEXT: %alive.2 = icmp eq i32 %a, 8
38; CHECK-NEXT: %result = or i1 %alive.1, %alive.2
39  br i1 %flag, label %true, label %false
40
41true:
42  %cmp = icmp ult i32 %a, 16
43  call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
44  br label %continue
45
46false:
47  br label %continue
48
49continue:
50  %alive.1 = icmp eq i32 %a, 16
51  %alive.2 = icmp eq i32 %a, 8
52  %result = or i1 %alive.1, %alive.2
53  ret i1 %result
54}
55
56define i1 @test4(i32 %a, i1 %flag) {
57; CHECK-LABEL: @test4(
58; CHECK: continue:
59; CHECK-NEXT: %alive = icmp eq i32 %a, 12
60; CHECK-NEXT: %result = or i1 false, %alive
61  br i1 %flag, label %true, label %false
62
63true:
64  %cmp.t = icmp ult i32 %a, 16
65  call void(i1,...) @llvm.experimental.guard(i1 %cmp.t) [ "deopt"() ]
66  br label %continue
67
68false:
69  %cmp.f = icmp ult i32 %a, 12
70  call void(i1,...) @llvm.experimental.guard(i1 %cmp.f) [ "deopt"() ]
71  br label %continue
72
73continue:
74  %dead = icmp eq i32 %a, 16
75  %alive = icmp eq i32 %a, 12
76  %result = or i1 %dead, %alive
77  ret i1 %result
78}
79
80define i1 @test5(i32 %a) {
81; CHECK-LABEL: @test5(
82; CHECK: continue:
83; CHECK-NEXT: %alive = icmp eq i32 %a.plus.8, 16
84; CHECK-NEXT: %result = or i1 false, %alive
85  %cmp = icmp ult i32 %a, 16
86  call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
87  %a.plus.8 = add i32 %a, 8
88  br label %continue
89
90continue:
91  %dead = icmp eq i32 %a.plus.8, 24
92  %alive = icmp eq i32 %a.plus.8, 16
93  %result = or i1 %dead, %alive
94  ret i1 %result
95}
96
97; Check that we handle the case when the guard is the very first instruction in
98; a basic block.
99define i1 @test6(i32 %a) {
100; CHECK-LABEL: @test6(
101; CHECK: %alive = icmp eq i32 %a, 8
102; CHECK-NEXT: %result = or i1 false, %alive
103  %cmp = icmp ult i32 %a, 16
104  br label %continue
105
106continue:
107  call void(i1,...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
108  %dead = icmp eq i32 %a, 16
109  %alive = icmp eq i32 %a, 8
110  %result = or i1 %dead, %alive
111  ret i1 %result
112}
113