xref: /llvm-project/llvm/test/Transforms/Util/assume-simplify.ll (revision 344d972736fc0030d1dd7e2e9709535e8d648f24)
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
3
4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
5
6declare void @may_throw()
7
8declare void @llvm.assume(i1 noundef) #0
9
10define 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
34;
35bb:
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
39
40bb4:                                              ; 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
54
55A:                                                ; 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
58
59B:                                                ; preds = %A, %bb4
60  ret i32 0
61}
62
63define 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
113;
114bb:
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
120
121bb7:                                              ; 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
141
142bb17:                                             ; 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
148
149bb23:                                             ; 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
161
162bb31:                                             ; preds = %bb23, %bb17
163  br label %bb32
164
165bb32:                                             ; preds = %bb31
166  br label %bb33
167
168bb33:                                             ; 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
171}
172
173define 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]]
184;
185bb:
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
189
190A:                                                ; preds = %bb
191  ret i32 0
192
193B:                                                ; preds = %bb
194  %ret = load i32, ptr %p, align 4
195  ret i32 %ret
196}
197
198define 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]]
209;
210bb:
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
214
215A:                                                ; preds = %bb
216  ret i32 0
217
218B:                                                ; preds = %bb
219  %ret = load i32, ptr %p, align 4
220  ret i32 %ret
221}
222
223define 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]]
236;
237bb:
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
242
243A:                                                ; preds = %bb
244  ret i32 0
245
246B:                                                ; preds = %bb
247  %ret = load i32, ptr %p, align 4
248  ret i32 %ret
249}
250
251define 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]]
262;
263bb:
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
267
268A:                                                ; preds = %bb
269  ret i32 0
270
271B:                                                ; preds = %bb
272  %ret = load i32, ptr %p, align 4
273  ret i32 %ret
274}
275
276define 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]]
288;
289bb:
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
293
294A:                                                ; preds = %bb
295  ret i32 0
296
297B:                                                ; preds = %bb
298  %ret = load i32, ptr %p, align 4
299  ret i32 %ret
300}
301
302define 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
308;
309bb:
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
315}
316
317define 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
323;
324bb:
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
330}
331
332attributes #0 = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: readwrite) }
333