1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2 ; RUN: opt < %s -passes=correlated-propagation -S | FileCheck %s
4 define void @test1(i32 %n) {
5 ; CHECK-LABEL: define void @test1(
6 ; CHECK-SAME: i32 [[N:%.*]]) {
7 ; CHECK-NEXT: [[ENTRY:.*]]:
8 ; CHECK-NEXT: br label %[[FOR_COND:.*]]
10 ; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], %[[ENTRY]] ], [ [[SHR:%.*]], %[[FOR_BODY:.*]] ]
11 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], 1
12 ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_END:.*]]
13 ; CHECK: [[FOR_BODY]]:
14 ; CHECK-NEXT: [[SHR]] = lshr i32 [[A]], 5
15 ; CHECK-NEXT: br label %[[FOR_COND]]
17 ; CHECK-NEXT: ret void
22 for.cond: ; preds = %for.body, %entry
23 %a = phi i32 [ %n, %entry ], [ %shr, %for.body ]
24 %cmp = icmp sgt i32 %a, 1
25 br i1 %cmp, label %for.body, label %for.end
27 for.body: ; preds = %for.cond
31 for.end: ; preds = %for.cond
35 ;; Negative test to show transform doesn't happen unless n > 0.
36 define void @test2(i32 %n) {
37 ; CHECK-LABEL: define void @test2(
38 ; CHECK-SAME: i32 [[N:%.*]]) {
39 ; CHECK-NEXT: [[ENTRY:.*]]:
40 ; CHECK-NEXT: br label %[[FOR_COND:.*]]
41 ; CHECK: [[FOR_COND]]:
42 ; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], %[[ENTRY]] ], [ [[SHR:%.*]], %[[FOR_BODY:.*]] ]
43 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[A]], -2
44 ; CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY]], label %[[FOR_END:.*]]
45 ; CHECK: [[FOR_BODY]]:
46 ; CHECK-NEXT: [[SHR]] = ashr i32 [[A]], 2
47 ; CHECK-NEXT: br label %[[FOR_COND]]
49 ; CHECK-NEXT: ret void
54 for.cond: ; preds = %for.body, %entry
55 %a = phi i32 [ %n, %entry ], [ %shr, %for.body ]
56 %cmp = icmp sgt i32 %a, -2
57 br i1 %cmp, label %for.body, label %for.end
59 for.body: ; preds = %for.cond
63 for.end: ; preds = %for.cond
67 ;; Non looping test case.
68 define void @test3(i32 %n) {
69 ; CHECK-LABEL: define void @test3(
70 ; CHECK-SAME: i32 [[N:%.*]]) {
71 ; CHECK-NEXT: [[ENTRY:.*:]]
72 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0
73 ; CHECK-NEXT: br i1 [[CMP]], label %[[BB:.*]], label %[[EXIT:.*]]
75 ; CHECK-NEXT: [[SHR:%.*]] = lshr exact i32 [[N]], 4
76 ; CHECK-NEXT: br label %[[EXIT]]
78 ; CHECK-NEXT: ret void
81 %cmp = icmp sgt i32 %n, 0
82 br i1 %cmp, label %bb, label %exit
85 %shr = ashr exact i32 %n, 4
92 ; looping case where loop has exactly one block
93 ; at the point of ashr, we know that the operand is always greater than 0,
94 ; because of the guard before it, so we can transform it to lshr.
95 declare void @llvm.experimental.guard(i1,...)
96 define void @test4(i32 %n) {
97 ; CHECK-LABEL: define void @test4(
98 ; CHECK-SAME: i32 [[N:%.*]]) {
99 ; CHECK-NEXT: [[ENTRY:.*]]:
100 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0
101 ; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP:.*]], label %[[EXIT:.*]]
103 ; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], %[[ENTRY]] ], [ [[SHR:%.*]], %[[LOOP]] ]
104 ; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[A]], 2
105 ; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[COND]]) [ "deopt"() ]
106 ; CHECK-NEXT: [[SHR]] = lshr i32 [[A]], 1
107 ; CHECK-NEXT: br i1 [[COND]], label %[[LOOP]], label %[[EXIT]]
109 ; CHECK-NEXT: ret void
112 %cmp = icmp sgt i32 %n, 0
113 br i1 %cmp, label %loop, label %exit
116 %a = phi i32 [ %n, %entry ], [ %shr, %loop ]
117 %cond = icmp sgt i32 %a, 2
118 call void(i1,...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
119 %shr = ashr i32 %a, 1
120 br i1 %cond, label %loop, label %exit
126 ; same test as above with assume instead of guard.
127 declare void @llvm.assume(i1)
128 define void @test5(i32 %n) {
129 ; CHECK-LABEL: define void @test5(
130 ; CHECK-SAME: i32 [[N:%.*]]) {
131 ; CHECK-NEXT: [[ENTRY:.*]]:
132 ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0
133 ; CHECK-NEXT: br i1 [[CMP]], label %[[LOOP:.*]], label %[[EXIT:.*]]
135 ; CHECK-NEXT: [[A:%.*]] = phi i32 [ [[N]], %[[ENTRY]] ], [ [[SHR:%.*]], %[[LOOP]] ]
136 ; CHECK-NEXT: [[COND:%.*]] = icmp samesign ugt i32 [[A]], 4
137 ; CHECK-NEXT: call void @llvm.assume(i1 [[COND]])
138 ; CHECK-NEXT: [[SHR]] = lshr i32 [[A]], 1
139 ; CHECK-NEXT: [[LOOPCOND:%.*]] = icmp samesign ugt i32 [[SHR]], 8
140 ; CHECK-NEXT: br i1 [[LOOPCOND]], label %[[LOOP]], label %[[EXIT]]
142 ; CHECK-NEXT: ret void
145 %cmp = icmp sgt i32 %n, 0
146 br i1 %cmp, label %loop, label %exit
149 %a = phi i32 [ %n, %entry ], [ %shr, %loop ]
150 %cond = icmp sgt i32 %a, 4
151 call void @llvm.assume(i1 %cond)
152 %shr = ashr i32 %a, 1
153 %loopcond = icmp sgt i32 %shr, 8
154 br i1 %loopcond, label %loop, label %exit
160 ; check that ashr of -1 or 0 is optimized away
161 define i32 @test6(i32 %f, i32 %g) {
162 ; CHECK-LABEL: define range(i32 -1, 1) i32 @test6(
163 ; CHECK-SAME: i32 [[F:%.*]], i32 [[G:%.*]]) {
164 ; CHECK-NEXT: [[ENTRY:.*:]]
165 ; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[F]], 1
166 ; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[TMP0]], 2
167 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP1]])
168 ; CHECK-NEXT: ret i32 [[F]]
172 %1 = icmp ult i32 %0, 2
173 tail call void @llvm.assume(i1 %1)
174 %shr = ashr i32 %f, %g
178 ; same test as above with different numbers
179 define i32 @test7(i32 %f, i32 %g) {
180 ; CHECK-LABEL: define range(i32 -1, 1) i32 @test7(
181 ; CHECK-SAME: i32 [[F:%.*]], i32 [[G:%.*]]) {
182 ; CHECK-NEXT: [[ENTRY:.*:]]
183 ; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[F]], -2
184 ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[TMP0]], 6
185 ; CHECK-NEXT: tail call void @llvm.assume(i1 [[TMP1]])
186 ; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[F]], -7
187 ; CHECK-NEXT: ret i32 [[SUB]]
191 %1 = icmp eq i32 %0, 6
192 tail call void @llvm.assume(i1 %1)
193 %sub = add nsw i32 %f, -7
194 %shr = ashr i32 %sub, %g
198 ; check that ashr of -2 or 1 is not optimized away
199 define i32 @test8(i32 %f, i32 %g, i1 %s) {
200 ; CHECK-LABEL: define range(i32 -2, 2) i32 @test8(
201 ; CHECK-SAME: i32 [[F:%.*]], i32 [[G:%.*]], i1 [[S:%.*]]) {
202 ; CHECK-NEXT: [[ENTRY:.*:]]
203 ; CHECK-NEXT: [[TMP0:%.*]] = ashr i32 -2, [[F]]
204 ; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 1, [[G]]
205 ; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[S]], i32 [[TMP0]], i32 [[TMP1]]
206 ; CHECK-NEXT: ret i32 [[TMP2]]
211 %2 = select i1 %s, i32 %0, i32 %1
215 define i32 @may_including_undef(i1 %c.1, i1 %c.2) {
216 ; CHECK-LABEL: define range(i32 -1073741824, 1073741824) i32 @may_including_undef(
217 ; CHECK-SAME: i1 [[C_1:%.*]], i1 [[C_2:%.*]]) {
218 ; CHECK-NEXT: br i1 [[C_1]], label %[[TRUE_1:.*]], label %[[FALSE:.*]]
220 ; CHECK-NEXT: br i1 [[C_2]], label %[[TRUE_2:.*]], label %[[EXIT:.*]]
222 ; CHECK-NEXT: br label %[[EXIT]]
224 ; CHECK-NEXT: br label %[[EXIT]]
226 ; CHECK-NEXT: [[P:%.*]] = phi i32 [ 2, %[[TRUE_1]] ], [ 4, %[[TRUE_2]] ], [ undef, %[[FALSE]] ]
227 ; CHECK-NEXT: [[R:%.*]] = ashr i32 [[P]], 1
228 ; CHECK-NEXT: ret i32 [[R]]
230 br i1 %c.1, label %true.1, label %false
233 br i1 %c.2, label %true.2, label %exit
242 %p = phi i32 [ 2, %true.1 ], [ 4, %true.2], [ undef, %false ]