Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / Attributor / dereferenceable-2.ll
blob435544dc8e84459dd779ed43e7f94f18e02f7fc6
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
5 ; Determine dereference-ability before unused loads get deleted:
6 ; https://bugs.llvm.org/show_bug.cgi?id=21780
8 define <4 x double> @PR21780(ptr %ptr) {
9 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
10 ; CHECK-LABEL: define {{[^@]+}}@PR21780
11 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
12 ; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 1
13 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 2
14 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 3
15 ; CHECK-NEXT:    [[T0:%.*]] = load double, ptr [[PTR]], align 8
16 ; CHECK-NEXT:    [[T1:%.*]] = load double, ptr [[ARRAYIDX1]], align 8
17 ; CHECK-NEXT:    [[T2:%.*]] = load double, ptr [[ARRAYIDX2]], align 8
18 ; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 8
19 ; CHECK-NEXT:    [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0
20 ; CHECK-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1
21 ; CHECK-NEXT:    [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2
22 ; CHECK-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3
23 ; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2>
24 ; CHECK-NEXT:    ret <4 x double> [[SHUFFLE]]
27   ; GEP of index 0 is simplified away.
28   %arrayidx1 = getelementptr inbounds double, ptr %ptr, i64 1
29   %arrayidx2 = getelementptr inbounds double, ptr %ptr, i64 2
30   %arrayidx3 = getelementptr inbounds double, ptr %ptr, i64 3
32   %t0 = load double, ptr %ptr, align 8
33   %t1 = load double, ptr %arrayidx1, align 8
34   %t2 = load double, ptr %arrayidx2, align 8
35   %t3 = load double, ptr %arrayidx3, align 8
37   %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
38   %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
39   %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
40   %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
41   %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
42   ret <4 x double> %shuffle
46 define double @PR21780_only_access3_with_inbounds(ptr %ptr) {
47 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
48 ; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds
49 ; CHECK-SAME: (ptr nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {
50 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, ptr [[PTR]], i64 3
51 ; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 8
52 ; CHECK-NEXT:    ret double [[T3]]
55   %arrayidx3 = getelementptr inbounds double, ptr %ptr, i64 3
56   %t3 = load double, ptr %arrayidx3, align 8
57   ret double %t3
60 define double @PR21780_only_access3_without_inbounds(ptr %ptr) {
61 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
62 ; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds
63 ; CHECK-SAME: (ptr nocapture nofree readonly align 8 [[PTR:%.*]]) #[[ATTR0]] {
64 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, ptr [[PTR]], i64 3
65 ; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 8
66 ; CHECK-NEXT:    ret double [[T3]]
68   %arrayidx3 = getelementptr double, ptr %ptr, i64 3
69   %t3 = load double, ptr %arrayidx3, align 8
70   ret double %t3
73 define double @PR21780_without_inbounds(ptr %ptr) {
74 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
75 ; CHECK-LABEL: define {{[^@]+}}@PR21780_without_inbounds
76 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {
77 ; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, ptr [[PTR]], i64 3
78 ; CHECK-NEXT:    [[T3:%.*]] = load double, ptr [[ARRAYIDX3]], align 8
79 ; CHECK-NEXT:    ret double [[T3]]
82   %arrayidx1 = getelementptr double, ptr %ptr, i64 1
83   %arrayidx2 = getelementptr double, ptr %ptr, i64 2
84   %arrayidx3 = getelementptr double, ptr %ptr, i64 3
86   %t0 = load double, ptr %ptr, align 8
87   %t1 = load double, ptr %arrayidx1, align 8
88   %t2 = load double, ptr %arrayidx2, align 8
89   %t3 = load double, ptr %arrayidx3, align 8
91   ret double %t3
94 ; Unsimplified, but still valid. Also, throw in some bogus arguments.
96 define void @gep0(ptr %unused, ptr %other, ptr %ptr) {
97 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite)
98 ; CHECK-LABEL: define {{[^@]+}}@gep0
99 ; CHECK-SAME: (ptr nocapture nofree readnone [[UNUSED:%.*]], ptr nocapture nofree noundef nonnull writeonly dereferenceable(1) [[OTHER:%.*]], ptr nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
100 ; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr i8, ptr [[PTR]], i64 2
101 ; CHECK-NEXT:    [[T2:%.*]] = load i8, ptr [[ARRAYIDX2]], align 1
102 ; CHECK-NEXT:    store i8 [[T2]], ptr [[OTHER]], align 1
103 ; CHECK-NEXT:    ret void
105   %arrayidx0 = getelementptr i8, ptr %ptr, i64 0
106   %arrayidx1 = getelementptr i8, ptr %ptr, i64 1
107   %arrayidx2 = getelementptr i8, ptr %ptr, i64 2
108   %t0 = load i8, ptr %arrayidx0
109   %t1 = load i8, ptr %arrayidx1
110   %t2 = load i8, ptr %arrayidx2
111   store i8 %t2, ptr %other
112   ret void
115 ; Order of accesses does not change computation.
116 ; Multiple arguments may be dereferenceable.
118 define void @ordering(ptr %ptr1, ptr %ptr2) {
119 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
120 ; CHECK-LABEL: define {{[^@]+}}@ordering
121 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone dereferenceable(3) [[PTR1:%.*]], ptr nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) #[[ATTR2:[0-9]+]] {
122 ; CHECK-NEXT:    ret void
124   %a20 = getelementptr i32, ptr %ptr2, i64 0
125   %a12 = getelementptr i8, ptr %ptr1, i64 2
126   %t12 = load i8, ptr %a12
127   %a11 = getelementptr i8, ptr %ptr1, i64 1
128   %t20 = load i32, ptr %a20
129   %t10 = load i8, ptr %ptr1
130   %t11 = load i8, ptr %a11
131   %a21 = getelementptr i32, ptr %ptr2, i64 1
132   %t21 = load i32, ptr %a21
133   ret void
136 ; Not in entry block.
138 define void @not_entry_but_guaranteed_to_execute(ptr %ptr) {
139 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
140 ; CHECK-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute
141 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) #[[ATTR2]] {
142 ; CHECK-NEXT:  entry:
143 ; CHECK-NEXT:    br label [[EXIT:%.*]]
144 ; CHECK:       exit:
145 ; CHECK-NEXT:    ret void
147 entry:
148   br label %exit
149 exit:
150   %arrayidx1 = getelementptr i8, ptr %ptr, i64 1
151   %arrayidx2 = getelementptr i8, ptr %ptr, i64 2
152   %t0 = load i8, ptr %ptr
153   %t1 = load i8, ptr %arrayidx1
154   %t2 = load i8, ptr %arrayidx2
155   ret void
158 ; Not in entry block and not guaranteed to execute.
160 define void @not_entry_not_guaranteed_to_execute(ptr %ptr, i1 %cond) {
161 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
162 ; CHECK-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute
163 ; CHECK-SAME: (ptr nocapture nofree readnone [[PTR:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR2]] {
164 ; CHECK-NEXT:  entry:
165 ; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
166 ; CHECK:       loads:
167 ; CHECK-NEXT:    ret void
168 ; CHECK:       exit:
169 ; CHECK-NEXT:    ret void
171 entry:
172   br i1 %cond, label %loads, label %exit
173 loads:
174   %arrayidx1 = getelementptr i8, ptr %ptr, i64 1
175   %arrayidx2 = getelementptr i8, ptr %ptr, i64 2
176   %t0 = load i8, ptr %ptr
177   %t1 = load i8, ptr %arrayidx1
178   %t2 = load i8, ptr %arrayidx2
179   ret void
180 exit:
181   ret void
184 ; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
186 define void @partial_in_entry(ptr %ptr, i1 %cond) {
187 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
188 ; CHECK-LABEL: define {{[^@]+}}@partial_in_entry
189 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 noundef [[COND:%.*]]) #[[ATTR2]] {
190 ; CHECK-NEXT:  entry:
191 ; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
192 ; CHECK:       loads:
193 ; CHECK-NEXT:    ret void
194 ; CHECK:       exit:
195 ; CHECK-NEXT:    ret void
197 entry:
198   %arrayidx1 = getelementptr i16, ptr %ptr, i64 1
199   %arrayidx2 = getelementptr i16, ptr %ptr, i64 2
200   %t0 = load i16, ptr %ptr
201   %t1 = load i16, ptr %arrayidx1
202   br i1 %cond, label %loads, label %exit
203 loads:
204   %t2 = load i16, ptr %arrayidx2
205   ret void
206 exit:
207   ret void
210 ; The volatile load can't be used to prove a non-volatile access is allowed.
211 ; The 2nd and 3rd loads may never execute.
213 define void @volatile_is_not_dereferenceable(ptr %ptr) {
214 ; CHECK: Function Attrs: mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite)
215 ; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
216 ; CHECK-SAME: (ptr nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
217 ; CHECK-NEXT:    [[T0:%.*]] = load volatile i16, ptr [[PTR]], align 2
218 ; CHECK-NEXT:    ret void
220   %arrayidx0 = getelementptr i16, ptr %ptr, i64 0
221   %arrayidx1 = getelementptr i16, ptr %ptr, i64 1
222   %arrayidx2 = getelementptr i16, ptr %ptr, i64 2
223   %t0 = load volatile i16, ptr %arrayidx0
224   %t1 = load i16, ptr %arrayidx1
225   %t2 = load i16, ptr %arrayidx2
226   ret void
229 ; TODO: We should allow inference for atomic (but not volatile) ops.
231 define void @atomic_is_alright(ptr %ptr) {
232 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
233 ; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright
234 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) #[[ATTR2]] {
235 ; CHECK-NEXT:    ret void
237   %arrayidx0 = getelementptr i16, ptr %ptr, i64 0
238   %arrayidx1 = getelementptr i16, ptr %ptr, i64 1
239   %arrayidx2 = getelementptr i16, ptr %ptr, i64 2
240   %t0 = load atomic i16, ptr %arrayidx0 unordered, align 2
241   %t1 = load i16, ptr %arrayidx1
242   %t2 = load i16, ptr %arrayidx2
243   ret void
246 declare void @may_not_return()
248 define void @not_guaranteed_to_transfer_execution(ptr %ptr) {
249 ; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution
250 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) {
251 ; CHECK-NEXT:    call void @may_not_return()
252 ; CHECK-NEXT:    ret void
254   %arrayidx0 = getelementptr i16, ptr %ptr, i64 0
255   %arrayidx1 = getelementptr i16, ptr %ptr, i64 1
256   %arrayidx2 = getelementptr i16, ptr %ptr, i64 2
257   %t0 = load i16, ptr %arrayidx0
258   call void @may_not_return()
259   %t1 = load i16, ptr %arrayidx1
260   %t2 = load i16, ptr %arrayidx2
261   ret void
264 ; We must have consecutive accesses.
266 define void @variable_gep_index(ptr %unused, ptr %ptr, i64 %variable_index) {
267 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
268 ; CHECK-LABEL: define {{[^@]+}}@variable_gep_index
269 ; CHECK-SAME: (ptr nocapture nofree readnone [[UNUSED:%.*]], ptr nocapture nofree noundef nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) #[[ATTR2]] {
270 ; CHECK-NEXT:    ret void
272   %arrayidx1 = getelementptr i8, ptr %ptr, i64 %variable_index
273   %arrayidx2 = getelementptr i8, ptr %ptr, i64 2
274   %t0 = load i8, ptr %ptr
275   %t1 = load i8, ptr %arrayidx1
276   %t2 = load i8, ptr %arrayidx2
277   ret void
280 ; Deal with >1 GEP index.
282 define void @multi_index_gep(ptr %ptr) {
283 ; FIXME: %ptr should be dereferenceable(4)
284 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
285 ; CHECK-LABEL: define {{[^@]+}}@multi_index_gep
286 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) #[[ATTR2]] {
287 ; CHECK-NEXT:    ret void
289   %arrayidx00 = getelementptr <4 x i8>, ptr %ptr, i64 0, i64 0
290   %t0 = load i8, ptr %arrayidx00
291   ret void
294 ; Could round weird bitwidths down?
296 define void @not_byte_multiple(ptr %ptr) {
297 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
298 ; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple
299 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) #[[ATTR2]] {
300 ; CHECK-NEXT:    ret void
302   %arrayidx0 = getelementptr i9, ptr %ptr, i64 0
303   %t0 = load i9, ptr %arrayidx0
304   ret void
307 ; Missing direct access from the pointer.
309 define void @no_pointer_deref(ptr %ptr) {
310 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
311 ; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref
312 ; CHECK-SAME: (ptr nocapture nofree readnone align 2 [[PTR:%.*]]) #[[ATTR2]] {
313 ; CHECK-NEXT:    ret void
315   %arrayidx1 = getelementptr i16, ptr %ptr, i64 1
316   %arrayidx2 = getelementptr i16, ptr %ptr, i64 2
317   %t1 = load i16, ptr %arrayidx1
318   %t2 = load i16, ptr %arrayidx2
319   ret void
322 ; Out-of-order is ok, but missing access concludes dereferenceable range.
324 define void @non_consecutive(ptr %ptr) {
325 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
326 ; CHECK-LABEL: define {{[^@]+}}@non_consecutive
327 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) #[[ATTR2]] {
328 ; CHECK-NEXT:    ret void
330   %arrayidx1 = getelementptr i32, ptr %ptr, i64 1
331   %arrayidx3 = getelementptr i32, ptr %ptr, i64 3
332   %t1 = load i32, ptr %arrayidx1
333   %t0 = load i32, ptr %ptr
334   %t3 = load i32, ptr %arrayidx3
335   ret void
338 ; Improve on existing dereferenceable attribute.
340 define void @more_bytes(ptr dereferenceable(8) %ptr) {
341 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
342 ; CHECK-LABEL: define {{[^@]+}}@more_bytes
343 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
344 ; CHECK-NEXT:    ret void
346   %arrayidx3 = getelementptr i32, ptr %ptr, i64 3
347   %arrayidx1 = getelementptr i32, ptr %ptr, i64 1
348   %arrayidx2 = getelementptr i32, ptr %ptr, i64 2
349   %t3 = load i32, ptr %arrayidx3
350   %t1 = load i32, ptr %arrayidx1
351   %t2 = load i32, ptr %arrayidx2
352   %t0 = load i32, ptr %ptr
353   ret void
356 ; Improve on existing dereferenceable_or_null attribute.
358 define void @more_bytes_and_not_null(ptr dereferenceable_or_null(8) %ptr) {
359 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
360 ; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null
361 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
362 ; CHECK-NEXT:    ret void
364   %arrayidx3 = getelementptr i32, ptr %ptr, i64 3
365   %arrayidx1 = getelementptr i32, ptr %ptr, i64 1
366   %arrayidx2 = getelementptr i32, ptr %ptr, i64 2
367   %t3 = load i32, ptr %arrayidx3
368   %t1 = load i32, ptr %arrayidx1
369   %t2 = load i32, ptr %arrayidx2
370   %t0 = load i32, ptr %ptr
371   ret void
374 ; But don't pessimize existing dereferenceable attribute.
376 define void @better_bytes(ptr dereferenceable(100) %ptr) {
377 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
378 ; CHECK-LABEL: define {{[^@]+}}@better_bytes
379 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) #[[ATTR2]] {
380 ; CHECK-NEXT:    ret void
382   %arrayidx3 = getelementptr i32, ptr %ptr, i64 3
383   %arrayidx1 = getelementptr i32, ptr %ptr, i64 1
384   %arrayidx2 = getelementptr i32, ptr %ptr, i64 2
385   %t3 = load i32, ptr %arrayidx3
386   %t1 = load i32, ptr %arrayidx1
387   %t2 = load i32, ptr %arrayidx2
388   %t0 = load i32, ptr %ptr
389   ret void
392 define void @bitcast(ptr %arg) {
393 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
394 ; CHECK-LABEL: define {{[^@]+}}@bitcast
395 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR2]] {
396 ; CHECK-NEXT:    ret void
398   %ptr = bitcast ptr %arg to ptr
399   %arrayidx1 = getelementptr float, ptr %ptr, i64 1
400   %t0 = load float, ptr %ptr
401   %t1 = load float, ptr %arrayidx1
402   ret void
405 define void @bitcast_different_sizes(ptr %arg1, ptr %arg2) {
406 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
407 ; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes
408 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], ptr nocapture nofree noundef nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) #[[ATTR2]] {
409 ; CHECK-NEXT:    ret void
411   %ptr1 = bitcast ptr %arg1 to ptr
412   %a11 = getelementptr float, ptr %ptr1, i64 1
413   %a12 = getelementptr float, ptr %ptr1, i64 2
414   %ld10 = load float, ptr %ptr1
415   %ld11 = load float, ptr %a11
416   %ld12 = load float, ptr %a12
418   %a21 = getelementptr i64, ptr %arg2, i64 1
419   %ld20 = load i64, ptr %arg2
420   %ld21 = load i64, ptr %a21
421   ret void
424 define void @negative_offset(ptr %arg) {
425 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
426 ; CHECK-LABEL: define {{[^@]+}}@negative_offset
427 ; CHECK-SAME: (ptr nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR2]] {
428 ; CHECK-NEXT:    ret void
430   %ptr = bitcast ptr %arg to ptr
431   %arrayidx1 = getelementptr float, ptr %ptr, i64 -1
432   %t0 = load float, ptr %ptr
433   %t1 = load float, ptr %arrayidx1
434   ret void
437 define void @stores(ptr %arg) {
438 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
439 ; CHECK-LABEL: define {{[^@]+}}@stores
440 ; CHECK-SAME: (ptr nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
441 ; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, ptr [[ARG]], i64 1
442 ; CHECK-NEXT:    store float 1.000000e+00, ptr [[ARG]], align 4
443 ; CHECK-NEXT:    store float 2.000000e+00, ptr [[ARRAYIDX1]], align 4
444 ; CHECK-NEXT:    ret void
446   %ptr = bitcast ptr %arg to ptr
447   %arrayidx1 = getelementptr float, ptr %ptr, i64 1
448   store float 1.0, ptr %ptr
449   store float 2.0, ptr %arrayidx1
450   ret void
453 define void @load_store(ptr %arg) {
454 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
455 ; CHECK-LABEL: define {{[^@]+}}@load_store
456 ; CHECK-SAME: (ptr nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
457 ; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, ptr [[ARG]], i64 1
458 ; CHECK-NEXT:    store float 2.000000e+00, ptr [[ARRAYIDX1]], align 4
459 ; CHECK-NEXT:    ret void
461   %ptr = bitcast ptr %arg to ptr
462   %arrayidx1 = getelementptr float, ptr %ptr, i64 1
463   %t1 = load float, ptr %ptr
464   store float 2.0, ptr %arrayidx1
465   ret void
468 define void @different_size1(ptr %arg) {
469 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
470 ; CHECK-LABEL: define {{[^@]+}}@different_size1
471 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
472 ; CHECK-NEXT:    store double 0.000000e+00, ptr [[ARG]], align 8
473 ; CHECK-NEXT:    store i32 0, ptr [[ARG]], align 8
474 ; CHECK-NEXT:    ret void
476   %arg-cast = bitcast ptr %arg to ptr
477   store double 0.000000e+00, ptr %arg-cast
478   store i32 0, ptr %arg
479   ret void
482 define void @different_size2(ptr %arg) {
483 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
484 ; CHECK-LABEL: define {{[^@]+}}@different_size2
485 ; CHECK-SAME: (ptr nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
486 ; CHECK-NEXT:    store i32 0, ptr [[ARG]], align 8
487 ; CHECK-NEXT:    store double 0.000000e+00, ptr [[ARG]], align 8
488 ; CHECK-NEXT:    ret void
490   store i32 0, ptr %arg
491   store double 0.000000e+00, ptr %arg
492   ret void
495 ; Make use of MustBeExecuted Explorer
497 ; [CFG]
498 ; entry
499 ;  / \
500 ; l1 l2
501 ; | X |
502 ; l3 l4
503 ;  \ /
504 ;  l5
505 ;  / \
506 ; l6 l7
507 ;  \ /
508 ;  end
509 ; According to the above CFG, we can see that instructions in l5 Block must be executed.
510 ; Therefore, %p must be dereferenced.
512 ; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, ptr {{.*}} dereferenceable(4) %p)
513 define i32 @require_cfg_analysis(i32 %c, ptr %p) {
514 ; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write)
515 ; CHECK-LABEL: define {{[^@]+}}@require_cfg_analysis
516 ; CHECK-SAME: (i32 [[C:%.*]], ptr nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {
517 ; CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
518 ; CHECK-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
519 ; CHECK:       l1:
520 ; CHECK-NEXT:    br label [[L4:%.*]]
521 ; CHECK:       l2:
522 ; CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
523 ; CHECK-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]
524 ; CHECK:       l3:
525 ; CHECK-NEXT:    br label [[L5:%.*]]
526 ; CHECK:       l4:
527 ; CHECK-NEXT:    br label [[L5]]
528 ; CHECK:       l5:
529 ; CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
530 ; CHECK-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
531 ; CHECK:       l6:
532 ; CHECK-NEXT:    store i32 0, ptr [[P]], align 4
533 ; CHECK-NEXT:    br label [[END:%.*]]
534 ; CHECK:       l7:
535 ; CHECK-NEXT:    store i32 1, ptr [[P]], align 4
536 ; CHECK-NEXT:    br label [[END]]
537 ; CHECK:       end:
538 ; CHECK-NEXT:    ret i32 1
540   %tobool1 = icmp eq i32 %c, 0
541   br i1 %tobool1, label %l1, label %l2
543   %tobool2 = icmp eq i32 %c, 1
544   br i1 %tobool2, label %l3, label %l4
546   %tobool3 = icmp eq i32 %c, 2
547   br i1 %tobool3, label %l3, label %l4
549   br label %l5
551   br label %l5
553   %tobool4 = icmp eq i32 %c, 4
554   br i1 %tobool4, label %l6, label %l7
556   store i32 0, ptr %p
557   br label %end
559   store i32 1, ptr %p
560   br label %end
561 end:
562   ret i32 1
565 ; CHECK: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
566 ; CHECK: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: readwrite) }
567 ; CHECK: attributes #[[ATTR2]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
568 ; CHECK: attributes #[[ATTR3]] = { mustprogress nofree norecurse nounwind willreturn memory(argmem: readwrite) }
569 ; CHECK: attributes #[[ATTR4]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: write) }
571 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
572 ; CGSCC: {{.*}}
573 ; TUNIT: {{.*}}