[ARM] More MVE compare vector splat combines for ANDs
[llvm-complete.git] / test / Transforms / InferFunctionAttrs / dereferenceable.ll
blobf6580826bd146392a8a5ee06842d8dc8f7e9d0df
1 ; RUN: opt < %s -inferattrs -S | FileCheck %s
3 ; Determine dereference-ability before unused loads get deleted:
4 ; https://bugs.llvm.org/show_bug.cgi?id=21780
6 define <4 x double> @PR21780(double* %ptr) {
7 ; CHECK-LABEL: @PR21780(double* %ptr)
8   ; GEP of index 0 is simplified away.
9   %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
10   %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
11   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
13   %t0 = load double, double* %ptr, align 8
14   %t1 = load double, double* %arrayidx1, align 8
15   %t2 = load double, double* %arrayidx2, align 8
16   %t3 = load double, double* %arrayidx3, align 8
18   %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
19   %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
20   %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
21   %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
22   %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
23   ret <4 x double> %shuffle
26 ; Unsimplified, but still valid. Also, throw in some bogus arguments.
28 define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
29 ; CHECK-LABEL: @gep0(i8* %unused, i8* %other, i8* %ptr)
30   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
31   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
32   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
33   %t0 = load i8, i8* %arrayidx0
34   %t1 = load i8, i8* %arrayidx1
35   %t2 = load i8, i8* %arrayidx2
36   store i8 %t2, i8* %other
37   ret void
40 ; Order of accesses does not change computation.
41 ; Multiple arguments may be dereferenceable.
43 define void @ordering(i8* %ptr1, i32* %ptr2) {
44 ; CHECK-LABEL: @ordering(i8* %ptr1, i32* %ptr2)
45   %a20 = getelementptr i32, i32* %ptr2, i64 0
46   %a12 = getelementptr i8, i8* %ptr1, i64 2
47   %t12 = load i8, i8* %a12
48   %a11 = getelementptr i8, i8* %ptr1, i64 1
49   %t20 = load i32, i32* %a20
50   %a10 = getelementptr i8, i8* %ptr1, i64 0
51   %t10 = load i8, i8* %a10
52   %t11 = load i8, i8* %a11
53   %a21 = getelementptr i32, i32* %ptr2, i64 1
54   %t21 = load i32, i32* %a21
55   ret void
58 ; Not in entry block.
60 define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
61 ; CHECK-LABEL: @not_entry_but_guaranteed_to_execute(i8* %ptr)
62 entry:
63   br label %exit
64 exit:
65   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
66   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
67   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
68   %t0 = load i8, i8* %arrayidx0
69   %t1 = load i8, i8* %arrayidx1
70   %t2 = load i8, i8* %arrayidx2
71   ret void
74 ; Not in entry block and not guaranteed to execute.
76 define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
77 ; CHECK-LABEL: @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond)
78 entry:
79   br i1 %cond, label %loads, label %exit
80 loads:
81   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
82   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
83   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
84   %t0 = load i8, i8* %arrayidx0
85   %t1 = load i8, i8* %arrayidx1
86   %t2 = load i8, i8* %arrayidx2
87   ret void
88 exit:
89   ret void
92 ; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
94 define void @partial_in_entry(i16* %ptr, i1 %cond) {
95 ; CHECK-LABEL: @partial_in_entry(i16* %ptr, i1 %cond)
96 entry:
97   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
98   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
99   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
100   %t0 = load i16, i16* %arrayidx0
101   %t1 = load i16, i16* %arrayidx1
102   br i1 %cond, label %loads, label %exit
103 loads:
104   %t2 = load i16, i16* %arrayidx2
105   ret void
106 exit:
107   ret void
110 ; The volatile load can't be used to prove a non-volatile access is allowed.
111 ; The 2nd and 3rd loads may never execute.
113 define void @volatile_is_not_dereferenceable(i16* %ptr) {
114 ; CHECK-LABEL: @volatile_is_not_dereferenceable(i16* %ptr)
115   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
116   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
117   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
118   %t0 = load volatile i16, i16* %arrayidx0
119   %t1 = load i16, i16* %arrayidx1
120   %t2 = load i16, i16* %arrayidx2
121   ret void
124 declare void @may_not_return()
126 define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
127 ; CHECK-LABEL: @not_guaranteed_to_transfer_execution(i16* %ptr)
128   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
129   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
130   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
131   %t0 = load i16, i16* %arrayidx0
132   call void @may_not_return()
133   %t1 = load i16, i16* %arrayidx1
134   %t2 = load i16, i16* %arrayidx2
135   ret void
138 ; We must have consecutive accesses.
140 define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
141 ; CHECK-LABEL: @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index)
142   %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
143   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
144   %t0 = load i8, i8* %ptr
145   %t1 = load i8, i8* %arrayidx1
146   %t2 = load i8, i8* %arrayidx2
147   ret void
150 ; Deal with >1 GEP index.
152 define void @multi_index_gep(<4 x i8>* %ptr) {
153 ; CHECK-LABEL: @multi_index_gep(<4 x i8>* %ptr)
154   %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
155   %t0 = load i8, i8* %arrayidx00
156   ret void
159 ; Could round weird bitwidths down?
161 define void @not_byte_multiple(i9* %ptr) {
162 ; CHECK-LABEL: @not_byte_multiple(i9* %ptr)
163   %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
164   %t0 = load i9, i9* %arrayidx0
165   ret void
168 ; Missing direct access from the pointer.
170 define void @no_pointer_deref(i16* %ptr) {
171 ; CHECK-LABEL: @no_pointer_deref(i16* %ptr)
172   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
173   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
174   %t1 = load i16, i16* %arrayidx1
175   %t2 = load i16, i16* %arrayidx2
176   ret void
179 ; Out-of-order is ok, but missing access concludes dereferenceable range.
181 define void @non_consecutive(i32* %ptr) {
182 ; CHECK-LABEL: @non_consecutive(i32* %ptr)
183   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
184   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
185   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
186   %t1 = load i32, i32* %arrayidx1
187   %t0 = load i32, i32* %arrayidx0
188   %t3 = load i32, i32* %arrayidx3
189   ret void
192 ; Improve on existing dereferenceable attribute.
194 define void @more_bytes(i32* dereferenceable(8) %ptr) {
195 ; CHECK-LABEL: @more_bytes(i32* dereferenceable(8) %ptr)
196   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
197   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
198   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
199   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
200   %t3 = load i32, i32* %arrayidx3
201   %t1 = load i32, i32* %arrayidx1
202   %t2 = load i32, i32* %arrayidx2
203   %t0 = load i32, i32* %arrayidx0
204   ret void
207 ; But don't pessimize existing dereferenceable attribute.
209 define void @better_bytes(i32* dereferenceable(100) %ptr) {
210 ; CHECK-LABEL: @better_bytes(i32* dereferenceable(100) %ptr)
211   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
212   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
213   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
214   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
215   %t3 = load i32, i32* %arrayidx3
216   %t1 = load i32, i32* %arrayidx1
217   %t2 = load i32, i32* %arrayidx2
218   %t0 = load i32, i32* %arrayidx0
219   ret void
222 define void @bitcast(i32* %arg) {
223 ; CHECK-LABEL: @bitcast(i32* %arg)
224   %ptr = bitcast i32* %arg to float*
225   %arrayidx0 = getelementptr float, float* %ptr, i64 0
226   %arrayidx1 = getelementptr float, float* %ptr, i64 1
227   %t0 = load float, float* %arrayidx0
228   %t1 = load float, float* %arrayidx1
229   ret void
232 define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
233 ; CHECK-LABEL: @bitcast_different_sizes(double* %arg1, i8* %arg2)
234   %ptr1 = bitcast double* %arg1 to float*
235   %a10 = getelementptr float, float* %ptr1, i64 0
236   %a11 = getelementptr float, float* %ptr1, i64 1
237   %a12 = getelementptr float, float* %ptr1, i64 2
238   %ld10 = load float, float* %a10
239   %ld11 = load float, float* %a11
240   %ld12 = load float, float* %a12
242   %ptr2 = bitcast i8* %arg2 to i64*
243   %a20 = getelementptr i64, i64* %ptr2, i64 0
244   %a21 = getelementptr i64, i64* %ptr2, i64 1
245   %ld20 = load i64, i64* %a20
246   %ld21 = load i64, i64* %a21
247   ret void
250 define void @negative_offset(i32* %arg) {
251 ; CHECK-LABEL: @negative_offset(i32* %arg)
252   %ptr = bitcast i32* %arg to float*
253   %arrayidx0 = getelementptr float, float* %ptr, i64 0
254   %arrayidx1 = getelementptr float, float* %ptr, i64 -1
255   %t0 = load float, float* %arrayidx0
256   %t1 = load float, float* %arrayidx1
257   ret void
260 define void @stores(i32* %arg) {
261 ; CHECK-LABEL: @stores(i32* %arg)
262   %ptr = bitcast i32* %arg to float*
263   %arrayidx0 = getelementptr float, float* %ptr, i64 0
264   %arrayidx1 = getelementptr float, float* %ptr, i64 1
265   store float 1.0, float* %arrayidx0
266   store float 2.0, float* %arrayidx1
267   ret void
270 define void @load_store(i32* %arg) {
271 ; CHECK-LABEL: @load_store(i32* %arg)
272   %ptr = bitcast i32* %arg to float*
273   %arrayidx0 = getelementptr float, float* %ptr, i64 0
274   %arrayidx1 = getelementptr float, float* %ptr, i64 1
275   %t1 = load float, float* %arrayidx0
276   store float 2.0, float* %arrayidx1
277   ret void