[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / Util / assume-simplify.ll
blobd336d4420c90a133b0e843e69b24463c2a2d1d63
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2 ; RUN: opt -passes='require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s
4 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
6 declare void @may_throw()
8 declare void @llvm.assume(i1 noundef) #0
10 define i32 @test1(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) {
11 ; CHECK-LABEL: define {{[^@]+}}@test1
12 ; CHECK-SAME: (ptr nonnull dereferenceable(4) [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
13 ; CHECK-NEXT:  bb:
14 ; CHECK-NEXT:    [[I:%.*]] = icmp ne i32 [[ARG2]], 4
15 ; CHECK-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[A:%.*]]
16 ; CHECK:       bb4:
17 ; CHECK-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
18 ; CHECK-NEXT:    call void @may_throw()
19 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "align"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]) ]
20 ; CHECK-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
21 ; CHECK-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
22 ; CHECK-NEXT:    store i32 0, ptr [[ARG]], align 4
23 ; CHECK-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
24 ; CHECK-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
25 ; CHECK-NEXT:    call void @may_throw()
26 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "ignore"(ptr poison) ]
27 ; CHECK-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
28 ; CHECK-NEXT:    br label [[B:%.*]]
29 ; CHECK:       A:
30 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "ignore"(ptr poison, i64 4), "ignore"(ptr poison) ]
31 ; CHECK-NEXT:    br label [[B]]
32 ; CHECK:       B:
33 ; CHECK-NEXT:    ret i32 0
35 bb:
36   %i = icmp ne i32 %arg2, 4
37   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ]
38   br i1 %i, label %bb4, label %A
40 bb4:                                              ; preds = %bb
41   %i5 = add nsw i32 %arg3, %arg2
42   call void @may_throw()
43   %i6 = load i32, ptr %arg, align 4
44   %i7 = add nsw i32 %i5, %i6
45   store i32 0, ptr %arg, align 4
46   call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4) ]
47   %i8 = load i32, ptr %arg1, align 4
48   %i9 = add nsw i32 %i7, %i8
49   call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ]
50   call void @may_throw()
51   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ]
52   store i32 %i9, ptr %arg1, align 4
53   br label %B
55 A:                                                ; preds = %bb
56   call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ]
57   br label %B
59 B:                                                ; preds = %A, %bb4
60   ret i32 0
63 define i32 @test2(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) {
64 ; CHECK-LABEL: define {{[^@]+}}@test2
65 ; CHECK-SAME: (ptr [[ARG:%.*]], ptr nonnull align 4 dereferenceable(4) [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
66 ; CHECK-NEXT:  bb:
67 ; CHECK-NEXT:    [[I4:%.*]] = load i32, ptr [[ARG1]], align 4
68 ; CHECK-NEXT:    [[I5:%.*]] = icmp ne i32 [[I4]], 0
69 ; CHECK-NEXT:    br i1 [[I5]], label [[BB7:%.*]], label [[BB17:%.*]]
70 ; CHECK:       bb7:
71 ; CHECK-NEXT:    call void @may_throw()
72 ; CHECK-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
73 ; CHECK-NEXT:    [[I9:%.*]] = getelementptr inbounds i32, ptr [[ARG1]], i64 2
74 ; CHECK-NEXT:    store i32 [[I8]], ptr [[I9]], align 4
75 ; CHECK-NEXT:    call void @may_throw()
76 ; CHECK-NEXT:    call void @may_throw()
77 ; CHECK-NEXT:    [[I10:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1
78 ; CHECK-NEXT:    [[I11:%.*]] = load ptr, ptr [[I10]], align 8
79 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 12), "align"(ptr [[I11]], i64 4), "dereferenceable"(ptr [[I11]], i64 4), "nonnull"(ptr [[I11]]) ]
80 ; CHECK-NEXT:    [[I13:%.*]] = load i32, ptr [[I11]], align 4
81 ; CHECK-NEXT:    [[I14:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 1
82 ; CHECK-NEXT:    [[I15:%.*]] = load ptr, ptr [[I14]], align 8
83 ; CHECK-NEXT:    [[I16:%.*]] = getelementptr inbounds i32, ptr [[I15]], i64 2
84 ; CHECK-NEXT:    store i32 [[I13]], ptr [[I16]], align 4
85 ; CHECK-NEXT:    call void @may_throw()
86 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ]
87 ; CHECK-NEXT:    br label [[BB33:%.*]]
88 ; CHECK:       bb17:
89 ; CHECK-NEXT:    [[I18:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 7
90 ; CHECK-NEXT:    [[I19:%.*]] = load ptr, ptr [[I18]], align 8
91 ; CHECK-NEXT:    [[I21:%.*]] = load i32, ptr [[I19]], align 4
92 ; CHECK-NEXT:    [[I22:%.*]] = icmp ne i32 [[I21]], 0
93 ; CHECK-NEXT:    br i1 [[I22]], label [[BB23:%.*]], label [[BB31:%.*]]
94 ; CHECK:       bb23:
95 ; CHECK-NEXT:    call void @may_throw()
96 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ]
97 ; CHECK-NEXT:    [[I24:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2
98 ; CHECK-NEXT:    [[I25:%.*]] = load ptr, ptr [[I24]], align 8
99 ; CHECK-NEXT:    [[I27:%.*]] = load i32, ptr [[I25]], align 4
100 ; CHECK-NEXT:    [[I28:%.*]] = getelementptr inbounds ptr, ptr [[ARG]], i64 2
101 ; CHECK-NEXT:    [[I29:%.*]] = load ptr, ptr [[I28]], align 8
102 ; CHECK-NEXT:    [[I30:%.*]] = getelementptr inbounds i32, ptr [[I29]], i64 2
103 ; CHECK-NEXT:    store i32 [[I27]], ptr [[I30]], align 4
104 ; CHECK-NEXT:    call void @may_throw()
105 ; CHECK-NEXT:    br label [[BB31]]
106 ; CHECK:       bb31:
107 ; CHECK-NEXT:    br label [[BB32:%.*]]
108 ; CHECK:       bb32:
109 ; CHECK-NEXT:    br label [[BB33]]
110 ; CHECK:       bb33:
111 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]) ]
112 ; CHECK-NEXT:    ret i32 0
115   %i4 = load i32, ptr %arg1, align 4
116   %i5 = icmp ne i32 %i4, 0
117   call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4) ]
118   call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ]
119   br i1 %i5, label %bb7, label %bb17
121 bb7:                                              ; preds = %bb
122   call void @may_throw()
123   call void @llvm.assume(i1 true) [ "align"(ptr %arg1, i64 4), "dereferenceable"(ptr %arg1, i64 4), "nonnull"(ptr %arg1) ]
124   %i8 = load i32, ptr %arg1, align 4
125   %i9 = getelementptr inbounds i32, ptr %arg1, i64 2
126   store i32 %i8, ptr %i9, align 4
127   call void @may_throw()
128   call void @may_throw()
129   call void @llvm.assume(i1 true) [ "align"(ptr %i9, i64 4), "dereferenceable"(ptr %i9, i64 4), "nonnull"(ptr %i9) ]
130   %i10 = getelementptr inbounds ptr, ptr %arg, i64 1
131   %i11 = load ptr, ptr %i10, align 8
132   %i13 = load i32, ptr %i11, align 4
133   call void @llvm.assume(i1 true) [ "align"(ptr %i11, i64 4), "dereferenceable"(ptr %i11, i64 4), "nonnull"(ptr %i11) ]
134   %i14 = getelementptr inbounds ptr, ptr %arg, i64 1
135   %i15 = load ptr, ptr %i14, align 8
136   %i16 = getelementptr inbounds i32, ptr %i15, i64 2
137   store i32 %i13, ptr %i16, align 4
138   call void @may_throw()
139   call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ]
140   br label %bb33
142 bb17:                                             ; preds = %bb
143   %i18 = getelementptr inbounds ptr, ptr %arg, i64 7
144   %i19 = load ptr, ptr %i18, align 8
145   %i21 = load i32, ptr %i19, align 4
146   %i22 = icmp ne i32 %i21, 0
147   br i1 %i22, label %bb23, label %bb31
149 bb23:                                             ; preds = %bb17
150   call void @may_throw()
151   call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ]
152   %i24 = getelementptr inbounds ptr, ptr %arg, i64 2
153   %i25 = load ptr, ptr %i24, align 8
154   %i27 = load i32, ptr %i25, align 4
155   %i28 = getelementptr inbounds ptr, ptr %arg, i64 2
156   %i29 = load ptr, ptr %i28, align 8
157   %i30 = getelementptr inbounds i32, ptr %i29, i64 2
158   store i32 %i27, ptr %i30, align 4
159   call void @may_throw()
160   br label %bb31
162 bb31:                                             ; preds = %bb23, %bb17
163   br label %bb32
165 bb32:                                             ; preds = %bb31
166   br label %bb33
168 bb33:                                             ; preds = %bb32, %bb7
169   call void @llvm.assume(i1 true) [ "align"(ptr %arg, i64 4), "dereferenceable"(ptr %arg, i64 4), "nonnull"(ptr %arg) ]
170   ret i32 0
173 define i32 @test3(ptr nonnull %p, i32 %i) {
174 ; CHECK-LABEL: define {{[^@]+}}@test3
175 ; CHECK-SAME: (ptr nonnull [[P:%.*]], i32 [[I:%.*]]) {
176 ; CHECK-NEXT:  bb:
177 ; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
178 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
179 ; CHECK:       A:
180 ; CHECK-NEXT:    ret i32 0
181 ; CHECK:       B:
182 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr [[P]], align 4
183 ; CHECK-NEXT:    ret i32 [[RET]]
186   %cond = icmp ne i32 %i, 0
187   call void @llvm.assume(i1 true) [ "nonnull"(ptr %p) ]
188   br i1 %cond, label %A, label %B
190 A:                                                ; preds = %bb
191   ret i32 0
193 B:                                                ; preds = %bb
194   %ret = load i32, ptr %p, align 4
195   ret i32 %ret
198 define i32 @test4(ptr %p, i32 %i) {
199 ; CHECK-LABEL: define {{[^@]+}}@test4
200 ; CHECK-SAME: (ptr nonnull dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) {
201 ; CHECK-NEXT:  bb:
202 ; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
203 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
204 ; CHECK:       A:
205 ; CHECK-NEXT:    ret i32 0
206 ; CHECK:       B:
207 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr [[P]], align 4
208 ; CHECK-NEXT:    ret i32 [[RET]]
211   %cond = icmp ne i32 %i, 0
212   call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ]
213   br i1 %cond, label %A, label %B
215 A:                                                ; preds = %bb
216   ret i32 0
218 B:                                                ; preds = %bb
219   %ret = load i32, ptr %p, align 4
220   ret i32 %ret
223 define i32 @test4A(ptr %p, i32 %i) {
224 ; CHECK-LABEL: define {{[^@]+}}@test4A
225 ; CHECK-SAME: (ptr [[P:%.*]], i32 [[I:%.*]]) {
226 ; CHECK-NEXT:  bb:
227 ; CHECK-NEXT:    call void @may_throw()
228 ; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
229 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i32 32) ]
230 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
231 ; CHECK:       A:
232 ; CHECK-NEXT:    ret i32 0
233 ; CHECK:       B:
234 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr [[P]], align 4
235 ; CHECK-NEXT:    ret i32 [[RET]]
238   call void @may_throw()
239   %cond = icmp ne i32 %i, 0
240   call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ]
241   br i1 %cond, label %A, label %B
243 A:                                                ; preds = %bb
244   ret i32 0
246 B:                                                ; preds = %bb
247   %ret = load i32, ptr %p, align 4
248   ret i32 %ret
251 define i32 @test5(ptr dereferenceable(64) %p, i32 %i) {
252 ; CHECK-LABEL: define {{[^@]+}}@test5
253 ; CHECK-SAME: (ptr nonnull dereferenceable(64) [[P:%.*]], i32 [[I:%.*]]) {
254 ; CHECK-NEXT:  bb:
255 ; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
256 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
257 ; CHECK:       A:
258 ; CHECK-NEXT:    ret i32 0
259 ; CHECK:       B:
260 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr [[P]], align 4
261 ; CHECK-NEXT:    ret i32 [[RET]]
264   %cond = icmp ne i32 %i, 0
265   call void @llvm.assume(i1 true) [ "nonnull"(ptr %p), "dereferenceable"(ptr %p, i32 32) ]
266   br i1 %cond, label %A, label %B
268 A:                                                ; preds = %bb
269   ret i32 0
271 B:                                                ; preds = %bb
272   %ret = load i32, ptr %p, align 4
273   ret i32 %ret
276 define i32 @test5A(ptr dereferenceable(8) %p, i32 %i) {
277 ; CHECK-LABEL: define {{[^@]+}}@test5A
278 ; CHECK-SAME: (ptr dereferenceable(32) [[P:%.*]], i32 [[I:%.*]]) {
279 ; CHECK-NEXT:  bb:
280 ; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
281 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"(), "ignore"(ptr poison, i32 32) ]
282 ; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
283 ; CHECK:       A:
284 ; CHECK-NEXT:    ret i32 0
285 ; CHECK:       B:
286 ; CHECK-NEXT:    [[RET:%.*]] = load i32, ptr [[P]], align 4
287 ; CHECK-NEXT:    ret i32 [[RET]]
290   %cond = icmp ne i32 %i, 0
291   call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(ptr %p, i32 32) ]
292   br i1 %cond, label %A, label %B
294 A:                                                ; preds = %bb
295   ret i32 0
297 B:                                                ; preds = %bb
298   %ret = load i32, ptr %p, align 4
299   ret i32 %ret
302 define i32 @test6() {
303 ; CHECK-LABEL: define {{[^@]+}}@test6() {
304 ; CHECK-NEXT:  bb:
305 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
306 ; CHECK-NEXT:    call void @may_throw()
307 ; CHECK-NEXT:    ret i32 0
310   call void @llvm.assume(i1 true) [ "cold"() ]
311   call void @llvm.assume(i1 true) [ "cold"() ]
312   call void @may_throw()
313   call void @llvm.assume(i1 true) [ "cold"() ]
314   ret i32 0
317 define i32 @test7(ptr %p) {
318 ; CHECK-LABEL: define {{[^@]+}}@test7
319 ; CHECK-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]]) {
320 ; CHECK-NEXT:  bb:
321 ; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
322 ; CHECK-NEXT:    ret i32 0
325   call void @llvm.assume(i1 true) [ "cold"() ]
326   call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4) ]
327   call void @llvm.assume(i1 true) [ "dereferenceable"(ptr %p, i32 4) ]
328   call void @llvm.assume(i1 true) [ "align"(ptr %p, i32 4), "nonnull"(ptr %p) ]
329   ret i32 0
332 attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }