1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
6
7; Determine dereference-ability before unused loads get deleted:
8; https://bugs.llvm.org/show_bug.cgi?id=21780
9
10define <4 x double> @PR21780(double* %ptr) {
11; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
12; CHECK-LABEL: define {{[^@]+}}@PR21780
13; CHECK-SAME: (double* nocapture nofree noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
14; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1
15; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2
16; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
17; CHECK-NEXT:    [[T0:%.*]] = load double, double* [[PTR]], align 8
18; CHECK-NEXT:    [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8
19; CHECK-NEXT:    [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8
20; CHECK-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
21; CHECK-NEXT:    [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0
22; CHECK-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1
23; CHECK-NEXT:    [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2
24; CHECK-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3
25; CHECK-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2>
26; CHECK-NEXT:    ret <4 x double> [[SHUFFLE]]
27;
28
29  ; GEP of index 0 is simplified away.
30  %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
31  %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
32  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
33
34  %t0 = load double, double* %ptr, align 8
35  %t1 = load double, double* %arrayidx1, align 8
36  %t2 = load double, double* %arrayidx2, align 8
37  %t3 = load double, double* %arrayidx3, align 8
38
39  %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
40  %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
41  %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
42  %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
43  %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
44  ret <4 x double> %shuffle
45}
46
47
48define double @PR21780_only_access3_with_inbounds(double* %ptr) {
49; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
50; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds
51; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {
52; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
53; CHECK-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
54; CHECK-NEXT:    ret double [[T3]]
55;
56
57  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
58  %t3 = load double, double* %arrayidx3, align 8
59  ret double %t3
60}
61
62define double @PR21780_only_access3_without_inbounds(double* %ptr) {
63; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
64; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds
65; CHECK-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) #[[ATTR0]] {
66; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
67; CHECK-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
68; CHECK-NEXT:    ret double [[T3]]
69;
70  %arrayidx3 = getelementptr double, double* %ptr, i64 3
71  %t3 = load double, double* %arrayidx3, align 8
72  ret double %t3
73}
74
75define double @PR21780_without_inbounds(double* %ptr) {
76; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
77; CHECK-LABEL: define {{[^@]+}}@PR21780_without_inbounds
78; CHECK-SAME: (double* nocapture nofree noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0]] {
79; CHECK-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
80; CHECK-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
81; CHECK-NEXT:    ret double [[T3]]
82;
83
84  %arrayidx1 = getelementptr double, double* %ptr, i64 1
85  %arrayidx2 = getelementptr double, double* %ptr, i64 2
86  %arrayidx3 = getelementptr double, double* %ptr, i64 3
87
88  %t0 = load double, double* %ptr, align 8
89  %t1 = load double, double* %arrayidx1, align 8
90  %t2 = load double, double* %arrayidx2, align 8
91  %t3 = load double, double* %arrayidx3, align 8
92
93  ret double %t3
94}
95
96; Unsimplified, but still valid. Also, throw in some bogus arguments.
97
98define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
99; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
100; CHECK-LABEL: define {{[^@]+}}@gep0
101; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree noundef nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
102; CHECK-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2
103; CHECK-NEXT:    [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1
104; CHECK-NEXT:    store i8 [[T2]], i8* [[OTHER]], align 1
105; CHECK-NEXT:    ret void
106;
107  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
108  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
109  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
110  %t0 = load i8, i8* %arrayidx0
111  %t1 = load i8, i8* %arrayidx1
112  %t2 = load i8, i8* %arrayidx2
113  store i8 %t2, i8* %other
114  ret void
115}
116
117; Order of accesses does not change computation.
118; Multiple arguments may be dereferenceable.
119
120define void @ordering(i8* %ptr1, i32* %ptr2) {
121; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
122; CHECK-LABEL: define {{[^@]+}}@ordering
123; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) #[[ATTR2:[0-9]+]] {
124; CHECK-NEXT:    ret void
125;
126  %a20 = getelementptr i32, i32* %ptr2, i64 0
127  %a12 = getelementptr i8, i8* %ptr1, i64 2
128  %t12 = load i8, i8* %a12
129  %a11 = getelementptr i8, i8* %ptr1, i64 1
130  %t20 = load i32, i32* %a20
131  %a10 = getelementptr i8, i8* %ptr1, i64 0
132  %t10 = load i8, i8* %a10
133  %t11 = load i8, i8* %a11
134  %a21 = getelementptr i32, i32* %ptr2, i64 1
135  %t21 = load i32, i32* %a21
136  ret void
137}
138
139; Not in entry block.
140
141define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
142; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
143; CHECK-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute
144; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) #[[ATTR2]] {
145; CHECK-NEXT:  entry:
146; CHECK-NEXT:    br label [[EXIT:%.*]]
147; CHECK:       exit:
148; CHECK-NEXT:    ret void
149;
150entry:
151  br label %exit
152exit:
153  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
154  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
155  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
156  %t0 = load i8, i8* %arrayidx0
157  %t1 = load i8, i8* %arrayidx1
158  %t2 = load i8, i8* %arrayidx2
159  ret void
160}
161
162; Not in entry block and not guaranteed to execute.
163
164define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
165; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
166; CHECK-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute
167; CHECK-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) #[[ATTR2]] {
168; CHECK-NEXT:  entry:
169; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
170; CHECK:       loads:
171; CHECK-NEXT:    ret void
172; CHECK:       exit:
173; CHECK-NEXT:    ret void
174;
175entry:
176  br i1 %cond, label %loads, label %exit
177loads:
178  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
179  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
180  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
181  %t0 = load i8, i8* %arrayidx0
182  %t1 = load i8, i8* %arrayidx1
183  %t2 = load i8, i8* %arrayidx2
184  ret void
185exit:
186  ret void
187}
188
189; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
190
191define void @partial_in_entry(i16* %ptr, i1 %cond) {
192; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
193; CHECK-LABEL: define {{[^@]+}}@partial_in_entry
194; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) #[[ATTR2]] {
195; CHECK-NEXT:  entry:
196; CHECK-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
197; CHECK:       loads:
198; CHECK-NEXT:    ret void
199; CHECK:       exit:
200; CHECK-NEXT:    ret void
201;
202entry:
203  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
204  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
205  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
206  %t0 = load i16, i16* %arrayidx0
207  %t1 = load i16, i16* %arrayidx1
208  br i1 %cond, label %loads, label %exit
209loads:
210  %t2 = load i16, i16* %arrayidx2
211  ret void
212exit:
213  ret void
214}
215
216; The volatile load can't be used to prove a non-volatile access is allowed.
217; The 2nd and 3rd loads may never execute.
218
219define void @volatile_is_not_dereferenceable(i16* %ptr) {
220; CHECK: Function Attrs: argmemonly nofree norecurse nounwind willreturn
221; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
222; CHECK-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
223; CHECK-NEXT:    [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2
224; CHECK-NEXT:    ret void
225;
226  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
227  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
228  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
229  %t0 = load volatile i16, i16* %arrayidx0
230  %t1 = load i16, i16* %arrayidx1
231  %t2 = load i16, i16* %arrayidx2
232  ret void
233}
234
235; TODO: We should allow inference for atomic (but not volatile) ops.
236
237define void @atomic_is_alright(i16* %ptr) {
238; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
239; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright
240; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) #[[ATTR2]] {
241; CHECK-NEXT:    ret void
242;
243  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
244  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
245  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
246  %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2
247  %t1 = load i16, i16* %arrayidx1
248  %t2 = load i16, i16* %arrayidx2
249  ret void
250}
251
252declare void @may_not_return()
253
254define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
255; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution
256; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) {
257; CHECK-NEXT:    call void @may_not_return()
258; CHECK-NEXT:    ret void
259;
260  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
261  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
262  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
263  %t0 = load i16, i16* %arrayidx0
264  call void @may_not_return()
265  %t1 = load i16, i16* %arrayidx1
266  %t2 = load i16, i16* %arrayidx2
267  ret void
268}
269
270; We must have consecutive accesses.
271
272define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
273; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
274; CHECK-LABEL: define {{[^@]+}}@variable_gep_index
275; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) #[[ATTR2]] {
276; CHECK-NEXT:    ret void
277;
278  %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
279  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
280  %t0 = load i8, i8* %ptr
281  %t1 = load i8, i8* %arrayidx1
282  %t2 = load i8, i8* %arrayidx2
283  ret void
284}
285
286; Deal with >1 GEP index.
287
288define void @multi_index_gep(<4 x i8>* %ptr) {
289; FIXME: %ptr should be dereferenceable(4)
290; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
291; CHECK-LABEL: define {{[^@]+}}@multi_index_gep
292; CHECK-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) #[[ATTR2]] {
293; CHECK-NEXT:    ret void
294;
295  %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
296  %t0 = load i8, i8* %arrayidx00
297  ret void
298}
299
300; Could round weird bitwidths down?
301
302define void @not_byte_multiple(i9* %ptr) {
303; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
304; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple
305; CHECK-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) #[[ATTR2]] {
306; CHECK-NEXT:    ret void
307;
308  %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
309  %t0 = load i9, i9* %arrayidx0
310  ret void
311}
312
313; Missing direct access from the pointer.
314
315define void @no_pointer_deref(i16* %ptr) {
316; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
317; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref
318; CHECK-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) #[[ATTR2]] {
319; CHECK-NEXT:    ret void
320;
321  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
322  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
323  %t1 = load i16, i16* %arrayidx1
324  %t2 = load i16, i16* %arrayidx2
325  ret void
326}
327
328; Out-of-order is ok, but missing access concludes dereferenceable range.
329
330define void @non_consecutive(i32* %ptr) {
331; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
332; CHECK-LABEL: define {{[^@]+}}@non_consecutive
333; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) #[[ATTR2]] {
334; CHECK-NEXT:    ret void
335;
336  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
337  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
338  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
339  %t1 = load i32, i32* %arrayidx1
340  %t0 = load i32, i32* %arrayidx0
341  %t3 = load i32, i32* %arrayidx3
342  ret void
343}
344
345; Improve on existing dereferenceable attribute.
346
347define void @more_bytes(i32* dereferenceable(8) %ptr) {
348; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
349; CHECK-LABEL: define {{[^@]+}}@more_bytes
350; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
351; CHECK-NEXT:    ret void
352;
353  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
354  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
355  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
356  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
357  %t3 = load i32, i32* %arrayidx3
358  %t1 = load i32, i32* %arrayidx1
359  %t2 = load i32, i32* %arrayidx2
360  %t0 = load i32, i32* %arrayidx0
361  ret void
362}
363
364; Improve on existing dereferenceable_or_null attribute.
365
366define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
367; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
368; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null
369; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
370; CHECK-NEXT:    ret void
371;
372  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
373  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
374  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
375  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
376  %t3 = load i32, i32* %arrayidx3
377  %t1 = load i32, i32* %arrayidx1
378  %t2 = load i32, i32* %arrayidx2
379  %t0 = load i32, i32* %arrayidx0
380  ret void
381}
382
383; But don't pessimize existing dereferenceable attribute.
384
385define void @better_bytes(i32* dereferenceable(100) %ptr) {
386; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
387; CHECK-LABEL: define {{[^@]+}}@better_bytes
388; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) #[[ATTR2]] {
389; CHECK-NEXT:    ret void
390;
391  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
392  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
393  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
394  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
395  %t3 = load i32, i32* %arrayidx3
396  %t1 = load i32, i32* %arrayidx1
397  %t2 = load i32, i32* %arrayidx2
398  %t0 = load i32, i32* %arrayidx0
399  ret void
400}
401
402define void @bitcast(i32* %arg) {
403; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
404; CHECK-LABEL: define {{[^@]+}}@bitcast
405; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR2]] {
406; CHECK-NEXT:    ret void
407;
408  %ptr = bitcast i32* %arg to float*
409  %arrayidx0 = getelementptr float, float* %ptr, i64 0
410  %arrayidx1 = getelementptr float, float* %ptr, i64 1
411  %t0 = load float, float* %arrayidx0
412  %t1 = load float, float* %arrayidx1
413  ret void
414}
415
416define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
417; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
418; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes
419; CHECK-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) #[[ATTR2]] {
420; CHECK-NEXT:    ret void
421;
422  %ptr1 = bitcast double* %arg1 to float*
423  %a10 = getelementptr float, float* %ptr1, i64 0
424  %a11 = getelementptr float, float* %ptr1, i64 1
425  %a12 = getelementptr float, float* %ptr1, i64 2
426  %ld10 = load float, float* %a10
427  %ld11 = load float, float* %a11
428  %ld12 = load float, float* %a12
429
430  %ptr2 = bitcast i8* %arg2 to i64*
431  %a20 = getelementptr i64, i64* %ptr2, i64 0
432  %a21 = getelementptr i64, i64* %ptr2, i64 1
433  %ld20 = load i64, i64* %a20
434  %ld21 = load i64, i64* %a21
435  ret void
436}
437
438define void @negative_offset(i32* %arg) {
439; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
440; CHECK-LABEL: define {{[^@]+}}@negative_offset
441; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR2]] {
442; CHECK-NEXT:    ret void
443;
444  %ptr = bitcast i32* %arg to float*
445  %arrayidx0 = getelementptr float, float* %ptr, i64 0
446  %arrayidx1 = getelementptr float, float* %ptr, i64 -1
447  %t0 = load float, float* %arrayidx0
448  %t1 = load float, float* %arrayidx1
449  ret void
450}
451
452define void @stores(i32* %arg) {
453; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
454; CHECK-LABEL: define {{[^@]+}}@stores
455; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
456; CHECK-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
457; CHECK-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0
458; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
459; CHECK-NEXT:    store float 1.000000e+00, float* [[ARRAYIDX0]], align 4
460; CHECK-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
461; CHECK-NEXT:    ret void
462;
463  %ptr = bitcast i32* %arg to float*
464  %arrayidx0 = getelementptr float, float* %ptr, i64 0
465  %arrayidx1 = getelementptr float, float* %ptr, i64 1
466  store float 1.0, float* %arrayidx0
467  store float 2.0, float* %arrayidx1
468  ret void
469}
470
471define void @load_store(i32* %arg) {
472; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
473; CHECK-LABEL: define {{[^@]+}}@load_store
474; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
475; CHECK-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
476; CHECK-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
477; CHECK-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
478; CHECK-NEXT:    ret void
479;
480  %ptr = bitcast i32* %arg to float*
481  %arrayidx0 = getelementptr float, float* %ptr, i64 0
482  %arrayidx1 = getelementptr float, float* %ptr, i64 1
483  %t1 = load float, float* %arrayidx0
484  store float 2.0, float* %arrayidx1
485  ret void
486}
487
488define void @different_size1(i32* %arg) {
489; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
490; CHECK-LABEL: define {{[^@]+}}@different_size1
491; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
492; CHECK-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
493; CHECK-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
494; CHECK-NEXT:    store i32 0, i32* [[ARG]], align 8
495; CHECK-NEXT:    ret void
496;
497  %arg-cast = bitcast i32* %arg to double*
498  store double 0.000000e+00, double* %arg-cast
499  store i32 0, i32* %arg
500  ret void
501}
502
503define void @different_size2(i32* %arg) {
504; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
505; CHECK-LABEL: define {{[^@]+}}@different_size2
506; CHECK-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
507; CHECK-NEXT:    store i32 0, i32* [[ARG]], align 8
508; CHECK-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
509; CHECK-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
510; CHECK-NEXT:    ret void
511;
512  store i32 0, i32* %arg
513  %arg-cast = bitcast i32* %arg to double*
514  store double 0.000000e+00, double* %arg-cast
515  ret void
516}
517
518; Make use of MustBeExecuted Explorer
519;
520; [CFG]
521; entry
522;  / \
523; l1 l2
524; | X |
525; l3 l4
526;  \ /
527;  l5
528;  / \
529; l6 l7
530;  \ /
531;  end
532; According to the above CFG, we can see that instructions in l5 Block must be executed.
533; Therefore, %p must be dereferenced.
534;
535; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p)
536define i32 @require_cfg_analysis(i32 %c, i32* %p) {
537; IS________OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
538; IS________OPM-LABEL: define {{[^@]+}}@require_cfg_analysis
539; IS________OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR4]] {
540; IS________OPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
541; IS________OPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
542; IS________OPM:       l1:
543; IS________OPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
544; IS________OPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
545; IS________OPM:       l2:
546; IS________OPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
547; IS________OPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
548; IS________OPM:       l3:
549; IS________OPM-NEXT:    br label [[L5:%.*]]
550; IS________OPM:       l4:
551; IS________OPM-NEXT:    br label [[L5]]
552; IS________OPM:       l5:
553; IS________OPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
554; IS________OPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
555; IS________OPM:       l6:
556; IS________OPM-NEXT:    store i32 0, i32* [[P]], align 4
557; IS________OPM-NEXT:    br label [[END:%.*]]
558; IS________OPM:       l7:
559; IS________OPM-NEXT:    store i32 1, i32* [[P]], align 4
560; IS________OPM-NEXT:    br label [[END]]
561; IS________OPM:       end:
562; IS________OPM-NEXT:    ret i32 1
563;
564; IS________NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
565; IS________NPM-LABEL: define {{[^@]+}}@require_cfg_analysis
566; IS________NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {
567; IS________NPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
568; IS________NPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
569; IS________NPM:       l1:
570; IS________NPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
571; IS________NPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
572; IS________NPM:       l2:
573; IS________NPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
574; IS________NPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
575; IS________NPM:       l3:
576; IS________NPM-NEXT:    br label [[L5:%.*]]
577; IS________NPM:       l4:
578; IS________NPM-NEXT:    br label [[L5]]
579; IS________NPM:       l5:
580; IS________NPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
581; IS________NPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
582; IS________NPM:       l6:
583; IS________NPM-NEXT:    store i32 0, i32* [[P]], align 4
584; IS________NPM-NEXT:    br label [[END:%.*]]
585; IS________NPM:       l7:
586; IS________NPM-NEXT:    store i32 1, i32* [[P]], align 4
587; IS________NPM-NEXT:    br label [[END]]
588; IS________NPM:       end:
589; IS________NPM-NEXT:    ret i32 1
590;
591  %tobool1 = icmp eq i32 %c, 0
592  br i1 %tobool1, label %l1, label %l2
593l1:
594  %tobool2 = icmp eq i32 %c, 1
595  br i1 %tobool2, label %l3, label %l4
596l2:
597  %tobool3 = icmp eq i32 %c, 2
598  br i1 %tobool3, label %l3, label %l4
599l3:
600  br label %l5
601l4:
602  br label %l5
603l5:
604  %tobool4 = icmp eq i32 %c, 4
605  br i1 %tobool4, label %l6, label %l7
606l6:
607  store i32 0, i32* %p
608  br label %end
609l7:
610  store i32 1, i32* %p
611  br label %end
612end:
613  ret i32 1
614}
615;.
616; CHECK: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }
617; CHECK: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn }
618; CHECK: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
619; CHECK: attributes #[[ATTR3]] = { argmemonly nofree norecurse nounwind willreturn }
620; CHECK: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }
621;.
622