[rtsan] Add fork/execve interceptors (#117198)
[llvm-project.git] / llvm / test / Transforms / GVN / metadata.ll
bloba5dbb5ee060701bd8a77eb756d61c4154bf2177a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals --version 2
2 ; RUN: opt -passes=gvn -S < %s | FileCheck %s
4 declare void @use.ptr(ptr) memory(none)
5 declare void @use.i64(i64) memory(none)
6 declare void @use.i32(i32) memory(none)
8 define i32 @test1(ptr %p) {
9 ; CHECK-LABEL: define i32 @test1
10 ; CHECK-SAME: (ptr [[P:%.*]]) {
11 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]]
12 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
13 ; CHECK-NEXT:    ret i32 [[C]]
15   %a = load i32, ptr %p, !range !0
16   %b = load i32, ptr %p, !range !0
17   %c = add i32 %a, %b
18   ret i32 %c
21 define i32 @test2(ptr %p) {
22 ; CHECK-LABEL: define i32 @test2
23 ; CHECK-SAME: (ptr [[P:%.*]]) {
24 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4
25 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
26 ; CHECK-NEXT:    ret i32 [[C]]
28   %a = load i32, ptr %p, !range !0
29   %b = load i32, ptr %p
30   %c = add i32 %a, %b
31   ret i32 %c
34 define i32 @test3(ptr %p) {
35 ; CHECK-LABEL: define i32 @test3
36 ; CHECK-SAME: (ptr [[P:%.*]]) {
37 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1:![0-9]+]]
38 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
39 ; CHECK-NEXT:    ret i32 [[C]]
41   %a = load i32, ptr %p, !range !0
42   %b = load i32, ptr %p, !range !1
43   %c = add i32 %a, %b
44   ret i32 %c
47 define i32 @test4(ptr %p) {
48 ; CHECK-LABEL: define i32 @test4
49 ; CHECK-SAME: (ptr [[P:%.*]]) {
50 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG2:![0-9]+]]
51 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
52 ; CHECK-NEXT:    ret i32 [[C]]
54   %a = load i32, ptr %p, !range !0
55   %b = load i32, ptr %p, !range !2
56   %c = add i32 %a, %b
57   ret i32 %c
60 define i32 @test5(ptr %p) {
61 ; CHECK-LABEL: define i32 @test5
62 ; CHECK-SAME: (ptr [[P:%.*]]) {
63 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG3:![0-9]+]]
64 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
65 ; CHECK-NEXT:    ret i32 [[C]]
67   %a = load i32, ptr %p, !range !3
68   %b = load i32, ptr %p, !range !4
69   %c = add i32 %a, %b
70   ret i32 %c
73 define i32 @test6(ptr %p) {
74 ; CHECK-LABEL: define i32 @test6
75 ; CHECK-SAME: (ptr [[P:%.*]]) {
76 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG4:![0-9]+]]
77 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
78 ; CHECK-NEXT:    ret i32 [[C]]
80   %a = load i32, ptr %p, !range !5
81   %b = load i32, ptr %p, !range !6
82   %c = add i32 %a, %b
83   ret i32 %c
86 define i32 @test7(ptr %p) {
87 ; CHECK-LABEL: define i32 @test7
88 ; CHECK-SAME: (ptr [[P:%.*]]) {
89 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG5:![0-9]+]]
90 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
91 ; CHECK-NEXT:    ret i32 [[C]]
93   %a = load i32, ptr %p, !range !7
94   %b = load i32, ptr %p, !range !8
95   %c = add i32 %a, %b
96   ret i32 %c
99 define i32 @test8(ptr %p) {
100 ; CHECK-LABEL: define i32 @test8
101 ; CHECK-SAME: (ptr [[P:%.*]]) {
102 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4
103 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
104 ; CHECK-NEXT:    ret i32 [[C]]
106   %a = load i32, ptr %p, !range !9
107   %b = load i32, ptr %p, !range !10
108   %c = add i32 %a, %b
109   ret i32 %c
112 define i32 @load_noundef_load(ptr %p) {
113 ; CHECK-LABEL: define i32 @load_noundef_load
114 ; CHECK-SAME: (ptr [[P:%.*]]) {
115 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]], !noundef !6
116 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
117 ; CHECK-NEXT:    ret i32 [[C]]
119   %a = load i32, ptr %p, !range !0, !noundef !11
120   %b = load i32, ptr %p, !range !1
121   %c = add i32 %a, %b
122   ret i32 %c
125 define i32 @load_load_noundef(ptr %p) {
126 ; CHECK-LABEL: define i32 @load_load_noundef
127 ; CHECK-SAME: (ptr [[P:%.*]]) {
128 ; CHECK-NEXT:    [[A:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG1]]
129 ; CHECK-NEXT:    [[C:%.*]] = add i32 [[A]], [[A]]
130 ; CHECK-NEXT:    ret i32 [[C]]
132   %a = load i32, ptr %p, !range !0
133   %b = load i32, ptr %p, !range !1, !noundef !11
134   %c = add i32 %a, %b
135   ret i32 %c
138 define void @load_dereferenceable_dominating(ptr %p) {
139 ; CHECK-LABEL: define void @load_dereferenceable_dominating
140 ; CHECK-SAME: (ptr [[P:%.*]]) {
141 ; CHECK-NEXT:    [[A:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
142 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
143 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
144 ; CHECK-NEXT:    ret void
146   %a = load ptr, ptr %p, !dereferenceable !{i64 10}
147   %b = load ptr, ptr %p
148   call void @use.ptr(ptr %a)
149   call void @use.ptr(ptr %b)
150   ret void
153 define void @load_dereferenceable_not_dominating(ptr %p) {
154 ; CHECK-LABEL: define void @load_dereferenceable_not_dominating
155 ; CHECK-SAME: (ptr [[P:%.*]]) {
156 ; CHECK-NEXT:    [[A:%.*]] = load ptr, ptr [[P]], align 8
157 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
158 ; CHECK-NEXT:    call void @use.ptr(ptr [[A]])
159 ; CHECK-NEXT:    ret void
161   %a = load ptr, ptr %p
162   %b = load ptr, ptr %p, !dereferenceable !{i64 10}
163   call void @use.ptr(ptr %a)
164   call void @use.ptr(ptr %b)
165   ret void
168 define void @load_ptr_nonnull_to_i64(ptr %p) {
169 ; CHECK-LABEL: define void @load_ptr_nonnull_to_i64
170 ; CHECK-SAME: (ptr [[P:%.*]]) {
171 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8
172 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
173 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
174 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
175 ; CHECK-NEXT:    ret void
177   %val = load ptr, ptr %p, align 8, !nonnull !{}
178   %val.int = ptrtoint ptr %val to i64
179   %val2 = load i64, ptr %p, align 8
180   call void @use.i64(i64 %val.int)
181   call void @use.i64(i64 %val2)
182   ret void
185 define void @load_ptr_nonnull_noundef_to_i64(ptr %p) {
186 ; CHECK-LABEL: define void @load_ptr_nonnull_noundef_to_i64
187 ; CHECK-SAME: (ptr [[P:%.*]]) {
188 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !nonnull !6, !noundef !6
189 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
190 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
191 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
192 ; CHECK-NEXT:    ret void
194   %val = load ptr, ptr %p, align 8, !nonnull !{}, !noundef !{}
195   %val.int = ptrtoint ptr %val to i64
196   %val2 = load i64, ptr %p, align 8
197   call void @use.i64(i64 %val.int)
198   call void @use.i64(i64 %val2)
199   ret void
202 define void @load_ptr_invariant_load_to_i64(ptr %p) {
203 ; CHECK-LABEL: define void @load_ptr_invariant_load_to_i64
204 ; CHECK-SAME: (ptr [[P:%.*]]) {
205 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !invariant.load !6
206 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
207 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
208 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
209 ; CHECK-NEXT:    ret void
211   %val = load ptr, ptr %p, align 8, !invariant.load !{}
212   %val.int = ptrtoint ptr %val to i64
213   %val2 = load i64, ptr %p, align 8
214   call void @use.i64(i64 %val.int)
215   call void @use.i64(i64 %val2)
216   ret void
219 define void @load_ptr_dereferenceable_to_i64(ptr %p) {
220 ; CHECK-LABEL: define void @load_ptr_dereferenceable_to_i64
221 ; CHECK-SAME: (ptr [[P:%.*]]) {
222 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable !7
223 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
224 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
225 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
226 ; CHECK-NEXT:    ret void
228   %val = load ptr, ptr %p, align 8, !dereferenceable !{i64 10}
229   %val.int = ptrtoint ptr %val to i64
230   %val2 = load i64, ptr %p, align 8
231   call void @use.i64(i64 %val.int)
232   call void @use.i64(i64 %val2)
233   ret void
236 define void @load_ptr_dereferenceable_or_null_to_i64(ptr %p) {
237 ; CHECK-LABEL: define void @load_ptr_dereferenceable_or_null_to_i64
238 ; CHECK-SAME: (ptr [[P:%.*]]) {
239 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8, !dereferenceable_or_null !7
240 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
241 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
242 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
243 ; CHECK-NEXT:    ret void
245   %val = load ptr, ptr %p, align 8, !dereferenceable_or_null !{i64 10}
246   %val.int = ptrtoint ptr %val to i64
247   %val2 = load i64, ptr %p, align 8
248   call void @use.i64(i64 %val.int)
249   call void @use.i64(i64 %val2)
250   ret void
253 define void @load_ptr_nonnull_to_i32(ptr %p) {
254 ; CHECK-LABEL: define void @load_ptr_nonnull_to_i32
255 ; CHECK-SAME: (ptr [[P:%.*]]) {
256 ; CHECK-NEXT:    [[VAL:%.*]] = load ptr, ptr [[P]], align 8
257 ; CHECK-NEXT:    [[VAL_INT:%.*]] = ptrtoint ptr [[VAL]] to i64
258 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[VAL_INT]] to i32
259 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL_INT]])
260 ; CHECK-NEXT:    call void @use.i32(i32 [[TMP1]])
261 ; CHECK-NEXT:    ret void
263   %val = load ptr, ptr %p, align 8, !nonnull !{}
264   %val.int = ptrtoint ptr %val to i64
265   %val2 = load i32, ptr %p, align 8
266   call void @use.i64(i64 %val.int)
267   call void @use.i32(i32 %val2)
268   ret void
271 define void @load_i64_range_to_i32_range(ptr %p) {
272 ; CHECK-LABEL: define void @load_i64_range_to_i32_range
273 ; CHECK-SAME: (ptr [[P:%.*]]) {
274 ; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[P]], align 8
275 ; CHECK-NEXT:    [[TMP1:%.*]] = trunc i64 [[VAL]] to i32
276 ; CHECK-NEXT:    call void @use.i64(i64 [[VAL]])
277 ; CHECK-NEXT:    call void @use.i32(i32 [[TMP1]])
278 ; CHECK-NEXT:    ret void
280   %val = load i64, ptr %p, align 8, !range !{i64 0, i64 10}
281   %val2 = load i32, ptr %p, align 8, !range !{i32 0, i32 10}
282   call void @use.i64(i64 %val)
283   call void @use.i32(i32 %val2)
284   ret void
287 define i64 @load_is_stored(ptr %p, ptr %p2) {
288 ; CHECK-LABEL: define i64 @load_is_stored
289 ; CHECK-SAME: (ptr [[P:%.*]], ptr [[P2:%.*]]) {
290 ; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG8:![0-9]+]]
291 ; CHECK-NEXT:    store i64 [[V1]], ptr [[P2]], align 4
292 ; CHECK-NEXT:    ret i64 [[V1]]
294   %v1 = load i64, ptr %p, !range !{i64 0, i64 10}
295   store i64 %v1, ptr %p2
296   %v2 = load i64, ptr %p2
297   ret i64 %v2
300 define void @non_local_dominating(i1 %c, ptr %p) {
301 ; CHECK-LABEL: define void @non_local_dominating
302 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
303 ; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9:![0-9]+]]
304 ; CHECK-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]
305 ; CHECK:       if:
306 ; CHECK-NEXT:    br label [[JOIN]]
307 ; CHECK:       join:
308 ; CHECK-NEXT:    call void @use.i64(i64 [[V1]])
309 ; CHECK-NEXT:    call void @use.i64(i64 [[V1]])
310 ; CHECK-NEXT:    ret void
312   %v1 = load i64, ptr %p, !range !{i64 0, i64 10}
313   br i1 %c, label %if, label %join
316   br label %join
318 join:
319   %v2 = load i64, ptr %p, !range !{i64 20, i64 30}
320   call void @use.i64(i64 %v1)
321   call void @use.i64(i64 %v2)
322   ret void
325 define void @non_local_non_dominating(i1 %c, ptr %p) {
326 ; CHECK-LABEL: define void @non_local_non_dominating
327 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
328 ; CHECK-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
329 ; CHECK:       if:
330 ; CHECK-NEXT:    [[V1:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9]]
331 ; CHECK-NEXT:    call void @use.i64(i64 [[V1]])
332 ; CHECK-NEXT:    br label [[JOIN:%.*]]
333 ; CHECK:       else:
334 ; CHECK-NEXT:    [[V2:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG10:![0-9]+]]
335 ; CHECK-NEXT:    call void @use.i64(i64 [[V2]])
336 ; CHECK-NEXT:    br label [[JOIN]]
337 ; CHECK:       join:
338 ; CHECK-NEXT:    [[V3:%.*]] = phi i64 [ [[V2]], [[ELSE]] ], [ [[V1]], [[IF]] ]
339 ; CHECK-NEXT:    call void @use.i64(i64 [[V3]])
340 ; CHECK-NEXT:    ret void
342   br i1 %c, label %if, label %else
345   %v1 = load i64, ptr %p, !range !{i64 0, i64 10}
346   call void @use.i64(i64 %v1)
347   br label %join
349 else:
350   %v2 = load i64, ptr %p, !range !{i64 10, i64 20}
351   call void @use.i64(i64 %v2)
352   br label %join
354 join:
355   %v3 = load i64, ptr %p, !range !{i64 20, i64 30}
356   call void @use.i64(i64 %v3)
357   ret void
360 define void @non_local_coerced(i1 %c, ptr %p) {
361 ; CHECK-LABEL: define void @non_local_coerced
362 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
363 ; CHECK-NEXT:    [[V1_PTR:%.*]] = load ptr, ptr [[P]], align 8
364 ; CHECK-NEXT:    [[V1:%.*]] = ptrtoint ptr [[V1_PTR]] to i64
365 ; CHECK-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]
366 ; CHECK:       if:
367 ; CHECK-NEXT:    br label [[JOIN]]
368 ; CHECK:       join:
369 ; CHECK-NEXT:    call void @use.i64(i64 [[V1]])
370 ; CHECK-NEXT:    call void @use.i64(i64 [[V1]])
371 ; CHECK-NEXT:    ret void
373   %v1.ptr = load ptr, ptr %p, !nonnull !{}
374   %v1 = ptrtoint ptr %v1.ptr to i64
375   br i1 %c, label %if, label %join
378   br label %join
380 join:
381   %v2 = load i64, ptr %p, !range !{i64 20, i64 30}
382   call void @use.i64(i64 %v1)
383   call void @use.i64(i64 %v2)
384   ret void
387 define void @non_local_pre(i1 %c, ptr %p) {
388 ; CHECK-LABEL: define void @non_local_pre
389 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
390 ; CHECK-NEXT:    [[V2_PRE:%.*]] = load i64, ptr [[P]], align 4, !range [[RNG9]]
391 ; CHECK-NEXT:    br i1 [[C]], label [[IF:%.*]], label [[JOIN:%.*]]
392 ; CHECK:       if:
393 ; CHECK-NEXT:    call void @use.i64(i64 [[V2_PRE]])
394 ; CHECK-NEXT:    br label [[JOIN]]
395 ; CHECK:       join:
396 ; CHECK-NEXT:    call void @use.i64(i64 [[V2_PRE]])
397 ; CHECK-NEXT:    ret void
399   br i1 %c, label %if, label %join
402   %v1 = load i64, ptr %p, !range !{i64 0, i64 10}
403   call void @use.i64(i64 %v1)
404   br label %join
406 join:
407   %v2 = load i64, ptr %p, !range !{i64 20, i64 30}
408   call void @use.i64(i64 %v2)
409   ret void
412 !0 = !{i32 0, i32 2}
413 !1 = !{i32 3, i32 5}
414 !2 = !{i32 2, i32 5}
415 !3 = !{i32 -5, i32 -2}
416 !4 = !{i32 1, i32 5}
417 !5 = !{i32 10, i32 1}
418 !6 = !{i32 12, i32 16}
419 !7 = !{i32 1, i32 2, i32 3, i32 4}
420 !8 = !{i32 5, i32 1}
421 !9 = !{i32 1, i32 5}
422 !10 = !{i32 5, i32 1}
423 !11 = !{}
425 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { memory(none) }
427 ; CHECK: [[RNG0]] = !{i32 0, i32 2}
428 ; CHECK: [[RNG1]] = !{i32 0, i32 2, i32 3, i32 5}
429 ; CHECK: [[RNG2]] = !{i32 0, i32 5}
430 ; CHECK: [[RNG3]] = !{i32 -5, i32 -2, i32 1, i32 5}
431 ; CHECK: [[RNG4]] = !{i32 10, i32 1}
432 ; CHECK: [[RNG5]] = !{i32 3, i32 4, i32 5, i32 2}
433 ; CHECK: [[META6:![0-9]+]] = !{}
434 ; CHECK: [[META7:![0-9]+]] = !{i64 10}
435 ; CHECK: [[RNG8]] = !{i64 0, i64 10}
436 ; CHECK: [[RNG9]] = !{i64 0, i64 10, i64 20, i64 30}
437 ; CHECK: [[RNG10]] = !{i64 10, i64 30}