[InstCombine] Signed saturation patterns
[llvm-complete.git] / test / Transforms / InferFunctionAttrs / dereferenceable.ll
blob17c76f11d6c8e33929a826937de7a56a2afc9711
1 ; RUN: opt < %s -inferattrs -S | FileCheck %s
2 ; RUN: opt < %s -attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR
6 ; Determine dereference-ability before unused loads get deleted:
7 ; https://bugs.llvm.org/show_bug.cgi?id=21780
9 define <4 x double> @PR21780(double* %ptr) {
10 ; CHECK-LABEL: @PR21780(double* %ptr)
11 ; FIXME: this should be @PR21780(double* nonnull dereferenceable(32) %ptr) 
12 ;        trakcing use of GEP in Attributor would fix this problem.
13 ; ATTRIBUTOR-LABEL: @PR21780(double* nocapture nonnull readonly dereferenceable(8) %ptr)
15   ; GEP of index 0 is simplified away.
16   %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1
17   %arrayidx2 = getelementptr inbounds double, double* %ptr, i64 2
18   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
20   %t0 = load double, double* %ptr, align 8
21   %t1 = load double, double* %arrayidx1, align 8
22   %t2 = load double, double* %arrayidx2, align 8
23   %t3 = load double, double* %arrayidx3, align 8
25   %vecinit0 = insertelement <4 x double> undef, double %t0, i32 0
26   %vecinit1 = insertelement <4 x double> %vecinit0, double %t1, i32 1
27   %vecinit2 = insertelement <4 x double> %vecinit1, double %t2, i32 2
28   %vecinit3 = insertelement <4 x double> %vecinit2, double %t3, i32 3
29   %shuffle = shufflevector <4 x double> %vecinit3, <4 x double> %vecinit3, <4 x i32> <i32 0, i32 0, i32 2, i32 2>
30   ret <4 x double> %shuffle
34 define double @PR21780_only_access3_with_inbounds(double* %ptr) {
35 ; CHECK-LABEL: @PR21780_only_access3_with_inbounds(double* %ptr)
36 ; FIXME: this should be @PR21780_only_access3_with_inbounds(double* nonnull dereferenceable(32) %ptr)
37 ;        trakcing use of GEP in Attributor would fix this problem.
38 ; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture readonly %ptr) 
40   %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
41   %t3 = load double, double* %arrayidx3, align 8
42   ret double %t3
45 define double @PR21780_only_access3_without_inbounds(double* %ptr) {
46 ; CHECK-LABEL: @PR21780_only_access3_without_inbounds(double* %ptr)
47 ; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture readonly %ptr)
48   %arrayidx3 = getelementptr double, double* %ptr, i64 3
49   %t3 = load double, double* %arrayidx3, align 8
50   ret double %t3
53 define double @PR21780_without_inbounds(double* %ptr) {
54 ; CHECK-LABEL: @PR21780_without_inbounds(double* %ptr)
55 ; FIXME: this should be @PR21780_without_inbounds(double* nonnull dereferenceable(32) %ptr)
56 ; ATTRIBUTOR-LABEL: @PR21780_without_inbounds(double* nocapture nonnull readonly dereferenceable(8) %ptr)
58   %arrayidx1 = getelementptr double, double* %ptr, i64 1
59   %arrayidx2 = getelementptr double, double* %ptr, i64 2
60   %arrayidx3 = getelementptr double, double* %ptr, i64 3
62   %t0 = load double, double* %ptr, align 8
63   %t1 = load double, double* %arrayidx1, align 8
64   %t2 = load double, double* %arrayidx2, align 8
65   %t3 = load double, double* %arrayidx3, align 8
67   ret double %t3
70 ; Unsimplified, but still valid. Also, throw in some bogus arguments.
72 define void @gep0(i8* %unused, i8* %other, i8* %ptr) {
73 ; CHECK-LABEL: @gep0(i8* %unused, i8* %other, i8* %ptr)
74   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
75   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
76   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
77   %t0 = load i8, i8* %arrayidx0
78   %t1 = load i8, i8* %arrayidx1
79   %t2 = load i8, i8* %arrayidx2
80   store i8 %t2, i8* %other
81   ret void
84 ; Order of accesses does not change computation.
85 ; Multiple arguments may be dereferenceable.
87 define void @ordering(i8* %ptr1, i32* %ptr2) {
88 ; CHECK-LABEL: @ordering(i8* %ptr1, i32* %ptr2)
89   %a20 = getelementptr i32, i32* %ptr2, i64 0
90   %a12 = getelementptr i8, i8* %ptr1, i64 2
91   %t12 = load i8, i8* %a12
92   %a11 = getelementptr i8, i8* %ptr1, i64 1
93   %t20 = load i32, i32* %a20
94   %a10 = getelementptr i8, i8* %ptr1, i64 0
95   %t10 = load i8, i8* %a10
96   %t11 = load i8, i8* %a11
97   %a21 = getelementptr i32, i32* %ptr2, i64 1
98   %t21 = load i32, i32* %a21
99   ret void
102 ; Not in entry block.
104 define void @not_entry_but_guaranteed_to_execute(i8* %ptr) {
105 ; CHECK-LABEL: @not_entry_but_guaranteed_to_execute(i8* %ptr)
106 entry:
107   br label %exit
108 exit:
109   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
110   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
111   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
112   %t0 = load i8, i8* %arrayidx0
113   %t1 = load i8, i8* %arrayidx1
114   %t2 = load i8, i8* %arrayidx2
115   ret void
118 ; Not in entry block and not guaranteed to execute.
120 define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) {
121 ; CHECK-LABEL: @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond)
122 entry:
123   br i1 %cond, label %loads, label %exit
124 loads:
125   %arrayidx0 = getelementptr i8, i8* %ptr, i64 0
126   %arrayidx1 = getelementptr i8, i8* %ptr, i64 1
127   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
128   %t0 = load i8, i8* %arrayidx0
129   %t1 = load i8, i8* %arrayidx1
130   %t2 = load i8, i8* %arrayidx2
131   ret void
132 exit:
133   ret void
136 ; The last load may not execute, so derefenceable bytes only covers the 1st two loads.
138 define void @partial_in_entry(i16* %ptr, i1 %cond) {
139 ; CHECK-LABEL: @partial_in_entry(i16* %ptr, i1 %cond)
140 entry:
141   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
142   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
143   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
144   %t0 = load i16, i16* %arrayidx0
145   %t1 = load i16, i16* %arrayidx1
146   br i1 %cond, label %loads, label %exit
147 loads:
148   %t2 = load i16, i16* %arrayidx2
149   ret void
150 exit:
151   ret void
154 ; The volatile load can't be used to prove a non-volatile access is allowed.
155 ; The 2nd and 3rd loads may never execute.
157 define void @volatile_is_not_dereferenceable(i16* %ptr) {
158 ; CHECK-LABEL: @volatile_is_not_dereferenceable(i16* %ptr)
159   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
160   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
161   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
162   %t0 = load volatile i16, i16* %arrayidx0
163   %t1 = load i16, i16* %arrayidx1
164   %t2 = load i16, i16* %arrayidx2
165   ret void
168 declare void @may_not_return()
170 define void @not_guaranteed_to_transfer_execution(i16* %ptr) {
171 ; CHECK-LABEL: @not_guaranteed_to_transfer_execution(i16* %ptr)
172   %arrayidx0 = getelementptr i16, i16* %ptr, i64 0
173   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
174   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
175   %t0 = load i16, i16* %arrayidx0
176   call void @may_not_return()
177   %t1 = load i16, i16* %arrayidx1
178   %t2 = load i16, i16* %arrayidx2
179   ret void
182 ; We must have consecutive accesses.
184 define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) {
185 ; CHECK-LABEL: @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index)
186   %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index
187   %arrayidx2 = getelementptr i8, i8* %ptr, i64 2
188   %t0 = load i8, i8* %ptr
189   %t1 = load i8, i8* %arrayidx1
190   %t2 = load i8, i8* %arrayidx2
191   ret void
194 ; Deal with >1 GEP index.
196 define void @multi_index_gep(<4 x i8>* %ptr) {
197 ; CHECK-LABEL: @multi_index_gep(<4 x i8>* %ptr)
198   %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0
199   %t0 = load i8, i8* %arrayidx00
200   ret void
203 ; Could round weird bitwidths down?
205 define void @not_byte_multiple(i9* %ptr) {
206 ; CHECK-LABEL: @not_byte_multiple(i9* %ptr)
207   %arrayidx0 = getelementptr i9, i9* %ptr, i64 0
208   %t0 = load i9, i9* %arrayidx0
209   ret void
212 ; Missing direct access from the pointer.
214 define void @no_pointer_deref(i16* %ptr) {
215 ; CHECK-LABEL: @no_pointer_deref(i16* %ptr)
216   %arrayidx1 = getelementptr i16, i16* %ptr, i64 1
217   %arrayidx2 = getelementptr i16, i16* %ptr, i64 2
218   %t1 = load i16, i16* %arrayidx1
219   %t2 = load i16, i16* %arrayidx2
220   ret void
223 ; Out-of-order is ok, but missing access concludes dereferenceable range.
225 define void @non_consecutive(i32* %ptr) {
226 ; CHECK-LABEL: @non_consecutive(i32* %ptr)
227   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
228   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
229   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
230   %t1 = load i32, i32* %arrayidx1
231   %t0 = load i32, i32* %arrayidx0
232   %t3 = load i32, i32* %arrayidx3
233   ret void
236 ; Improve on existing dereferenceable attribute.
238 define void @more_bytes(i32* dereferenceable(8) %ptr) {
239 ; CHECK-LABEL: @more_bytes(i32* dereferenceable(8) %ptr)
240   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
241   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
242   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
243   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
244   %t3 = load i32, i32* %arrayidx3
245   %t1 = load i32, i32* %arrayidx1
246   %t2 = load i32, i32* %arrayidx2
247   %t0 = load i32, i32* %arrayidx0
248   ret void
251 ; But don't pessimize existing dereferenceable attribute.
253 define void @better_bytes(i32* dereferenceable(100) %ptr) {
254 ; CHECK-LABEL: @better_bytes(i32* dereferenceable(100) %ptr)
255   %arrayidx3 = getelementptr i32, i32* %ptr, i64 3
256   %arrayidx1 = getelementptr i32, i32* %ptr, i64 1
257   %arrayidx0 = getelementptr i32, i32* %ptr, i64 0
258   %arrayidx2 = getelementptr i32, i32* %ptr, i64 2
259   %t3 = load i32, i32* %arrayidx3
260   %t1 = load i32, i32* %arrayidx1
261   %t2 = load i32, i32* %arrayidx2
262   %t0 = load i32, i32* %arrayidx0
263   ret void
266 define void @bitcast(i32* %arg) {
267 ; CHECK-LABEL: @bitcast(i32* %arg)
268   %ptr = bitcast i32* %arg to float*
269   %arrayidx0 = getelementptr float, float* %ptr, i64 0
270   %arrayidx1 = getelementptr float, float* %ptr, i64 1
271   %t0 = load float, float* %arrayidx0
272   %t1 = load float, float* %arrayidx1
273   ret void
276 define void @bitcast_different_sizes(double* %arg1, i8* %arg2) {
277 ; CHECK-LABEL: @bitcast_different_sizes(double* %arg1, i8* %arg2)
278   %ptr1 = bitcast double* %arg1 to float*
279   %a10 = getelementptr float, float* %ptr1, i64 0
280   %a11 = getelementptr float, float* %ptr1, i64 1
281   %a12 = getelementptr float, float* %ptr1, i64 2
282   %ld10 = load float, float* %a10
283   %ld11 = load float, float* %a11
284   %ld12 = load float, float* %a12
286   %ptr2 = bitcast i8* %arg2 to i64*
287   %a20 = getelementptr i64, i64* %ptr2, i64 0
288   %a21 = getelementptr i64, i64* %ptr2, i64 1
289   %ld20 = load i64, i64* %a20
290   %ld21 = load i64, i64* %a21
291   ret void
294 define void @negative_offset(i32* %arg) {
295 ; CHECK-LABEL: @negative_offset(i32* %arg)
296   %ptr = bitcast i32* %arg to float*
297   %arrayidx0 = getelementptr float, float* %ptr, i64 0
298   %arrayidx1 = getelementptr float, float* %ptr, i64 -1
299   %t0 = load float, float* %arrayidx0
300   %t1 = load float, float* %arrayidx1
301   ret void
304 define void @stores(i32* %arg) {
305 ; CHECK-LABEL: @stores(i32* %arg)
306   %ptr = bitcast i32* %arg to float*
307   %arrayidx0 = getelementptr float, float* %ptr, i64 0
308   %arrayidx1 = getelementptr float, float* %ptr, i64 1
309   store float 1.0, float* %arrayidx0
310   store float 2.0, float* %arrayidx1
311   ret void
314 define void @load_store(i32* %arg) {
315 ; CHECK-LABEL: @load_store(i32* %arg)
316   %ptr = bitcast i32* %arg to float*
317   %arrayidx0 = getelementptr float, float* %ptr, i64 0
318   %arrayidx1 = getelementptr float, float* %ptr, i64 1
319   %t1 = load float, float* %arrayidx0
320   store float 2.0, float* %arrayidx1
321   ret void