• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt -enable-new-pm=0 -domtree -assumption-cache-tracker -assume-simplify -verify --enable-knowledge-retention -S %s | FileCheck %s
3; RUN: opt -passes='require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s
4
5target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
6
7declare void @may_throw()
8declare void @llvm.assume(i1)
9
10define i32 @test1(i32* %0, i32* %1, i32 %2, i32 %3) {
11; CHECK-LABEL: define {{[^@]+}}@test1
12; CHECK-SAME: (i32* nonnull dereferenceable(4) [[TMP0:%.*]], i32* [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]])
13; CHECK-NEXT:    [[TMP5:%.*]] = icmp ne i32 [[TMP2]], 4
14; CHECK-NEXT:    br i1 [[TMP5]], label [[TMP6:%.*]], label [[A:%.*]]
15; CHECK:       6:
16; CHECK-NEXT:    [[TMP7:%.*]] = add nsw i32 [[TMP3]], [[TMP2]]
17; CHECK-NEXT:    call void @may_throw()
18; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[TMP0]], i64 4), "align"(i32* [[TMP1]], i64 4), "nonnull"(i32* [[TMP1]]) ]
19; CHECK-NEXT:    [[TMP8:%.*]] = load i32, i32* [[TMP0]], align 4
20; CHECK-NEXT:    [[TMP9:%.*]] = add nsw i32 [[TMP7]], [[TMP8]]
21; CHECK-NEXT:    store i32 0, i32* [[TMP0]], align 4
22; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP1]], align 4
23; CHECK-NEXT:    [[TMP11:%.*]] = add nsw i32 [[TMP9]], [[TMP10]]
24; CHECK-NEXT:    call void @may_throw()
25; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 4), "ignore"(i32* undef) ]
26; CHECK-NEXT:    store i32 [[TMP11]], i32* [[TMP1]], align 4
27; CHECK-NEXT:    br label [[B:%.*]]
28; CHECK:       A:
29; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[TMP0]], i64 4), "ignore"(i32* undef, i64 4), "ignore"(i32* undef) ]
30; CHECK-NEXT:    br label [[B]]
31; CHECK:       B:
32; CHECK-NEXT:    ret i32 0
33;
34  %5 = icmp ne i32 %2, 4
35  call void @llvm.assume(i1 true) ["dereferenceable"(i32* %0, i64 4), "nonnull"(i32* %0) ]
36  br i1 %5, label %6, label %A
37
386:                                                ; preds = %4
39  %7 = add nsw i32 %3, %2
40  call void @may_throw()
41  %8 = load i32, i32* %0, align 4
42  %9 = add nsw i32 %7, %8
43  store i32 0, i32* %0, align 4
44  call void @llvm.assume(i1 true) [ "align"(i32* %0, i64 4), "dereferenceable"(i32* %0, i64 4) ]
45  %10 = load i32, i32* %1, align 4
46  %11 = add nsw i32 %9, %10
47  call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "nonnull"(i32* %1) ]
48  call void @may_throw()
49  call void @llvm.assume(i1 true) [ "dereferenceable"(i32* %1, i64 4), "nonnull"(i32* %1) ]
50  store i32 %11, i32* %1, align 4
51  br label %B
52
53A:
54  call void @llvm.assume(i1 true) [ "align"(i32* %0, i64 4), "dereferenceable"(i32* %0, i64 4), "nonnull"(i32* %0) ]
55  br label %B
56
57B:                                               ; preds = %6, %4
58  ret i32 0
59}
60
61define i32 @test2(i32** %0, i32* %1, i32 %2, i32 %3) {
62; CHECK-LABEL: define {{[^@]+}}@test2
63; CHECK-SAME: (i32** [[TMP0:%.*]], i32* nonnull align 4 dereferenceable(4) [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[TMP3:%.*]])
64; CHECK-NEXT:    [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 0
65; CHECK-NEXT:    [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 4
66; CHECK-NEXT:    [[TMP7:%.*]] = icmp ne i32 [[TMP6]], 0
67; CHECK-NEXT:    [[TMP8:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 0
68; CHECK-NEXT:    br i1 [[TMP7]], label [[TMP9:%.*]], label [[TMP19:%.*]]
69; CHECK:       9:
70; CHECK-NEXT:    call void @may_throw()
71; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32* [[TMP8]], i64 4), "dereferenceable"(i32* [[TMP8]], i64 4), "nonnull"(i32* [[TMP8]]) ]
72; CHECK-NEXT:    [[TMP10:%.*]] = load i32, i32* [[TMP8]], align 4
73; CHECK-NEXT:    [[TMP11:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 2
74; CHECK-NEXT:    store i32 [[TMP10]], i32* [[TMP11]], align 4
75; CHECK-NEXT:    call void @may_throw()
76; CHECK-NEXT:    call void @may_throw()
77; CHECK-NEXT:    [[TMP12:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 1
78; CHECK-NEXT:    [[TMP13:%.*]] = load i32*, i32** [[TMP12]], align 8
79; CHECK-NEXT:    [[TMP14:%.*]] = getelementptr inbounds i32, i32* [[TMP13]], i64 0
80; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[TMP1]], i64 12), "align"(i32* [[TMP13]], i64 4), "dereferenceable"(i32* [[TMP13]], i64 4), "nonnull"(i32* [[TMP13]]) ]
81; CHECK-NEXT:    [[TMP15:%.*]] = load i32, i32* [[TMP14]], align 4
82; CHECK-NEXT:    [[TMP16:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 1
83; CHECK-NEXT:    [[TMP17:%.*]] = load i32*, i32** [[TMP16]], align 8
84; CHECK-NEXT:    [[TMP18:%.*]] = getelementptr inbounds i32, i32* [[TMP17]], i64 2
85; CHECK-NEXT:    store i32 [[TMP15]], i32* [[TMP18]], align 4
86; CHECK-NEXT:    call void @may_throw()
87; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ]
88; CHECK-NEXT:    br label [[TMP35:%.*]]
89; CHECK:       19:
90; CHECK-NEXT:    [[TMP20:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 7
91; CHECK-NEXT:    [[TMP21:%.*]] = load i32*, i32** [[TMP20]], align 8
92; CHECK-NEXT:    [[TMP22:%.*]] = getelementptr inbounds i32, i32* [[TMP21]], i64 0
93; CHECK-NEXT:    [[TMP23:%.*]] = load i32, i32* [[TMP22]], align 4
94; CHECK-NEXT:    [[TMP24:%.*]] = icmp ne i32 [[TMP23]], 0
95; CHECK-NEXT:    br i1 [[TMP24]], label [[TMP25:%.*]], label [[TMP33:%.*]]
96; CHECK:       25:
97; CHECK-NEXT:    call void @may_throw()
98; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ]
99; CHECK-NEXT:    [[TMP26:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 2
100; CHECK-NEXT:    [[TMP27:%.*]] = load i32*, i32** [[TMP26]], align 8
101; CHECK-NEXT:    [[TMP28:%.*]] = getelementptr inbounds i32, i32* [[TMP27]], i64 0
102; CHECK-NEXT:    [[TMP29:%.*]] = load i32, i32* [[TMP28]], align 4
103; CHECK-NEXT:    [[TMP30:%.*]] = getelementptr inbounds i32*, i32** [[TMP0]], i64 2
104; CHECK-NEXT:    [[TMP31:%.*]] = load i32*, i32** [[TMP30]], align 8
105; CHECK-NEXT:    [[TMP32:%.*]] = getelementptr inbounds i32, i32* [[TMP31]], i64 2
106; CHECK-NEXT:    store i32 [[TMP29]], i32* [[TMP32]], align 4
107; CHECK-NEXT:    call void @may_throw()
108; CHECK-NEXT:    br label [[TMP33]]
109; CHECK:       33:
110; CHECK-NEXT:    br label [[TMP34:%.*]]
111; CHECK:       34:
112; CHECK-NEXT:    br label [[TMP35]]
113; CHECK:       35:
114; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "align"(i32** [[TMP0]], i64 4), "dereferenceable"(i32** [[TMP0]], i64 4), "nonnull"(i32** [[TMP0]]) ]
115; CHECK-NEXT:    ret i32 0
116;
117  %5 = getelementptr inbounds i32, i32* %1, i64 0
118  %6 = load i32, i32* %5, align 4
119  %7 = icmp ne i32 %6, 0
120  call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "dereferenceable"(i32* %1, i64 4) ]
121  call void @llvm.assume(i1 true) [ "align"(i32* %1, i64 4), "nonnull"(i32* %1) ]
122  %8 = getelementptr inbounds i32, i32* %1, i64 0
123  br i1 %7, label %9, label %19
124
1259:                                                ; preds = %4
126  call void @may_throw()
127  call void @llvm.assume(i1 true) [ "align"(i32* %8, i64 4), "dereferenceable"(i32* %8, i64 4), "nonnull"(i32* %8) ]
128  %10 = load i32, i32* %8, align 4
129  %11 = getelementptr inbounds i32, i32* %1, i64 2
130  store i32 %10, i32* %11, align 4
131  call void @may_throw()
132  call void @may_throw()
133  call void @llvm.assume(i1 true) [ "align"(i32* %11, i64 4), "dereferenceable"(i32* %11, i64 4), "nonnull"(i32* %11) ]
134  %12 = getelementptr inbounds i32*, i32** %0, i64 1
135  %13 = load i32*, i32** %12, align 8
136  %14 = getelementptr inbounds i32, i32* %13, i64 0
137  %15 = load i32, i32* %14, align 4
138  call void @llvm.assume(i1 true) [ "align"(i32* %14, i64 4), "dereferenceable"(i32* %14, i64 4), "nonnull"(i32* %14) ]
139  %16 = getelementptr inbounds i32*, i32** %0, i64 1
140  %17 = load i32*, i32** %16, align 8
141  %18 = getelementptr inbounds i32, i32* %17, i64 2
142  store i32 %15, i32* %18, align 4
143  call void @may_throw()
144  call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ]
145  br label %35
146
14719:                                               ; preds = %4
148  %20 = getelementptr inbounds i32*, i32** %0, i64 7
149  %21 = load i32*, i32** %20, align 8
150  %22 = getelementptr inbounds i32, i32* %21, i64 0
151  %23 = load i32, i32* %22, align 4
152  %24 = icmp ne i32 %23, 0
153  br i1 %24, label %25, label %33
154
15525:                                               ; preds = %19
156  call void @may_throw()
157  call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ]
158  %26 = getelementptr inbounds i32*, i32** %0, i64 2
159  %27 = load i32*, i32** %26, align 8
160  %28 = getelementptr inbounds i32, i32* %27, i64 0
161  %29 = load i32, i32* %28, align 4
162  %30 = getelementptr inbounds i32*, i32** %0, i64 2
163  %31 = load i32*, i32** %30, align 8
164  %32 = getelementptr inbounds i32, i32* %31, i64 2
165  store i32 %29, i32* %32, align 4
166  call void @may_throw()
167  br label %33
168
16933:                                               ; preds = %25, %19
170  br label %34
171
17234:                                               ; preds = %33
173  br label %35
174
17535:                                               ; preds = %34, %8
176  call void @llvm.assume(i1 true) [ "align"(i32** %0, i64 4), "dereferenceable"(i32** %0, i64 4), "nonnull"(i32** %0) ]
177  ret i32 0
178}
179
180define i32 @test3(i32* nonnull %p, i32 %i) {
181; CHECK-LABEL: define {{[^@]+}}@test3
182; CHECK-SAME: (i32* nonnull [[P:%.*]], i32 [[I:%.*]])
183; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
184; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
185; CHECK:       A:
186; CHECK-NEXT:    ret i32 0
187; CHECK:       B:
188; CHECK-NEXT:    [[RET:%.*]] = load i32, i32* [[P]]
189; CHECK-NEXT:    ret i32 [[RET]]
190;
191  %cond = icmp ne i32 %i, 0
192  call void @llvm.assume(i1 true) [ "nonnull"(i32* %p) ]
193  br i1 %cond, label %A, label %B
194A:
195  ret i32 0
196B:
197  %ret = load i32, i32* %p
198  ret i32 %ret
199}
200
201define i32 @test4(i32* %p, i32 %i) {
202; CHECK-LABEL: define {{[^@]+}}@test4
203; CHECK-SAME: (i32* nonnull dereferenceable(32) [[P:%.*]], i32 [[I:%.*]])
204; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
205; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
206; CHECK:       A:
207; CHECK-NEXT:    ret i32 0
208; CHECK:       B:
209; CHECK-NEXT:    [[RET:%.*]] = load i32, i32* [[P]]
210; CHECK-NEXT:    ret i32 [[RET]]
211;
212  %cond = icmp ne i32 %i, 0
213  call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ]
214  br i1 %cond, label %A, label %B
215A:
216  ret i32 0
217B:
218  %ret = load i32, i32* %p
219  ret i32 %ret
220}
221
222define i32 @test4A(i32* %p, i32 %i) {
223; CHECK-LABEL: define {{[^@]+}}@test4A
224; CHECK-SAME: (i32* [[P:%.*]], i32 [[I:%.*]])
225; CHECK-NEXT:    call void @may_throw()
226; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
227; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(i32* [[P]]), "dereferenceable"(i32* [[P]], i32 32) ]
228; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
229; CHECK:       A:
230; CHECK-NEXT:    ret i32 0
231; CHECK:       B:
232; CHECK-NEXT:    [[RET:%.*]] = load i32, i32* [[P]]
233; CHECK-NEXT:    ret i32 [[RET]]
234;
235  call void @may_throw()
236  %cond = icmp ne i32 %i, 0
237  call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ]
238  br i1 %cond, label %A, label %B
239A:
240  ret i32 0
241B:
242  %ret = load i32, i32* %p
243  ret i32 %ret
244}
245
246define i32 @test5(i32* dereferenceable(64) %p, i32 %i) {
247; CHECK-LABEL: define {{[^@]+}}@test5
248; CHECK-SAME: (i32* nonnull dereferenceable(64) [[P:%.*]], i32 [[I:%.*]])
249; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
250; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
251; CHECK:       A:
252; CHECK-NEXT:    ret i32 0
253; CHECK:       B:
254; CHECK-NEXT:    [[RET:%.*]] = load i32, i32* [[P]]
255; CHECK-NEXT:    ret i32 [[RET]]
256;
257  %cond = icmp ne i32 %i, 0
258  call void @llvm.assume(i1 true) [ "nonnull"(i32* %p), "dereferenceable"(i32* %p, i32 32) ]
259  br i1 %cond, label %A, label %B
260A:
261  ret i32 0
262B:
263  %ret = load i32, i32* %p
264  ret i32 %ret
265}
266
267
268define i32 @test5A(i32* dereferenceable(8) %p, i32 %i) {
269; CHECK-LABEL: define {{[^@]+}}@test5A
270; CHECK-SAME: (i32* dereferenceable(32) [[P:%.*]], i32 [[I:%.*]])
271; CHECK-NEXT:    [[COND:%.*]] = icmp ne i32 [[I]], 0
272; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"(), "ignore"(i32* undef, i32 32) ]
273; CHECK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
274; CHECK:       A:
275; CHECK-NEXT:    ret i32 0
276; CHECK:       B:
277; CHECK-NEXT:    [[RET:%.*]] = load i32, i32* [[P]]
278; CHECK-NEXT:    ret i32 [[RET]]
279;
280  %cond = icmp ne i32 %i, 0
281  call void @llvm.assume(i1 true) [ "cold"(), "dereferenceable"(i32* %p, i32 32) ]
282  br i1 %cond, label %A, label %B
283A:
284  ret i32 0
285B:
286  %ret = load i32, i32* %p
287  ret i32 %ret
288}
289
290define i32 @test6() {
291; CHECK-LABEL: define {{[^@]+}}@test6()
292; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
293; CHECK-NEXT:    call void @may_throw()
294; CHECK-NEXT:    ret i32 0
295;
296  call void @llvm.assume(i1 true) [ "cold"() ]
297  call void @llvm.assume(i1 true) [ "cold"() ]
298  call void @may_throw()
299  call void @llvm.assume(i1 true) [ "cold"() ]
300  ret i32 0
301}
302
303define i32 @test7(i32* %p) {
304; CHECK-LABEL: define {{[^@]+}}@test7
305; CHECK-SAME: (i32* align 4 dereferenceable(4) [[P:%.*]])
306; CHECK-NEXT:    [[P1:%.*]] = bitcast i32* [[P]] to i8*
307; CHECK-NEXT:    call void @llvm.assume(i1 true) [ "cold"(), "nonnull"(i32* [[P]]) ]
308; CHECK-NEXT:    ret i32 0
309;
310  %p1 = bitcast i32* %p to i8*
311  call void @llvm.assume(i1 true) [ "cold"() ]
312  call void @llvm.assume(i1 true) [ "align"(i32* %p, i32 4) ]
313  call void @llvm.assume(i1 true) [ "dereferenceable"(i32* %p, i32 4) ]
314  call void @llvm.assume(i1 true) [ "align"(i8* %p1, i32 4), "nonnull"(i8* %p1) ]
315  ret i32 0
316}
317