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