[ORC] Add std::tuple support to SimplePackedSerialization.
[llvm-project.git] / llvm / test / Transforms / InferFunctionAttrs / dereferenceable-inseltpoison.ll
blobac3245e8a86c03bdb90589fc2f50ffe6eeeb1699
1 ; RUN: opt < %s -inferattrs -S | FileCheck %s
5 ; Determine dereference-ability before unused loads get deleted:
6 ; https://bugs.llvm.org/show_bug.cgi?id=21780
8 define <4 x double> @PR21780(double* %ptr) {
9 ; CHECK-LABEL: @PR21780(double* %ptr)
11   ; GEP of index 0 is simplified away.
12   %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
13   %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
14   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
16   %t0 = load double, double* %ptr, align 8
17   %t1 = load double, double* %arrayidx1, align 8
18   %t2 = load double, double* %arrayidx2, align 8
19   %t3 = load double, double* %arrayidx3, align 8
21   %vecinit0 = insertelement <4 x double> poison, double %t0, i32 0
22   %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
23   %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
24   %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
25   %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
26   ret <4 x double> %shuffle
30 define double @PR21780_only_access3_with_inbounds(double* %ptr) {
31 ; CHECK-LABEL: @PR21780_only_access3_with_inbounds(double* %ptr)
33   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
34   %t3 = load double, double* %arrayidx3, align 8
35   ret double %t3
38 define double @PR21780_only_access3_without_inbounds(double* %ptr) {
39 ; CHECK-LABEL: @PR21780_only_access3_without_inbounds(double* %ptr)
40   %arrayidx3 = getelementptr double, double* %ptr, i64 3
41   %t3 = load double, double* %arrayidx3, align 8
42   ret double %t3
45 define double @PR21780_without_inbounds(double* %ptr) {
46 ; CHECK-LABEL: @PR21780_without_inbounds(double* %ptr)
48   %arrayidx1 = getelementptr double, double* %ptr, i64 1
49   %arrayidx2 = getelementptr double, double* %ptr, i64 2
50   %arrayidx3 = getelementptr double, double* %ptr, i64 3
52   %t0 = load double, double* %ptr, align 8
53   %t1 = load double, double* %arrayidx1, align 8
54   %t2 = load double, double* %arrayidx2, align 8
55   %t3 = load double, double* %arrayidx3, align 8
57   ret double %t3
60 ; Unsimplified, but still valid. Also, throw in some bogus arguments.
62 define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
63 ; CHECK-LABEL: @gep0(i8* %unused, i8* %other, i8* %ptr)
64   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
65   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
66   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
67   %t0 = load i8, i8* %arrayidx0
68   %t1 = load i8, i8* %arrayidx1
69   %t2 = load i8, i8* %arrayidx2
70   store i8 %t2, i8* %other
71   ret void
74 ; Order of accesses does not change computation.
75 ; Multiple arguments may be dereferenceable.
77 define void @ordering(i8* %ptr1, i32* %ptr2) {
78 ; CHECK-LABEL: @ordering(i8* %ptr1, i32* %ptr2)
79   %a20 = getelementptr i32, i32* %ptr2, i64 0
80   %a12 = getelementptr i8, i8* %ptr1, i64 2
81   %t12 = load i8, i8* %a12
82   %a11 = getelementptr i8, i8* %ptr1, i64 1
83   %t20 = load i32, i32* %a20
84   %a10 = getelementptr i8, i8* %ptr1, i64 0
85   %t10 = load i8, i8* %a10
86   %t11 = load i8, i8* %a11
87   %a21 = getelementptr i32, i32* %ptr2, i64 1
88   %t21 = load i32, i32* %a21
89   ret void
92 ; Not in entry block.
94 define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
95 ; CHECK-LABEL: @not_entry_but_guaranteed_to_execute(i8* %ptr)
96 entry:
97   br label %exit
98 exit:
99   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
100   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
101   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
102   %t0 = load i8, i8* %arrayidx0
103   %t1 = load i8, i8* %arrayidx1
104   %t2 = load i8, i8* %arrayidx2
105   ret void
108 ; Not in entry block and not guaranteed to execute.
110 define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
111 ; CHECK-LABEL: @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond)
112 entry:
113   br i1 %cond, label %loads, label %exit
114 loads:
115   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
116   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
117   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
118   %t0 = load i8, i8* %arrayidx0
119   %t1 = load i8, i8* %arrayidx1
120   %t2 = load i8, i8* %arrayidx2
121   ret void
122 exit:
123   ret void
126 ; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
128 define void @partial_in_entry(i16* %ptr, i1 %cond) {
129 ; CHECK-LABEL: @partial_in_entry(i16* %ptr, i1 %cond)
130 entry:
131   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
132   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
133   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
134   %t0 = load i16, i16* %arrayidx0
135   %t1 = load i16, i16* %arrayidx1
136   br i1 %cond, label %loads, label %exit
137 loads:
138   %t2 = load i16, i16* %arrayidx2
139   ret void
140 exit:
141   ret void
144 ; The volatile load can't be used to prove a non-volatile access is allowed.
145 ; The 2nd and 3rd loads may never execute.
147 define void @volatile_is_not_dereferenceable(i16* %ptr) {
148 ; CHECK-LABEL: @volatile_is_not_dereferenceable(i16* %ptr)
149   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
150   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
151   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
152   %t0 = load volatile i16, i16* %arrayidx0
153   %t1 = load i16, i16* %arrayidx1
154   %t2 = load i16, i16* %arrayidx2
155   ret void
158 ; TODO: We should allow inference for atomic (but not volatile) ops.
160 define void @atomic_is_alright(i16* %ptr) {
161 ; CHECK-LABEL: @atomic_is_alright(i16* %ptr)
162   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
163   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
164   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
165   %t0 = load atomic i16, i16* %arrayidx0 unordered, align 2
166   %t1 = load i16, i16* %arrayidx1
167   %t2 = load i16, i16* %arrayidx2
168   ret void
171 declare void @may_not_return()
173 define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
174 ; CHECK-LABEL: @not_guaranteed_to_transfer_execution(i16* %ptr)
175   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
176   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
177   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
178   %t0 = load i16, i16* %arrayidx0
179   call void @may_not_return()
180   %t1 = load i16, i16* %arrayidx1
181   %t2 = load i16, i16* %arrayidx2
182   ret void
185 ; We must have consecutive accesses.
187 define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
188 ; CHECK-LABEL: @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index)
189   %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
190   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
191   %t0 = load i8, i8* %ptr
192   %t1 = load i8, i8* %arrayidx1
193   %t2 = load i8, i8* %arrayidx2
194   ret void
197 ; Deal with >1 GEP index.
199 define void @multi_index_gep(<4 x i8>* %ptr) {
200 ; CHECK-LABEL: @multi_index_gep(<4 x i8>* %ptr)
201 ; FIXME: %ptr should be dereferenceable(4)
202   %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
203   %t0 = load i8, i8* %arrayidx00
204   ret void
207 ; Could round weird bitwidths down?
209 define void @not_byte_multiple(i9* %ptr) {
210 ; CHECK-LABEL: @not_byte_multiple(i9* %ptr)
211   %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
212   %t0 = load i9, i9* %arrayidx0
213   ret void
216 ; Missing direct access from the pointer.
218 define void @no_pointer_deref(i16* %ptr) {
219 ; CHECK-LABEL: @no_pointer_deref(i16* %ptr)
220   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
221   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
222   %t1 = load i16, i16* %arrayidx1
223   %t2 = load i16, i16* %arrayidx2
224   ret void
227 ; Out-of-order is ok, but missing access concludes dereferenceable range.
229 define void @non_consecutive(i32* %ptr) {
230 ; CHECK-LABEL: @non_consecutive(i32* %ptr)
231   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
232   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
233   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
234   %t1 = load i32, i32* %arrayidx1
235   %t0 = load i32, i32* %arrayidx0
236   %t3 = load i32, i32* %arrayidx3
237   ret void
240 ; Improve on existing dereferenceable attribute.
242 define void @more_bytes(i32* dereferenceable(8) %ptr) {
243 ; CHECK-LABEL: @more_bytes(i32* dereferenceable(8) %ptr)
244   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
245   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
246   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
247   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
248   %t3 = load i32, i32* %arrayidx3
249   %t1 = load i32, i32* %arrayidx1
250   %t2 = load i32, i32* %arrayidx2
251   %t0 = load i32, i32* %arrayidx0
252   ret void
255 ; Improve on existing dereferenceable_or_null attribute.
257 define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) {
258 ; CHECK-LABEL: @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr)
259   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
260   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
261   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
262   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
263   %t3 = load i32, i32* %arrayidx3
264   %t1 = load i32, i32* %arrayidx1
265   %t2 = load i32, i32* %arrayidx2
266   %t0 = load i32, i32* %arrayidx0
267   ret void
270 ; But don't pessimize existing dereferenceable attribute.
272 define void @better_bytes(i32* dereferenceable(100) %ptr) {
273 ; CHECK-LABEL: @better_bytes(i32* dereferenceable(100) %ptr)
274   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
275   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
276   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
277   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
278   %t3 = load i32, i32* %arrayidx3
279   %t1 = load i32, i32* %arrayidx1
280   %t2 = load i32, i32* %arrayidx2
281   %t0 = load i32, i32* %arrayidx0
282   ret void
285 define void @bitcast(i32* %arg) {
286 ; CHECK-LABEL: @bitcast(i32* %arg)
287   %ptr = bitcast i32* %arg to float*
288   %arrayidx0 = getelementptr float, float* %ptr, i64 0
289   %arrayidx1 = getelementptr float, float* %ptr, i64 1
290   %t0 = load float, float* %arrayidx0
291   %t1 = load float, float* %arrayidx1
292   ret void
295 define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
296 ; CHECK-LABEL: @bitcast_different_sizes(double* %arg1, i8* %arg2)
297   %ptr1 = bitcast double* %arg1 to float*
298   %a10 = getelementptr float, float* %ptr1, i64 0
299   %a11 = getelementptr float, float* %ptr1, i64 1
300   %a12 = getelementptr float, float* %ptr1, i64 2
301   %ld10 = load float, float* %a10
302   %ld11 = load float, float* %a11
303   %ld12 = load float, float* %a12
305   %ptr2 = bitcast i8* %arg2 to i64*
306   %a20 = getelementptr i64, i64* %ptr2, i64 0
307   %a21 = getelementptr i64, i64* %ptr2, i64 1
308   %ld20 = load i64, i64* %a20
309   %ld21 = load i64, i64* %a21
310   ret void
313 define void @negative_offset(i32* %arg) {
314 ; CHECK-LABEL: @negative_offset(i32* %arg)
315   %ptr = bitcast i32* %arg to float*
316   %arrayidx0 = getelementptr float, float* %ptr, i64 0
317   %arrayidx1 = getelementptr float, float* %ptr, i64 -1
318   %t0 = load float, float* %arrayidx0
319   %t1 = load float, float* %arrayidx1
320   ret void
323 define void @stores(i32* %arg) {
324 ; CHECK-LABEL: @stores(i32* %arg)
325   %ptr = bitcast i32* %arg to float*
326   %arrayidx0 = getelementptr float, float* %ptr, i64 0
327   %arrayidx1 = getelementptr float, float* %ptr, i64 1
328   store float 1.0, float* %arrayidx0
329   store float 2.0, float* %arrayidx1
330   ret void
333 define void @load_store(i32* %arg) {
334 ; CHECK-LABEL: @load_store(i32* %arg)
335   %ptr = bitcast i32* %arg to float*
336   %arrayidx0 = getelementptr float, float* %ptr, i64 0
337   %arrayidx1 = getelementptr float, float* %ptr, i64 1
338   %t1 = load float, float* %arrayidx0
339   store float 2.0, float* %arrayidx1
340   ret void
343 define void @different_size1(i32* %arg) {
344 ; CHECK-LABEL: @different_size1(i32* %arg)
345   %arg-cast = bitcast i32* %arg to double*
346   store double 0.000000e+00, double* %arg-cast
347   store i32 0, i32* %arg
348   ret void
351 define void @different_size2(i32* %arg) {
352 ; CHECK-LABEL: @different_size2(i32* %arg)
353   store i32 0, i32* %arg
354   %arg-cast = bitcast i32* %arg to double*
355   store double 0.000000e+00, double* %arg-cast
356   ret void