xref: /llvm-project/llvm/test/CodeGen/ARM/memfunc.ll (revision 70605f7d2230aebbccb9c0edc7504446f95f412f)
1; RUN: llc < %s -mtriple=armv7-apple-ios -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-IOS --check-prefix=CHECK
2; RUN: llc < %s -mtriple=thumbv7m-none-macho -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-DARWIN --check-prefix=CHECK
3; RUN: llc < %s -mtriple=arm-none-eabi -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-EABI --check-prefix=CHECK
4; RUN: llc < %s -mtriple=arm-none-eabihf -disable-post-ra -o - | FileCheck %s --check-prefix=CHECK-EABI --check-prefix=CHECK
5
6define void @f1(i8* %dest, i8* %src) {
7entry:
8  ; CHECK-LABEL: f1
9
10  ; CHECK-IOS: memmove
11  ; CHECK-DARWIN: memmove
12  ; CHECK-EABI: __aeabi_memmove
13  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 0, i1 false)
14
15  ; CHECK-IOS: memcpy
16  ; CHECK-DARWIN: memcpy
17  ; CHECK-EABI: __aeabi_memcpy
18  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 0, i1 false)
19
20  ; EABI memset swaps arguments
21  ; CHECK-IOS: mov r1, #1
22  ; CHECK-IOS: memset
23  ; CHECK-DARWIN: movs r1, #1
24  ; CHECK-DARWIN: memset
25  ; CHECK-EABI: mov r2, #1
26  ; CHECK-EABI: __aeabi_memset
27  call void @llvm.memset.p0i8.i32(i8* %dest, i8 1, i32 500, i32 0, i1 false)
28
29  ; EABI uses memclr if value set to 0
30  ; CHECK-IOS: mov r1, #0
31  ; CHECK-IOS: memset
32  ; CHECK-DARWIN: movs r1, #0
33  ; CHECK-DARWIN: memset
34  ; CHECK-EABI: __aeabi_memclr
35  call void @llvm.memset.p0i8.i32(i8* %dest, i8 0, i32 500, i32 0, i1 false)
36
37  ; EABI uses aligned function variants if possible
38
39  ; CHECK-IOS: memmove
40  ; CHECK-DARWIN: memmove
41  ; CHECK-EABI: __aeabi_memmove4
42  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 4, i1 false)
43
44  ; CHECK-IOS: memcpy
45  ; CHECK-DARWIN: memcpy
46  ; CHECK-EABI: __aeabi_memcpy4
47  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 4, i1 false)
48
49  ; CHECK-IOS: memset
50  ; CHECK-DARWIN: memset
51  ; CHECK-EABI: __aeabi_memset4
52  call void @llvm.memset.p0i8.i32(i8* %dest, i8 1, i32 500, i32 4, i1 false)
53
54  ; CHECK-IOS: memset
55  ; CHECK-DARWIN: memset
56  ; CHECK-EABI: __aeabi_memclr4
57  call void @llvm.memset.p0i8.i32(i8* %dest, i8 0, i32 500, i32 4, i1 false)
58
59  ; CHECK-IOS: memmove
60  ; CHECK-DARWIN: memmove
61  ; CHECK-EABI: __aeabi_memmove8
62  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 8, i1 false)
63
64  ; CHECK-IOS: memcpy
65  ; CHECK-DARWIN: memcpy
66  ; CHECK-EABI: __aeabi_memcpy8
67  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 500, i32 8, i1 false)
68
69  ; CHECK-IOS: memset
70  ; CHECK-DARWIN: memset
71  ; CHECK-EABI: __aeabi_memset8
72  call void @llvm.memset.p0i8.i32(i8* %dest, i8 1, i32 500, i32 8, i1 false)
73
74  ; CHECK-IOS: memset
75  ; CHECK-DARWIN: memset
76  ; CHECK-EABI: __aeabi_memclr8
77  call void @llvm.memset.p0i8.i32(i8* %dest, i8 0, i32 500, i32 8, i1 false)
78
79  unreachable
80}
81
82; Check that alloca arguments to memory intrinsics are automatically aligned if at least 8 bytes in size
83define void @f2(i8* %dest, i32 %n) {
84entry:
85  ; CHECK-LABEL: f2
86
87  ; IOS (ARMv7) should 8-byte align, others should 4-byte align
88  ; CHECK-IOS: add r1, sp, #32
89  ; CHECK-IOS: memmove
90  ; CHECK-DARWIN: add r1, sp, #28
91  ; CHECK-DARWIN: memmove
92  ; CHECK-EABI: add r1, sp, #28
93  ; CHECK-EABI: __aeabi_memmove
94  %arr0 = alloca [9 x i8], align 1
95  %0 = bitcast [9 x i8]* %arr0 to i8*
96  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
97
98  ; CHECK: add r1, sp, #16
99  ; CHECK-IOS: memcpy
100  ; CHECK-DARWIN: memcpy
101  ; CHECK-EABI: __aeabi_memcpy
102  %arr1 = alloca [9 x i8], align 1
103  %1 = bitcast [9 x i8]* %arr1 to i8*
104  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
105
106  ; CHECK-IOS: mov r0, sp
107  ; CHECK-IOS: mov r1, #1
108  ; CHECK-IOS: memset
109  ; CHECK-DARWIN: add r0, sp, #4
110  ; CHECK-DARWIN: movs r1, #1
111  ; CHECK-DARWIN: memset
112  ; CHECK-EABI: add r0, sp, #4
113  ; CHECK-EABI: mov r2, #1
114  ; CHECK-EABI: __aeabi_memset
115  %arr2 = alloca [9 x i8], align 1
116  %2 = bitcast [9 x i8]* %arr2 to i8*
117  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
118
119  unreachable
120}
121
122; Check that alloca arguments are not aligned if less than 8 bytes in size
123define void @f3(i8* %dest, i32 %n) {
124entry:
125  ; CHECK-LABEL: f3
126
127  ; CHECK: {{add(.w)? r1, sp, #17|sub(.w)? r1, r7, #15}}
128  ; CHECK-IOS: memmove
129  ; CHECK-DARWIN: memmove
130  ; CHECK-EABI: __aeabi_memmove
131  %arr0 = alloca [7 x i8], align 1
132  %0 = bitcast [7 x i8]* %arr0 to i8*
133  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
134
135  ; CHECK: {{add(.w)? r1, sp, #10}}
136  ; CHECK-IOS: memcpy
137  ; CHECK-DARWIN: memcpy
138  ; CHECK-EABI: __aeabi_memcpy
139  %arr1 = alloca [7 x i8], align 1
140  %1 = bitcast [7 x i8]* %arr1 to i8*
141  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
142
143  ; CHECK: {{add(.w)? r0, sp, #3}}
144  ; CHECK-IOS: mov r1, #1
145  ; CHECK-IOS: memset
146  ; CHECK-DARWIN: movs r1, #1
147  ; CHECK-DARWIN: memset
148  ; CHECK-EABI: mov r2, #1
149  ; CHECK-EABI: __aeabi_memset
150  %arr2 = alloca [7 x i8], align 1
151  %2 = bitcast [7 x i8]* %arr2 to i8*
152  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
153
154  unreachable
155}
156
157; Check that alloca arguments are not aligned if size+offset is less than 8 bytes
158define void @f4(i8* %dest, i32 %n) {
159entry:
160  ; CHECK-LABEL: f4
161
162  ; CHECK: {{add(.w)? r., sp, #23|sub(.w)? r., r7, #17}}
163  ; CHECK-IOS: memmove
164  ; CHECK-DARWIN: memmove
165  ; CHECK-EABI: __aeabi_memmove
166  %arr0 = alloca [9 x i8], align 1
167  %0 = getelementptr inbounds [9 x i8], [9 x i8]* %arr0, i32 0, i32 4
168  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
169
170  ; CHECK: {{add(.w)? r., sp, #(10|14)}}
171  ; CHECK-IOS: memcpy
172  ; CHECK-DARWIN: memcpy
173  ; CHECK-EABI: __aeabi_memcpy
174  %arr1 = alloca [9 x i8], align 1
175  %1 = getelementptr inbounds [9 x i8], [9 x i8]* %arr1, i32 0, i32 4
176  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
177
178  ; CHECK: {{add(.w)? r., sp, #(1|5)}}
179  ; CHECK-IOS: mov r1, #1
180  ; CHECK-IOS: memset
181  ; CHECK-DARWIN: movs r1, #1
182  ; CHECK-DARWIN: memset
183  ; CHECK-EABI: mov r2, #1
184  ; CHECK-EABI: __aeabi_memset
185  %arr2 = alloca [9 x i8], align 1
186  %2 = getelementptr inbounds [9 x i8], [9 x i8]* %arr2, i32 0, i32 4
187  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
188
189  unreachable
190}
191
192; Check that alloca arguments are not aligned if the offset is not a multiple of 4
193define void @f5(i8* %dest, i32 %n) {
194entry:
195  ; CHECK-LABEL: f5
196
197  ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
198  ; CHECK-IOS: memmove
199  ; CHECK-DARWIN: memmove
200  ; CHECK-EABI: __aeabi_memmove
201  %arr0 = alloca [13 x i8], align 1
202  %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 1
203  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
204
205  ; CHECK: {{add(.w)? r., sp, #(10|14)}}
206  ; CHECK-IOS: memcpy
207  ; CHECK-DARWIN: memcpy
208  ; CHECK-EABI: __aeabi_memcpy
209  %arr1 = alloca [13 x i8], align 1
210  %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 1
211  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
212
213  ; CHECK: {{add(.w)? r., sp, #(1|5)}}
214  ; CHECK-IOS: mov r1, #1
215  ; CHECK-IOS: memset
216  ; CHECK-DARWIN: movs r1, #1
217  ; CHECK-DARWIN: memset
218  ; CHECK-EABI: mov r2, #1
219  ; CHECK-EABI: __aeabi_memset
220  %arr2 = alloca [13 x i8], align 1
221  %2 = getelementptr inbounds [13 x i8], [13 x i8]* %arr2, i32 0, i32 1
222  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
223
224  unreachable
225}
226
227; Check that alloca arguments are not aligned if the offset is unknown
228define void @f6(i8* %dest, i32 %n, i32 %i) {
229entry:
230  ; CHECK-LABEL: f6
231
232  ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #25}}
233  ; CHECK-IOS: memmove
234  ; CHECK-DARWIN: memmove
235  ; CHECK-EABI: __aeabi_memmove
236  %arr0 = alloca [13 x i8], align 1
237  %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 %i
238  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
239
240  ; CHECK: {{add(.w)? r., sp, #(10|14)}}
241  ; CHECK-IOS: memcpy
242  ; CHECK-DARWIN: memcpy
243  ; CHECK-EABI: __aeabi_memcpy
244  %arr1 = alloca [13 x i8], align 1
245  %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 %i
246  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
247
248  ; CHECK: {{add(.w)? r., sp, #(1|5)}}
249  ; CHECK-IOS: mov r1, #1
250  ; CHECK-IOS: memset
251  ; CHECK-DARWIN: movs r1, #1
252  ; CHECK-DARWIN: memset
253  ; CHECK-EABI: mov r2, #1
254  ; CHECK-EABI: __aeabi_memset
255  %arr2 = alloca [13 x i8], align 1
256  %2 = getelementptr inbounds [13 x i8], [13 x i8]* %arr2, i32 0, i32 %i
257  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
258
259  unreachable
260}
261
262; Check that alloca arguments are not aligned if the GEP is not inbounds
263define void @f7(i8* %dest, i32 %n) {
264entry:
265  ; CHECK-LABEL: f7
266
267  ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
268  ; CHECK-IOS: memmove
269  ; CHECK-DARWIN: memmove
270  ; CHECK-EABI: __aeabi_memmove
271  %arr0 = alloca [13 x i8], align 1
272  %0 = getelementptr [13 x i8], [13 x i8]* %arr0, i32 0, i32 4
273  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
274
275  ; CHECK: {{add(.w)? r., sp, #(10|14)}}
276  ; CHECK-IOS: memcpy
277  ; CHECK-DARWIN: memcpy
278  ; CHECK-EABI: __aeabi_memcpy
279  %arr1 = alloca [13 x i8], align 1
280  %1 = getelementptr [13 x i8], [13 x i8]* %arr1, i32 0, i32 4
281  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
282
283  ; CHECK: {{add(.w)? r., sp, #(1|5)}}
284  ; CHECK-IOS: mov r1, #1
285  ; CHECK-IOS: memset
286  ; CHECK-DARWIN: movs r1, #1
287  ; CHECK-DARWIN: memset
288  ; CHECK-EABI: mov r2, #1
289  ; CHECK-EABI: __aeabi_memset
290  %arr2 = alloca [13 x i8], align 1
291  %2 = getelementptr [13 x i8], [13 x i8]* %arr2, i32 0, i32 4
292  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
293
294  unreachable
295}
296
297; Check that alloca arguments are not aligned when the offset is past the end of the allocation
298define void @f8(i8* %dest, i32 %n) {
299entry:
300  ; CHECK-LABEL: f8
301
302  ; CHECK: {{add(.w)? r., sp, #27|sub(.w)? r., r7, #21}}
303  ; CHECK-IOS: memmove
304  ; CHECK-DARWIN: memmove
305  ; CHECK-EABI: __aeabi_memmove
306  %arr0 = alloca [13 x i8], align 1
307  %0 = getelementptr inbounds [13 x i8], [13 x i8]* %arr0, i32 0, i32 16
308  call void @llvm.memmove.p0i8.p0i8.i32(i8* %dest, i8* %0, i32 %n, i32 0, i1 false)
309
310  ; CHECK: {{add(.w)? r., sp, #(10|14)}}
311  ; CHECK-IOS: memcpy
312  ; CHECK-DARWIN: memcpy
313  ; CHECK-EABI: __aeabi_memcpy
314  %arr1 = alloca [13 x i8], align 1
315  %1 = getelementptr inbounds [13 x i8], [13 x i8]* %arr1, i32 0, i32 16
316  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %1, i32 %n, i32 0, i1 false)
317
318  ; CHECK: {{add(.w)? r., sp, #(1|5)}}
319  ; CHECK-IOS: mov r1, #1
320  ; CHECK-IOS: memset
321  ; CHECK-DARWIN: movs r1, #1
322  ; CHECK-DARWIN: memset
323  ; CHECK-EABI: mov r2, #1
324  ; CHECK-EABI: __aeabi_memset
325  %arr2 = alloca [13 x i8], align 1
326  %2 = getelementptr inbounds [13 x i8], [13 x i8]* %arr2, i32 0, i32 16
327  call void @llvm.memset.p0i8.i32(i8* %2, i8 1, i32 %n, i32 0, i1 false)
328
329  unreachable
330}
331
332; Check that global variables are aligned if they are large enough, but only if
333; they are defined in this object and don't have an explicit section.
334@arr1 = global [7 x i8] c"\01\02\03\04\05\06\07", align 1
335@arr2 = global [8 x i8] c"\01\02\03\04\05\06\07\08", align 1
336@arr3 = global [7 x i8] c"\01\02\03\04\05\06\07", section "foo,bar", align 1
337@arr4 = global [8 x i8] c"\01\02\03\04\05\06\07\08", section "foo,bar", align 1
338@arr5 = weak global [7 x i8] c"\01\02\03\04\05\06\07", align 1
339@arr6 = weak_odr global [7 x i8] c"\01\02\03\04\05\06\07", align 1
340@arr7 = external global [7 x i8], align 1
341define void @f9(i8* %dest, i32 %n) {
342entry:
343  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr1, i32 0, i32 0), i32 %n, i32 1, i1 false)
344  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @arr2, i32 0, i32 0), i32 %n, i32 1, i1 false)
345  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr3, i32 0, i32 0), i32 %n, i32 1, i1 false)
346  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @arr4, i32 0, i32 0), i32 %n, i32 1, i1 false)
347  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr5, i32 0, i32 0), i32 %n, i32 1, i1 false)
348  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr6, i32 0, i32 0), i32 %n, i32 1, i1 false)
349  call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* getelementptr inbounds ([7 x i8], [7 x i8]* @arr7, i32 0, i32 0), i32 %n, i32 1, i1 false)
350
351  unreachable
352}
353
354; CHECK: {{\.data|\.section.+data}}
355; CHECK-NOT: .align
356; CHECK: arr1:
357; CHECK-IOS: .align 3
358; CHECK-DARWIN: .align 2
359; CHECK-EABI: .align 2
360; CHECK: arr2:
361; CHECK: {{\.section.+foo,bar}}
362; CHECK-NOT: .align
363; CHECK: arr3:
364; CHECK-NOT: .align
365; CHECK: arr4:
366; CHECK: {{\.data|\.section.+data}}
367; CHECK-NOT: .align
368; CHECK: arr5:
369; CHECK-NOT: .align
370; CHECK: arr6:
371; CHECK-NOT: arr7:
372
373declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
374declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
375declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind
376