• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal  -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-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 -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; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
12; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780
13; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0:#.*]] {
14; IS__TUNIT____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1
15; IS__TUNIT____-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2
16; IS__TUNIT____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
17; IS__TUNIT____-NEXT:    [[T0:%.*]] = load double, double* [[PTR]], align 8
18; IS__TUNIT____-NEXT:    [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8
19; IS__TUNIT____-NEXT:    [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8
20; IS__TUNIT____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
21; IS__TUNIT____-NEXT:    [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0
22; IS__TUNIT____-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1
23; IS__TUNIT____-NEXT:    [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2
24; IS__TUNIT____-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3
25; IS__TUNIT____-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2>
26; IS__TUNIT____-NEXT:    ret <4 x double> [[SHUFFLE]]
27;
28; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
29; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780
30; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0:#.*]] {
31; IS__CGSCC____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1
32; IS__CGSCC____-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2
33; IS__CGSCC____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
34; IS__CGSCC____-NEXT:    [[T0:%.*]] = load double, double* [[PTR]], align 8
35; IS__CGSCC____-NEXT:    [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8
36; IS__CGSCC____-NEXT:    [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8
37; IS__CGSCC____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
38; IS__CGSCC____-NEXT:    [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0
39; IS__CGSCC____-NEXT:    [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1
40; IS__CGSCC____-NEXT:    [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2
41; IS__CGSCC____-NEXT:    [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3
42; IS__CGSCC____-NEXT:    [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> <i32 0, i32 0, i32 2, i32 2>
43; IS__CGSCC____-NEXT:    ret <4 x double> [[SHUFFLE]]
44;
45
46  ; GEP of index 0 is simplified away.
47  %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
48  %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
49  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
50
51  %t0 = load double, double* %ptr, align 8
52  %t1 = load double, double* %arrayidx1, align 8
53  %t2 = load double, double* %arrayidx2, align 8
54  %t3 = load double, double* %arrayidx3, align 8
55
56  %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
57  %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
58  %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
59  %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
60  %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
61  ret <4 x double> %shuffle
62}
63
64
65define double @PR21780_only_access3_with_inbounds(double* %ptr) {
66; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
67; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds
68; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] {
69; IS__TUNIT____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
70; IS__TUNIT____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
71; IS__TUNIT____-NEXT:    ret double [[T3]]
72;
73; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
74; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds
75; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] {
76; IS__CGSCC____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3
77; IS__CGSCC____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
78; IS__CGSCC____-NEXT:    ret double [[T3]]
79;
80
81  %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
82  %t3 = load double, double* %arrayidx3, align 8
83  ret double %t3
84}
85
86define double @PR21780_only_access3_without_inbounds(double* %ptr) {
87; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
88; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds
89; IS__TUNIT____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) [[ATTR0]] {
90; IS__TUNIT____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
91; IS__TUNIT____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
92; IS__TUNIT____-NEXT:    ret double [[T3]]
93;
94; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
95; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds
96; IS__CGSCC____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) [[ATTR0]] {
97; IS__CGSCC____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
98; IS__CGSCC____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
99; IS__CGSCC____-NEXT:    ret double [[T3]]
100;
101  %arrayidx3 = getelementptr double, double* %ptr, i64 3
102  %t3 = load double, double* %arrayidx3, align 8
103  ret double %t3
104}
105
106define double @PR21780_without_inbounds(double* %ptr) {
107; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn
108; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_without_inbounds
109; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] {
110; IS__TUNIT____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
111; IS__TUNIT____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
112; IS__TUNIT____-NEXT:    ret double [[T3]]
113;
114; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn
115; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_without_inbounds
116; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) [[ATTR0]] {
117; IS__CGSCC____-NEXT:    [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3
118; IS__CGSCC____-NEXT:    [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8
119; IS__CGSCC____-NEXT:    ret double [[T3]]
120;
121
122  %arrayidx1 = getelementptr double, double* %ptr, i64 1
123  %arrayidx2 = getelementptr double, double* %ptr, i64 2
124  %arrayidx3 = getelementptr double, double* %ptr, i64 3
125
126  %t0 = load double, double* %ptr, align 8
127  %t1 = load double, double* %arrayidx1, align 8
128  %t2 = load double, double* %arrayidx2, align 8
129  %t3 = load double, double* %arrayidx3, align 8
130
131  ret double %t3
132}
133
134; Unsimplified, but still valid. Also, throw in some bogus arguments.
135
136define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
137; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn
138; IS__TUNIT____-LABEL: define {{[^@]+}}@gep0
139; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) [[ATTR1:#.*]] {
140; IS__TUNIT____-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2
141; IS__TUNIT____-NEXT:    [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1
142; IS__TUNIT____-NEXT:    store i8 [[T2]], i8* [[OTHER]], align 1
143; IS__TUNIT____-NEXT:    ret void
144;
145; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn
146; IS__CGSCC____-LABEL: define {{[^@]+}}@gep0
147; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) [[ATTR1:#.*]] {
148; IS__CGSCC____-NEXT:    [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2
149; IS__CGSCC____-NEXT:    [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1
150; IS__CGSCC____-NEXT:    store i8 [[T2]], i8* [[OTHER]], align 1
151; IS__CGSCC____-NEXT:    ret void
152;
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  store i8 %t2, i8* %other
160  ret void
161}
162
163; Order of accesses does not change computation.
164; Multiple arguments may be dereferenceable.
165
166define void @ordering(i8* %ptr1, i32* %ptr2) {
167; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
168; IS__TUNIT____-LABEL: define {{[^@]+}}@ordering
169; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) [[ATTR2:#.*]] {
170; IS__TUNIT____-NEXT:    ret void
171;
172; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
173; IS__CGSCC____-LABEL: define {{[^@]+}}@ordering
174; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) [[ATTR2:#.*]] {
175; IS__CGSCC____-NEXT:    ret void
176;
177  %a20 = getelementptr i32, i32* %ptr2, i64 0
178  %a12 = getelementptr i8, i8* %ptr1, i64 2
179  %t12 = load i8, i8* %a12
180  %a11 = getelementptr i8, i8* %ptr1, i64 1
181  %t20 = load i32, i32* %a20
182  %a10 = getelementptr i8, i8* %ptr1, i64 0
183  %t10 = load i8, i8* %a10
184  %t11 = load i8, i8* %a11
185  %a21 = getelementptr i32, i32* %ptr2, i64 1
186  %t21 = load i32, i32* %a21
187  ret void
188}
189
190; Not in entry block.
191
192define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
193; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
194; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute
195; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) [[ATTR2]] {
196; IS__TUNIT____-NEXT:  entry:
197; IS__TUNIT____-NEXT:    br label [[EXIT:%.*]]
198; IS__TUNIT____:       exit:
199; IS__TUNIT____-NEXT:    ret void
200;
201; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
202; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute
203; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) [[ATTR2]] {
204; IS__CGSCC____-NEXT:  entry:
205; IS__CGSCC____-NEXT:    br label [[EXIT:%.*]]
206; IS__CGSCC____:       exit:
207; IS__CGSCC____-NEXT:    ret void
208;
209entry:
210  br label %exit
211exit:
212  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
213  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
214  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
215  %t0 = load i8, i8* %arrayidx0
216  %t1 = load i8, i8* %arrayidx1
217  %t2 = load i8, i8* %arrayidx2
218  ret void
219}
220
221; Not in entry block and not guaranteed to execute.
222
223define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
224; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
225; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute
226; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] {
227; IS__TUNIT____-NEXT:  entry:
228; IS__TUNIT____-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
229; IS__TUNIT____:       loads:
230; IS__TUNIT____-NEXT:    ret void
231; IS__TUNIT____:       exit:
232; IS__TUNIT____-NEXT:    ret void
233;
234; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
235; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute
236; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] {
237; IS__CGSCC____-NEXT:  entry:
238; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
239; IS__CGSCC____:       loads:
240; IS__CGSCC____-NEXT:    ret void
241; IS__CGSCC____:       exit:
242; IS__CGSCC____-NEXT:    ret void
243;
244entry:
245  br i1 %cond, label %loads, label %exit
246loads:
247  %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
248  %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
249  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
250  %t0 = load i8, i8* %arrayidx0
251  %t1 = load i8, i8* %arrayidx1
252  %t2 = load i8, i8* %arrayidx2
253  ret void
254exit:
255  ret void
256}
257
258; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
259
260define void @partial_in_entry(i16* %ptr, i1 %cond) {
261; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
262; IS__TUNIT____-LABEL: define {{[^@]+}}@partial_in_entry
263; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] {
264; IS__TUNIT____-NEXT:  entry:
265; IS__TUNIT____-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
266; IS__TUNIT____:       loads:
267; IS__TUNIT____-NEXT:    ret void
268; IS__TUNIT____:       exit:
269; IS__TUNIT____-NEXT:    ret void
270;
271; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
272; IS__CGSCC____-LABEL: define {{[^@]+}}@partial_in_entry
273; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) [[ATTR2]] {
274; IS__CGSCC____-NEXT:  entry:
275; IS__CGSCC____-NEXT:    br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]]
276; IS__CGSCC____:       loads:
277; IS__CGSCC____-NEXT:    ret void
278; IS__CGSCC____:       exit:
279; IS__CGSCC____-NEXT:    ret void
280;
281entry:
282  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
283  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
284  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
285  %t0 = load i16, i16* %arrayidx0
286  %t1 = load i16, i16* %arrayidx1
287  br i1 %cond, label %loads, label %exit
288loads:
289  %t2 = load i16, i16* %arrayidx2
290  ret void
291exit:
292  ret void
293}
294
295; The volatile load can't be used to prove a non-volatile access is allowed.
296; The 2nd and 3rd loads may never execute.
297
298define void @volatile_is_not_dereferenceable(i16* %ptr) {
299; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn
300; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
301; IS__TUNIT____-SAME: (i16* nofree align 2 [[PTR:%.*]]) [[ATTR3:#.*]] {
302; IS__TUNIT____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0
303; IS__TUNIT____-NEXT:    [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2
304; IS__TUNIT____-NEXT:    ret void
305;
306; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn
307; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
308; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) [[ATTR3:#.*]] {
309; IS__CGSCC____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0
310; IS__CGSCC____-NEXT:    [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2
311; IS__CGSCC____-NEXT:    ret void
312;
313  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
314  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
315  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
316  %t0 = load volatile i16, i16* %arrayidx0
317  %t1 = load i16, i16* %arrayidx1
318  %t2 = load i16, i16* %arrayidx2
319  ret void
320}
321
322; TODO: We should allow inference for atomic (but not volatile) ops.
323
324define void @atomic_is_alright(i16* %ptr) {
325; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
326; IS__TUNIT____-LABEL: define {{[^@]+}}@atomic_is_alright
327; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) [[ATTR2]] {
328; IS__TUNIT____-NEXT:    ret void
329;
330; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
331; IS__CGSCC____-LABEL: define {{[^@]+}}@atomic_is_alright
332; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) [[ATTR2]] {
333; IS__CGSCC____-NEXT:    ret void
334;
335  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
336  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
337  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
338  %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2
339  %t1 = load i16, i16* %arrayidx1
340  %t2 = load i16, i16* %arrayidx2
341  ret void
342}
343
344declare void @may_not_return()
345
346define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
347; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution
348; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) {
349; CHECK-NEXT:    call void @may_not_return()
350; CHECK-NEXT:    ret void
351;
352  %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
353  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
354  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
355  %t0 = load i16, i16* %arrayidx0
356  call void @may_not_return()
357  %t1 = load i16, i16* %arrayidx1
358  %t2 = load i16, i16* %arrayidx2
359  ret void
360}
361
362; We must have consecutive accesses.
363
364define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
365; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
366; IS__TUNIT____-LABEL: define {{[^@]+}}@variable_gep_index
367; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) [[ATTR2]] {
368; IS__TUNIT____-NEXT:    ret void
369;
370; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
371; IS__CGSCC____-LABEL: define {{[^@]+}}@variable_gep_index
372; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) [[ATTR2]] {
373; IS__CGSCC____-NEXT:    ret void
374;
375  %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
376  %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
377  %t0 = load i8, i8* %ptr
378  %t1 = load i8, i8* %arrayidx1
379  %t2 = load i8, i8* %arrayidx2
380  ret void
381}
382
383; Deal with >1 GEP index.
384
385define void @multi_index_gep(<4 x i8>* %ptr) {
386; FIXME: %ptr should be dereferenceable(4)
387; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
388; IS__TUNIT____-LABEL: define {{[^@]+}}@multi_index_gep
389; IS__TUNIT____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) [[ATTR2]] {
390; IS__TUNIT____-NEXT:    ret void
391;
392; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
393; IS__CGSCC____-LABEL: define {{[^@]+}}@multi_index_gep
394; IS__CGSCC____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) [[ATTR2]] {
395; IS__CGSCC____-NEXT:    ret void
396;
397  %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
398  %t0 = load i8, i8* %arrayidx00
399  ret void
400}
401
402; Could round weird bitwidths down?
403
404define void @not_byte_multiple(i9* %ptr) {
405; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
406; IS__TUNIT____-LABEL: define {{[^@]+}}@not_byte_multiple
407; IS__TUNIT____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) [[ATTR2]] {
408; IS__TUNIT____-NEXT:    ret void
409;
410; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
411; IS__CGSCC____-LABEL: define {{[^@]+}}@not_byte_multiple
412; IS__CGSCC____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) [[ATTR2]] {
413; IS__CGSCC____-NEXT:    ret void
414;
415  %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
416  %t0 = load i9, i9* %arrayidx0
417  ret void
418}
419
420; Missing direct access from the pointer.
421
422define void @no_pointer_deref(i16* %ptr) {
423; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
424; IS__TUNIT____-LABEL: define {{[^@]+}}@no_pointer_deref
425; IS__TUNIT____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) [[ATTR2]] {
426; IS__TUNIT____-NEXT:    ret void
427;
428; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
429; IS__CGSCC____-LABEL: define {{[^@]+}}@no_pointer_deref
430; IS__CGSCC____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) [[ATTR2]] {
431; IS__CGSCC____-NEXT:    ret void
432;
433  %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
434  %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
435  %t1 = load i16, i16* %arrayidx1
436  %t2 = load i16, i16* %arrayidx2
437  ret void
438}
439
440; Out-of-order is ok, but missing access concludes dereferenceable range.
441
442define void @non_consecutive(i32* %ptr) {
443; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
444; IS__TUNIT____-LABEL: define {{[^@]+}}@non_consecutive
445; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) [[ATTR2]] {
446; IS__TUNIT____-NEXT:    ret void
447;
448; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
449; IS__CGSCC____-LABEL: define {{[^@]+}}@non_consecutive
450; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) [[ATTR2]] {
451; IS__CGSCC____-NEXT:    ret void
452;
453  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
454  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
455  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
456  %t1 = load i32, i32* %arrayidx1
457  %t0 = load i32, i32* %arrayidx0
458  %t3 = load i32, i32* %arrayidx3
459  ret void
460}
461
462; Improve on existing dereferenceable attribute.
463
464define void @more_bytes(i32* dereferenceable(8) %ptr) {
465; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
466; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes
467; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] {
468; IS__TUNIT____-NEXT:    ret void
469;
470; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
471; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes
472; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] {
473; IS__CGSCC____-NEXT:    ret void
474;
475  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
476  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
477  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
478  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
479  %t3 = load i32, i32* %arrayidx3
480  %t1 = load i32, i32* %arrayidx1
481  %t2 = load i32, i32* %arrayidx2
482  %t0 = load i32, i32* %arrayidx0
483  ret void
484}
485
486; Improve on existing dereferenceable_or_null attribute.
487
488define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
489; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
490; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes_and_not_null
491; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] {
492; IS__TUNIT____-NEXT:    ret void
493;
494; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
495; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes_and_not_null
496; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) [[ATTR2]] {
497; IS__CGSCC____-NEXT:    ret void
498;
499  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
500  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
501  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
502  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
503  %t3 = load i32, i32* %arrayidx3
504  %t1 = load i32, i32* %arrayidx1
505  %t2 = load i32, i32* %arrayidx2
506  %t0 = load i32, i32* %arrayidx0
507  ret void
508}
509
510; But don't pessimize existing dereferenceable attribute.
511
512define void @better_bytes(i32* dereferenceable(100) %ptr) {
513; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
514; IS__TUNIT____-LABEL: define {{[^@]+}}@better_bytes
515; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) [[ATTR2]] {
516; IS__TUNIT____-NEXT:    ret void
517;
518; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
519; IS__CGSCC____-LABEL: define {{[^@]+}}@better_bytes
520; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) [[ATTR2]] {
521; IS__CGSCC____-NEXT:    ret void
522;
523  %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
524  %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
525  %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
526  %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
527  %t3 = load i32, i32* %arrayidx3
528  %t1 = load i32, i32* %arrayidx1
529  %t2 = load i32, i32* %arrayidx2
530  %t0 = load i32, i32* %arrayidx0
531  ret void
532}
533
534define void @bitcast(i32* %arg) {
535; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
536; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast
537; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR2]] {
538; IS__TUNIT____-NEXT:    ret void
539;
540; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
541; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast
542; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR2]] {
543; IS__CGSCC____-NEXT:    ret void
544;
545  %ptr = bitcast i32* %arg to float*
546  %arrayidx0 = getelementptr float, float* %ptr, i64 0
547  %arrayidx1 = getelementptr float, float* %ptr, i64 1
548  %t0 = load float, float* %arrayidx0
549  %t1 = load float, float* %arrayidx1
550  ret void
551}
552
553define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
554; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
555; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast_different_sizes
556; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) [[ATTR2]] {
557; IS__TUNIT____-NEXT:    ret void
558;
559; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
560; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast_different_sizes
561; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) [[ATTR2]] {
562; IS__CGSCC____-NEXT:    ret void
563;
564  %ptr1 = bitcast double* %arg1 to float*
565  %a10 = getelementptr float, float* %ptr1, i64 0
566  %a11 = getelementptr float, float* %ptr1, i64 1
567  %a12 = getelementptr float, float* %ptr1, i64 2
568  %ld10 = load float, float* %a10
569  %ld11 = load float, float* %a11
570  %ld12 = load float, float* %a12
571
572  %ptr2 = bitcast i8* %arg2 to i64*
573  %a20 = getelementptr i64, i64* %ptr2, i64 0
574  %a21 = getelementptr i64, i64* %ptr2, i64 1
575  %ld20 = load i64, i64* %a20
576  %ld21 = load i64, i64* %a21
577  ret void
578}
579
580define void @negative_offset(i32* %arg) {
581; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
582; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_offset
583; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR2]] {
584; IS__TUNIT____-NEXT:    ret void
585;
586; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
587; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_offset
588; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) [[ATTR2]] {
589; IS__CGSCC____-NEXT:    ret void
590;
591  %ptr = bitcast i32* %arg to float*
592  %arrayidx0 = getelementptr float, float* %ptr, i64 0
593  %arrayidx1 = getelementptr float, float* %ptr, i64 -1
594  %t0 = load float, float* %arrayidx0
595  %t1 = load float, float* %arrayidx1
596  ret void
597}
598
599define void @stores(i32* %arg) {
600; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
601; IS__TUNIT____-LABEL: define {{[^@]+}}@stores
602; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4:#.*]] {
603; IS__TUNIT____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
604; IS__TUNIT____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0
605; IS__TUNIT____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
606; IS__TUNIT____-NEXT:    store float 1.000000e+00, float* [[ARRAYIDX0]], align 4
607; IS__TUNIT____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
608; IS__TUNIT____-NEXT:    ret void
609;
610; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
611; IS__CGSCC____-LABEL: define {{[^@]+}}@stores
612; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4:#.*]] {
613; IS__CGSCC____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
614; IS__CGSCC____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0
615; IS__CGSCC____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
616; IS__CGSCC____-NEXT:    store float 1.000000e+00, float* [[ARRAYIDX0]], align 4
617; IS__CGSCC____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
618; IS__CGSCC____-NEXT:    ret void
619;
620  %ptr = bitcast i32* %arg to float*
621  %arrayidx0 = getelementptr float, float* %ptr, i64 0
622  %arrayidx1 = getelementptr float, float* %ptr, i64 1
623  store float 1.0, float* %arrayidx0
624  store float 2.0, float* %arrayidx1
625  ret void
626}
627
628define void @load_store(i32* %arg) {
629; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
630; IS__TUNIT____-LABEL: define {{[^@]+}}@load_store
631; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
632; IS__TUNIT____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
633; IS__TUNIT____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
634; IS__TUNIT____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
635; IS__TUNIT____-NEXT:    ret void
636;
637; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
638; IS__CGSCC____-LABEL: define {{[^@]+}}@load_store
639; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
640; IS__CGSCC____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
641; IS__CGSCC____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
642; IS__CGSCC____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
643; IS__CGSCC____-NEXT:    ret void
644;
645  %ptr = bitcast i32* %arg to float*
646  %arrayidx0 = getelementptr float, float* %ptr, i64 0
647  %arrayidx1 = getelementptr float, float* %ptr, i64 1
648  %t1 = load float, float* %arrayidx0
649  store float 2.0, float* %arrayidx1
650  ret void
651}
652
653define void @different_size1(i32* %arg) {
654; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
655; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size1
656; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
657; IS__TUNIT____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
658; IS__TUNIT____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
659; IS__TUNIT____-NEXT:    store i32 0, i32* [[ARG]], align 8
660; IS__TUNIT____-NEXT:    ret void
661;
662; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
663; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size1
664; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
665; IS__CGSCC____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
666; IS__CGSCC____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
667; IS__CGSCC____-NEXT:    store i32 0, i32* [[ARG]], align 8
668; IS__CGSCC____-NEXT:    ret void
669;
670  %arg-cast = bitcast i32* %arg to double*
671  store double 0.000000e+00, double* %arg-cast
672  store i32 0, i32* %arg
673  ret void
674}
675
676define void @different_size2(i32* %arg) {
677; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
678; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size2
679; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
680; IS__TUNIT____-NEXT:    store i32 0, i32* [[ARG]], align 8
681; IS__TUNIT____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
682; IS__TUNIT____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
683; IS__TUNIT____-NEXT:    ret void
684;
685; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
686; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size2
687; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) [[ATTR4]] {
688; IS__CGSCC____-NEXT:    store i32 0, i32* [[ARG]], align 8
689; IS__CGSCC____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
690; IS__CGSCC____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
691; IS__CGSCC____-NEXT:    ret void
692;
693  store i32 0, i32* %arg
694  %arg-cast = bitcast i32* %arg to double*
695  store double 0.000000e+00, double* %arg-cast
696  ret void
697}
698
699; Make use of MustBeExecuted Explorer
700;
701; [CFG]
702; entry
703;  / \
704; l1 l2
705; | X |
706; l3 l4
707;  \ /
708;  l5
709;  / \
710; l6 l7
711;  \ /
712;  end
713; According to the above CFG, we can see that instructions in l5 Block must be executed.
714; Therefore, %p must be dereferenced.
715;
716; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p)
717define i32 @require_cfg_analysis(i32 %c, i32* %p) {
718; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
719; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis
720; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR4:#.*]] {
721; IS__TUNIT_OPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
722; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
723; IS__TUNIT_OPM:       l1:
724; IS__TUNIT_OPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
725; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
726; IS__TUNIT_OPM:       l2:
727; IS__TUNIT_OPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
728; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
729; IS__TUNIT_OPM:       l3:
730; IS__TUNIT_OPM-NEXT:    br label [[L5:%.*]]
731; IS__TUNIT_OPM:       l4:
732; IS__TUNIT_OPM-NEXT:    br label [[L5]]
733; IS__TUNIT_OPM:       l5:
734; IS__TUNIT_OPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
735; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
736; IS__TUNIT_OPM:       l6:
737; IS__TUNIT_OPM-NEXT:    store i32 0, i32* [[P]], align 4
738; IS__TUNIT_OPM-NEXT:    br label [[END:%.*]]
739; IS__TUNIT_OPM:       l7:
740; IS__TUNIT_OPM-NEXT:    store i32 1, i32* [[P]], align 4
741; IS__TUNIT_OPM-NEXT:    br label [[END]]
742; IS__TUNIT_OPM:       end:
743; IS__TUNIT_OPM-NEXT:    ret i32 1
744;
745; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
746; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis
747; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) [[ATTR4:#.*]] {
748; IS__TUNIT_NPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
749; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
750; IS__TUNIT_NPM:       l1:
751; IS__TUNIT_NPM-NEXT:    br label [[L4:%.*]]
752; IS__TUNIT_NPM:       l2:
753; IS__TUNIT_NPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
754; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]
755; IS__TUNIT_NPM:       l3:
756; IS__TUNIT_NPM-NEXT:    br label [[L5:%.*]]
757; IS__TUNIT_NPM:       l4:
758; IS__TUNIT_NPM-NEXT:    br label [[L5]]
759; IS__TUNIT_NPM:       l5:
760; IS__TUNIT_NPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
761; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
762; IS__TUNIT_NPM:       l6:
763; IS__TUNIT_NPM-NEXT:    store i32 0, i32* [[P]], align 4
764; IS__TUNIT_NPM-NEXT:    br label [[END:%.*]]
765; IS__TUNIT_NPM:       l7:
766; IS__TUNIT_NPM-NEXT:    store i32 1, i32* [[P]], align 4
767; IS__TUNIT_NPM-NEXT:    br label [[END]]
768; IS__TUNIT_NPM:       end:
769; IS__TUNIT_NPM-NEXT:    ret i32 1
770;
771; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
772; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis
773; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR4:#.*]] {
774; IS__CGSCC_OPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
775; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
776; IS__CGSCC_OPM:       l1:
777; IS__CGSCC_OPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
778; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
779; IS__CGSCC_OPM:       l2:
780; IS__CGSCC_OPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
781; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
782; IS__CGSCC_OPM:       l3:
783; IS__CGSCC_OPM-NEXT:    br label [[L5:%.*]]
784; IS__CGSCC_OPM:       l4:
785; IS__CGSCC_OPM-NEXT:    br label [[L5]]
786; IS__CGSCC_OPM:       l5:
787; IS__CGSCC_OPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
788; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
789; IS__CGSCC_OPM:       l6:
790; IS__CGSCC_OPM-NEXT:    store i32 0, i32* [[P]], align 4
791; IS__CGSCC_OPM-NEXT:    br label [[END:%.*]]
792; IS__CGSCC_OPM:       l7:
793; IS__CGSCC_OPM-NEXT:    store i32 1, i32* [[P]], align 4
794; IS__CGSCC_OPM-NEXT:    br label [[END]]
795; IS__CGSCC_OPM:       end:
796; IS__CGSCC_OPM-NEXT:    ret i32 1
797;
798; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
799; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis
800; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) [[ATTR4:#.*]] {
801; IS__CGSCC_NPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
802; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
803; IS__CGSCC_NPM:       l1:
804; IS__CGSCC_NPM-NEXT:    br label [[L4:%.*]]
805; IS__CGSCC_NPM:       l2:
806; IS__CGSCC_NPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
807; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]
808; IS__CGSCC_NPM:       l3:
809; IS__CGSCC_NPM-NEXT:    br label [[L5:%.*]]
810; IS__CGSCC_NPM:       l4:
811; IS__CGSCC_NPM-NEXT:    br label [[L5]]
812; IS__CGSCC_NPM:       l5:
813; IS__CGSCC_NPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
814; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
815; IS__CGSCC_NPM:       l6:
816; IS__CGSCC_NPM-NEXT:    store i32 0, i32* [[P]], align 4
817; IS__CGSCC_NPM-NEXT:    br label [[END:%.*]]
818; IS__CGSCC_NPM:       l7:
819; IS__CGSCC_NPM-NEXT:    store i32 1, i32* [[P]], align 4
820; IS__CGSCC_NPM-NEXT:    br label [[END]]
821; IS__CGSCC_NPM:       end:
822; IS__CGSCC_NPM-NEXT:    ret i32 1
823;
824  %tobool1 = icmp eq i32 %c, 0
825  br i1 %tobool1, label %l1, label %l2
826l1:
827  %tobool2 = icmp eq i32 %c, 1
828  br i1 %tobool2, label %l3, label %l4
829l2:
830  %tobool3 = icmp eq i32 %c, 2
831  br i1 %tobool3, label %l3, label %l4
832l3:
833  br label %l5
834l4:
835  br label %l5
836l5:
837  %tobool4 = icmp eq i32 %c, 4
838  br i1 %tobool4, label %l6, label %l7
839l6:
840  store i32 0, i32* %p
841  br label %end
842l7:
843  store i32 1, i32* %p
844  br label %end
845end:
846  ret i32 1
847}
848