[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / Attributor / dereferenceable-2.ll
blobab407c3a84eb73dce497164d93a8b7abac8681a8
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=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
7 ; Determine dereference-ability before unused loads get deleted:
8 ; https://bugs.llvm.org/show_bug.cgi?id=21780
10 define <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 noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
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]]
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 noundef nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) #[[ATTR0:[0-9]+]] {
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]]
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
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
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
65 define 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]]
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]]
81   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
82   %t3 = load double, double* %arrayidx3, align 8
83   ret double %t3
86 define 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]]
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]]
101   %arrayidx3 = getelementptr double, double* %ptr, i64 3
102   %t3 = load double, double* %arrayidx3, align 8
103   ret double %t3
106 define 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 noundef 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]]
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 noundef 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]]
122   %arrayidx1 = getelementptr double, double* %ptr, i64 1
123   %arrayidx2 = getelementptr double, double* %ptr, i64 2
124   %arrayidx3 = getelementptr double, double* %ptr, i64 3
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
131   ret double %t3
134 ; Unsimplified, but still valid. Also, throw in some bogus arguments.
136 define 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 noundef nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
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
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 noundef nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) #[[ATTR1:[0-9]+]] {
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
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
163 ; Order of accesses does not change computation.
164 ; Multiple arguments may be dereferenceable.
166 define 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:[0-9]+]] {
170 ; IS__TUNIT____-NEXT:    ret void
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:[0-9]+]] {
175 ; IS__CGSCC____-NEXT:    ret void
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
190 ; Not in entry block.
192 define 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
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
209 entry:
210   br label %exit
211 exit:
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
221 ; Not in entry block and not guaranteed to execute.
223 define 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
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
244 entry:
245   br i1 %cond, label %loads, label %exit
246 loads:
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
254 exit:
255   ret void
258 ; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
260 define 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
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
281 entry:
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
288 loads:
289   %t2 = load i16, i16* %arrayidx2
290   ret void
291 exit:
292   ret void
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.
298 define 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:[0-9]+]] {
302 ; IS__TUNIT____-NEXT:    [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2
303 ; IS__TUNIT____-NEXT:    ret void
305 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn
306 ; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable
307 ; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) #[[ATTR3:[0-9]+]] {
308 ; IS__CGSCC____-NEXT:    [[T0:%.*]] = load volatile i16, i16* [[PTR]], align 2
309 ; IS__CGSCC____-NEXT:    ret void
311   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
312   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
313   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
314   %t0 = load volatile i16, i16* %arrayidx0
315   %t1 = load i16, i16* %arrayidx1
316   %t2 = load i16, i16* %arrayidx2
317   ret void
320 ; TODO: We should allow inference for atomic (but not volatile) ops.
322 define void @atomic_is_alright(i16* %ptr) {
323 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
324 ; IS__TUNIT____-LABEL: define {{[^@]+}}@atomic_is_alright
325 ; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) #[[ATTR2]] {
326 ; IS__TUNIT____-NEXT:    ret void
328 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
329 ; IS__CGSCC____-LABEL: define {{[^@]+}}@atomic_is_alright
330 ; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) #[[ATTR2]] {
331 ; IS__CGSCC____-NEXT:    ret void
333   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
334   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
335   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
336   %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2
337   %t1 = load i16, i16* %arrayidx1
338   %t2 = load i16, i16* %arrayidx2
339   ret void
342 declare void @may_not_return()
344 define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
345 ; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution
346 ; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) {
347 ; CHECK-NEXT:    call void @may_not_return()
348 ; CHECK-NEXT:    ret void
350   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
351   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
352   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
353   %t0 = load i16, i16* %arrayidx0
354   call void @may_not_return()
355   %t1 = load i16, i16* %arrayidx1
356   %t2 = load i16, i16* %arrayidx2
357   ret void
360 ; We must have consecutive accesses.
362 define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
363 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
364 ; IS__TUNIT____-LABEL: define {{[^@]+}}@variable_gep_index
365 ; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) #[[ATTR2]] {
366 ; IS__TUNIT____-NEXT:    ret void
368 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
369 ; IS__CGSCC____-LABEL: define {{[^@]+}}@variable_gep_index
370 ; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) #[[ATTR2]] {
371 ; IS__CGSCC____-NEXT:    ret void
373   %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
374   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
375   %t0 = load i8, i8* %ptr
376   %t1 = load i8, i8* %arrayidx1
377   %t2 = load i8, i8* %arrayidx2
378   ret void
381 ; Deal with >1 GEP index.
383 define void @multi_index_gep(<4 x i8>* %ptr) {
384 ; FIXME: %ptr should be dereferenceable(4)
385 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
386 ; IS__TUNIT____-LABEL: define {{[^@]+}}@multi_index_gep
387 ; IS__TUNIT____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) #[[ATTR2]] {
388 ; IS__TUNIT____-NEXT:    ret void
390 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
391 ; IS__CGSCC____-LABEL: define {{[^@]+}}@multi_index_gep
392 ; IS__CGSCC____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) #[[ATTR2]] {
393 ; IS__CGSCC____-NEXT:    ret void
395   %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
396   %t0 = load i8, i8* %arrayidx00
397   ret void
400 ; Could round weird bitwidths down?
402 define void @not_byte_multiple(i9* %ptr) {
403 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
404 ; IS__TUNIT____-LABEL: define {{[^@]+}}@not_byte_multiple
405 ; IS__TUNIT____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) #[[ATTR2]] {
406 ; IS__TUNIT____-NEXT:    ret void
408 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
409 ; IS__CGSCC____-LABEL: define {{[^@]+}}@not_byte_multiple
410 ; IS__CGSCC____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) #[[ATTR2]] {
411 ; IS__CGSCC____-NEXT:    ret void
413   %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
414   %t0 = load i9, i9* %arrayidx0
415   ret void
418 ; Missing direct access from the pointer.
420 define void @no_pointer_deref(i16* %ptr) {
421 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
422 ; IS__TUNIT____-LABEL: define {{[^@]+}}@no_pointer_deref
423 ; IS__TUNIT____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) #[[ATTR2]] {
424 ; IS__TUNIT____-NEXT:    ret void
426 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
427 ; IS__CGSCC____-LABEL: define {{[^@]+}}@no_pointer_deref
428 ; IS__CGSCC____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) #[[ATTR2]] {
429 ; IS__CGSCC____-NEXT:    ret void
431   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
432   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
433   %t1 = load i16, i16* %arrayidx1
434   %t2 = load i16, i16* %arrayidx2
435   ret void
438 ; Out-of-order is ok, but missing access concludes dereferenceable range.
440 define void @non_consecutive(i32* %ptr) {
441 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
442 ; IS__TUNIT____-LABEL: define {{[^@]+}}@non_consecutive
443 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) #[[ATTR2]] {
444 ; IS__TUNIT____-NEXT:    ret void
446 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
447 ; IS__CGSCC____-LABEL: define {{[^@]+}}@non_consecutive
448 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) #[[ATTR2]] {
449 ; IS__CGSCC____-NEXT:    ret void
451   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
452   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
453   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
454   %t1 = load i32, i32* %arrayidx1
455   %t0 = load i32, i32* %arrayidx0
456   %t3 = load i32, i32* %arrayidx3
457   ret void
460 ; Improve on existing dereferenceable attribute.
462 define void @more_bytes(i32* dereferenceable(8) %ptr) {
463 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
464 ; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes
465 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
466 ; IS__TUNIT____-NEXT:    ret void
468 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
469 ; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes
470 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
471 ; IS__CGSCC____-NEXT:    ret void
473   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
474   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
475   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
476   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
477   %t3 = load i32, i32* %arrayidx3
478   %t1 = load i32, i32* %arrayidx1
479   %t2 = load i32, i32* %arrayidx2
480   %t0 = load i32, i32* %arrayidx0
481   ret void
484 ; Improve on existing dereferenceable_or_null attribute.
486 define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
487 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
488 ; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes_and_not_null
489 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
490 ; IS__TUNIT____-NEXT:    ret void
492 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
493 ; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes_and_not_null
494 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) #[[ATTR2]] {
495 ; IS__CGSCC____-NEXT:    ret void
497   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
498   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
499   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
500   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
501   %t3 = load i32, i32* %arrayidx3
502   %t1 = load i32, i32* %arrayidx1
503   %t2 = load i32, i32* %arrayidx2
504   %t0 = load i32, i32* %arrayidx0
505   ret void
508 ; But don't pessimize existing dereferenceable attribute.
510 define void @better_bytes(i32* dereferenceable(100) %ptr) {
511 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
512 ; IS__TUNIT____-LABEL: define {{[^@]+}}@better_bytes
513 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) #[[ATTR2]] {
514 ; IS__TUNIT____-NEXT:    ret void
516 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
517 ; IS__CGSCC____-LABEL: define {{[^@]+}}@better_bytes
518 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) #[[ATTR2]] {
519 ; IS__CGSCC____-NEXT:    ret void
521   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
522   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
523   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
524   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
525   %t3 = load i32, i32* %arrayidx3
526   %t1 = load i32, i32* %arrayidx1
527   %t2 = load i32, i32* %arrayidx2
528   %t0 = load i32, i32* %arrayidx0
529   ret void
532 define void @bitcast(i32* %arg) {
533 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
534 ; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast
535 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR2]] {
536 ; IS__TUNIT____-NEXT:    ret void
538 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
539 ; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast
540 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR2]] {
541 ; IS__CGSCC____-NEXT:    ret void
543   %ptr = bitcast i32* %arg to float*
544   %arrayidx0 = getelementptr float, float* %ptr, i64 0
545   %arrayidx1 = getelementptr float, float* %ptr, i64 1
546   %t0 = load float, float* %arrayidx0
547   %t1 = load float, float* %arrayidx1
548   ret void
551 define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
552 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
553 ; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast_different_sizes
554 ; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) #[[ATTR2]] {
555 ; IS__TUNIT____-NEXT:    ret void
557 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
558 ; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast_different_sizes
559 ; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) #[[ATTR2]] {
560 ; IS__CGSCC____-NEXT:    ret void
562   %ptr1 = bitcast double* %arg1 to float*
563   %a10 = getelementptr float, float* %ptr1, i64 0
564   %a11 = getelementptr float, float* %ptr1, i64 1
565   %a12 = getelementptr float, float* %ptr1, i64 2
566   %ld10 = load float, float* %a10
567   %ld11 = load float, float* %a11
568   %ld12 = load float, float* %a12
570   %ptr2 = bitcast i8* %arg2 to i64*
571   %a20 = getelementptr i64, i64* %ptr2, i64 0
572   %a21 = getelementptr i64, i64* %ptr2, i64 1
573   %ld20 = load i64, i64* %a20
574   %ld21 = load i64, i64* %a21
575   ret void
578 define void @negative_offset(i32* %arg) {
579 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
580 ; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_offset
581 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR2]] {
582 ; IS__TUNIT____-NEXT:    ret void
584 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
585 ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_offset
586 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR2]] {
587 ; IS__CGSCC____-NEXT:    ret void
589   %ptr = bitcast i32* %arg to float*
590   %arrayidx0 = getelementptr float, float* %ptr, i64 0
591   %arrayidx1 = getelementptr float, float* %ptr, i64 -1
592   %t0 = load float, float* %arrayidx0
593   %t1 = load float, float* %arrayidx1
594   ret void
597 define void @stores(i32* %arg) {
598 ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
599 ; IS__TUNIT____-LABEL: define {{[^@]+}}@stores
600 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
601 ; IS__TUNIT____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
602 ; IS__TUNIT____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0
603 ; IS__TUNIT____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
604 ; IS__TUNIT____-NEXT:    store float 1.000000e+00, float* [[ARRAYIDX0]], align 4
605 ; IS__TUNIT____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
606 ; IS__TUNIT____-NEXT:    ret void
608 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
609 ; IS__CGSCC____-LABEL: define {{[^@]+}}@stores
610 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4:[0-9]+]] {
611 ; IS__CGSCC____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
612 ; IS__CGSCC____-NEXT:    [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0
613 ; IS__CGSCC____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
614 ; IS__CGSCC____-NEXT:    store float 1.000000e+00, float* [[ARRAYIDX0]], align 4
615 ; IS__CGSCC____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
616 ; IS__CGSCC____-NEXT:    ret void
618   %ptr = bitcast i32* %arg to float*
619   %arrayidx0 = getelementptr float, float* %ptr, i64 0
620   %arrayidx1 = getelementptr float, float* %ptr, i64 1
621   store float 1.0, float* %arrayidx0
622   store float 2.0, float* %arrayidx1
623   ret void
626 define void @load_store(i32* %arg) {
627 ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
628 ; IS__TUNIT____-LABEL: define {{[^@]+}}@load_store
629 ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
630 ; IS__TUNIT____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
631 ; IS__TUNIT____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
632 ; IS__TUNIT____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
633 ; IS__TUNIT____-NEXT:    ret void
635 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
636 ; IS__CGSCC____-LABEL: define {{[^@]+}}@load_store
637 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
638 ; IS__CGSCC____-NEXT:    [[PTR:%.*]] = bitcast i32* [[ARG]] to float*
639 ; IS__CGSCC____-NEXT:    [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1
640 ; IS__CGSCC____-NEXT:    store float 2.000000e+00, float* [[ARRAYIDX1]], align 4
641 ; IS__CGSCC____-NEXT:    ret void
643   %ptr = bitcast i32* %arg to float*
644   %arrayidx0 = getelementptr float, float* %ptr, i64 0
645   %arrayidx1 = getelementptr float, float* %ptr, i64 1
646   %t1 = load float, float* %arrayidx0
647   store float 2.0, float* %arrayidx1
648   ret void
651 define void @different_size1(i32* %arg) {
652 ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
653 ; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size1
654 ; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
655 ; IS__TUNIT____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
656 ; IS__TUNIT____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
657 ; IS__TUNIT____-NEXT:    store i32 0, i32* [[ARG]], align 8
658 ; IS__TUNIT____-NEXT:    ret void
660 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
661 ; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size1
662 ; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
663 ; IS__CGSCC____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
664 ; IS__CGSCC____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
665 ; IS__CGSCC____-NEXT:    store i32 0, i32* [[ARG]], align 8
666 ; IS__CGSCC____-NEXT:    ret void
668   %arg-cast = bitcast i32* %arg to double*
669   store double 0.000000e+00, double* %arg-cast
670   store i32 0, i32* %arg
671   ret void
674 define void @different_size2(i32* %arg) {
675 ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
676 ; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size2
677 ; IS__TUNIT____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
678 ; IS__TUNIT____-NEXT:    store i32 0, i32* [[ARG]], align 8
679 ; IS__TUNIT____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
680 ; IS__TUNIT____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
681 ; IS__TUNIT____-NEXT:    ret void
683 ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
684 ; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size2
685 ; IS__CGSCC____-SAME: (i32* nocapture nofree noundef nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) #[[ATTR4]] {
686 ; IS__CGSCC____-NEXT:    store i32 0, i32* [[ARG]], align 8
687 ; IS__CGSCC____-NEXT:    [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double*
688 ; IS__CGSCC____-NEXT:    store double 0.000000e+00, double* [[ARG_CAST]], align 8
689 ; IS__CGSCC____-NEXT:    ret void
691   store i32 0, i32* %arg
692   %arg-cast = bitcast i32* %arg to double*
693   store double 0.000000e+00, double* %arg-cast
694   ret void
697 ; Make use of MustBeExecuted Explorer
699 ; [CFG]
700 ; entry
701 ;  / \
702 ; l1 l2
703 ; | X |
704 ; l3 l4
705 ;  \ /
706 ;  l5
707 ;  / \
708 ; l6 l7
709 ;  \ /
710 ;  end
711 ; According to the above CFG, we can see that instructions in l5 Block must be executed.
712 ; Therefore, %p must be dereferenced.
714 ; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p)
715 define i32 @require_cfg_analysis(i32 %c, i32* %p) {
716 ; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
717 ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis
718 ; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR4]] {
719 ; IS__TUNIT_OPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
720 ; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
721 ; IS__TUNIT_OPM:       l1:
722 ; IS__TUNIT_OPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
723 ; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
724 ; IS__TUNIT_OPM:       l2:
725 ; IS__TUNIT_OPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
726 ; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
727 ; IS__TUNIT_OPM:       l3:
728 ; IS__TUNIT_OPM-NEXT:    br label [[L5:%.*]]
729 ; IS__TUNIT_OPM:       l4:
730 ; IS__TUNIT_OPM-NEXT:    br label [[L5]]
731 ; IS__TUNIT_OPM:       l5:
732 ; IS__TUNIT_OPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
733 ; IS__TUNIT_OPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
734 ; IS__TUNIT_OPM:       l6:
735 ; IS__TUNIT_OPM-NEXT:    store i32 0, i32* [[P]], align 4
736 ; IS__TUNIT_OPM-NEXT:    br label [[END:%.*]]
737 ; IS__TUNIT_OPM:       l7:
738 ; IS__TUNIT_OPM-NEXT:    store i32 1, i32* [[P]], align 4
739 ; IS__TUNIT_OPM-NEXT:    br label [[END]]
740 ; IS__TUNIT_OPM:       end:
741 ; IS__TUNIT_OPM-NEXT:    ret i32 1
743 ; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly
744 ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis
745 ; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {
746 ; IS__TUNIT_NPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
747 ; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
748 ; IS__TUNIT_NPM:       l1:
749 ; IS__TUNIT_NPM-NEXT:    br label [[L4:%.*]]
750 ; IS__TUNIT_NPM:       l2:
751 ; IS__TUNIT_NPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
752 ; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]
753 ; IS__TUNIT_NPM:       l3:
754 ; IS__TUNIT_NPM-NEXT:    br label [[L5:%.*]]
755 ; IS__TUNIT_NPM:       l4:
756 ; IS__TUNIT_NPM-NEXT:    br label [[L5]]
757 ; IS__TUNIT_NPM:       l5:
758 ; IS__TUNIT_NPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
759 ; IS__TUNIT_NPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
760 ; IS__TUNIT_NPM:       l6:
761 ; IS__TUNIT_NPM-NEXT:    store i32 0, i32* [[P]], align 4
762 ; IS__TUNIT_NPM-NEXT:    br label [[END:%.*]]
763 ; IS__TUNIT_NPM:       l7:
764 ; IS__TUNIT_NPM-NEXT:    store i32 1, i32* [[P]], align 4
765 ; IS__TUNIT_NPM-NEXT:    br label [[END]]
766 ; IS__TUNIT_NPM:       end:
767 ; IS__TUNIT_NPM-NEXT:    ret i32 1
769 ; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
770 ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis
771 ; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) #[[ATTR4]] {
772 ; IS__CGSCC_OPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
773 ; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
774 ; IS__CGSCC_OPM:       l1:
775 ; IS__CGSCC_OPM-NEXT:    [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1
776 ; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]]
777 ; IS__CGSCC_OPM:       l2:
778 ; IS__CGSCC_OPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
779 ; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL3]], label [[L3]], label [[L4]]
780 ; IS__CGSCC_OPM:       l3:
781 ; IS__CGSCC_OPM-NEXT:    br label [[L5:%.*]]
782 ; IS__CGSCC_OPM:       l4:
783 ; IS__CGSCC_OPM-NEXT:    br label [[L5]]
784 ; IS__CGSCC_OPM:       l5:
785 ; IS__CGSCC_OPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
786 ; IS__CGSCC_OPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
787 ; IS__CGSCC_OPM:       l6:
788 ; IS__CGSCC_OPM-NEXT:    store i32 0, i32* [[P]], align 4
789 ; IS__CGSCC_OPM-NEXT:    br label [[END:%.*]]
790 ; IS__CGSCC_OPM:       l7:
791 ; IS__CGSCC_OPM-NEXT:    store i32 1, i32* [[P]], align 4
792 ; IS__CGSCC_OPM-NEXT:    br label [[END]]
793 ; IS__CGSCC_OPM:       end:
794 ; IS__CGSCC_OPM-NEXT:    ret i32 1
796 ; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly
797 ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis
798 ; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) #[[ATTR4]] {
799 ; IS__CGSCC_NPM-NEXT:    [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0
800 ; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]]
801 ; IS__CGSCC_NPM:       l1:
802 ; IS__CGSCC_NPM-NEXT:    br label [[L4:%.*]]
803 ; IS__CGSCC_NPM:       l2:
804 ; IS__CGSCC_NPM-NEXT:    [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2
805 ; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]]
806 ; IS__CGSCC_NPM:       l3:
807 ; IS__CGSCC_NPM-NEXT:    br label [[L5:%.*]]
808 ; IS__CGSCC_NPM:       l4:
809 ; IS__CGSCC_NPM-NEXT:    br label [[L5]]
810 ; IS__CGSCC_NPM:       l5:
811 ; IS__CGSCC_NPM-NEXT:    [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4
812 ; IS__CGSCC_NPM-NEXT:    br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]]
813 ; IS__CGSCC_NPM:       l6:
814 ; IS__CGSCC_NPM-NEXT:    store i32 0, i32* [[P]], align 4
815 ; IS__CGSCC_NPM-NEXT:    br label [[END:%.*]]
816 ; IS__CGSCC_NPM:       l7:
817 ; IS__CGSCC_NPM-NEXT:    store i32 1, i32* [[P]], align 4
818 ; IS__CGSCC_NPM-NEXT:    br label [[END]]
819 ; IS__CGSCC_NPM:       end:
820 ; IS__CGSCC_NPM-NEXT:    ret i32 1
822   %tobool1 = icmp eq i32 %c, 0
823   br i1 %tobool1, label %l1, label %l2
825   %tobool2 = icmp eq i32 %c, 1
826   br i1 %tobool2, label %l3, label %l4
828   %tobool3 = icmp eq i32 %c, 2
829   br i1 %tobool3, label %l3, label %l4
831   br label %l5
833   br label %l5
835   %tobool4 = icmp eq i32 %c, 4
836   br i1 %tobool4, label %l6, label %l7
838   store i32 0, i32* %p
839   br label %end
841   store i32 1, i32* %p
842   br label %end
843 end:
844   ret i32 1
847 ; IS__TUNIT____: attributes #[[ATTR0]] = { argmemonly nofree nosync nounwind readonly willreturn }
848 ; IS__TUNIT____: attributes #[[ATTR1]] = { argmemonly nofree nosync nounwind willreturn }
849 ; IS__TUNIT____: attributes #[[ATTR2]] = { nofree nosync nounwind readnone willreturn }
850 ; IS__TUNIT____: attributes #[[ATTR3]] = { argmemonly nofree nounwind willreturn }
851 ; IS__TUNIT____: attributes #[[ATTR4]] = { argmemonly nofree nosync nounwind willreturn writeonly }
853 ; IS__CGSCC____: attributes #[[ATTR0]] = { argmemonly nofree norecurse nosync nounwind readonly willreturn }
854 ; IS__CGSCC____: attributes #[[ATTR1]] = { argmemonly nofree norecurse nosync nounwind willreturn }
855 ; IS__CGSCC____: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone willreturn }
856 ; IS__CGSCC____: attributes #[[ATTR3]] = { argmemonly nofree norecurse nounwind willreturn }
857 ; IS__CGSCC____: attributes #[[ATTR4]] = { argmemonly nofree norecurse nosync nounwind willreturn writeonly }