1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs < %s -mtriple=arm-eabi -mattr=v7,neon | FileCheck %s --check-prefixes=CHECK,CHECK-LE
3; RUN: llc -verify-machineinstrs < %s -mtriple=armeb-eabi -mattr=v7,neon | FileCheck %s --check-prefixes=CHECK,CHECK-BE
4
5@var32 = global i32 0
6@vardouble = global double 0.0
7
8define void @arg_longint( i64 %val ) {
9; CHECK-LE-LABEL: arg_longint:
10; CHECK-LE:       @ %bb.0:
11; CHECK-LE-NEXT:    movw r1, :lower16:var32
12; CHECK-LE-NEXT:    movt r1, :upper16:var32
13; CHECK-LE-NEXT:    str r0, [r1]
14; CHECK-LE-NEXT:    bx lr
15;
16; CHECK-BE-LABEL: arg_longint:
17; CHECK-BE:       @ %bb.0:
18; CHECK-BE-NEXT:    movw r0, :lower16:var32
19; CHECK-BE-NEXT:    movt r0, :upper16:var32
20; CHECK-BE-NEXT:    str r1, [r0]
21; CHECK-BE-NEXT:    bx lr
22   %tmp = trunc i64 %val to i32
23   store i32 %tmp, i32* @var32
24   ret void
25}
26
27define void @arg_double( double %val ) {
28; CHECK-LABEL: arg_double:
29; CHECK:       @ %bb.0:
30; CHECK-NEXT:    movw r2, :lower16:vardouble
31; CHECK-NEXT:    movt r2, :upper16:vardouble
32; CHECK-NEXT:    strd r0, r1, [r2]
33; CHECK-NEXT:    bx lr
34    store double  %val, double* @vardouble
35    ret void
36}
37
38define void @arg_v4i32(<4 x i32> %vec ) {
39; CHECK-LE-LABEL: arg_v4i32:
40; CHECK-LE:       @ %bb.0:
41; CHECK-LE-NEXT:    vmov d16, r0, r1
42; CHECK-LE-NEXT:    movw r0, :lower16:var32
43; CHECK-LE-NEXT:    movt r0, :upper16:var32
44; CHECK-LE-NEXT:    vst1.32 {d16[0]}, [r0:32]
45; CHECK-LE-NEXT:    bx lr
46;
47; CHECK-BE-LABEL: arg_v4i32:
48; CHECK-BE:       @ %bb.0:
49; CHECK-BE-NEXT:    vmov d16, r1, r0
50; CHECK-BE-NEXT:    movw r0, :lower16:var32
51; CHECK-BE-NEXT:    movt r0, :upper16:var32
52; CHECK-BE-NEXT:    vrev64.32 q8, q8
53; CHECK-BE-NEXT:    vst1.32 {d16[0]}, [r0:32]
54; CHECK-BE-NEXT:    bx lr
55    %tmp = extractelement <4 x i32> %vec, i32 0
56    store i32 %tmp, i32* @var32
57    ret void
58}
59
60define void @arg_v2f64(<2 x double> %vec ) {
61; CHECK-LABEL: arg_v2f64:
62; CHECK:       @ %bb.0:
63; CHECK-NEXT:    movw r2, :lower16:vardouble
64; CHECK-NEXT:    movt r2, :upper16:vardouble
65; CHECK-NEXT:    strd r0, r1, [r2]
66; CHECK-NEXT:    bx lr
67    %tmp = extractelement <2 x double> %vec, i32 0
68    store double %tmp, double* @vardouble
69    ret void
70}
71
72define i64 @return_longint() {
73; CHECK-LE-LABEL: return_longint:
74; CHECK-LE:       @ %bb.0:
75; CHECK-LE-NEXT:    mov r0, #42
76; CHECK-LE-NEXT:    mov r1, #0
77; CHECK-LE-NEXT:    bx lr
78;
79; CHECK-BE-LABEL: return_longint:
80; CHECK-BE:       @ %bb.0:
81; CHECK-BE-NEXT:    mov r0, #0
82; CHECK-BE-NEXT:    mov r1, #42
83; CHECK-BE-NEXT:    bx lr
84    ret i64 42
85}
86
87define double @return_double() {
88; CHECK-LE-LABEL: return_double:
89; CHECK-LE:       @ %bb.0:
90; CHECK-LE-NEXT:    vmov.f64 d16, #1.000000e+00
91; CHECK-LE-NEXT:    vmov r0, r1, d16
92; CHECK-LE-NEXT:    bx lr
93;
94; CHECK-BE-LABEL: return_double:
95; CHECK-BE:       @ %bb.0:
96; CHECK-BE-NEXT:    vmov.f64 d16, #1.000000e+00
97; CHECK-BE-NEXT:    vmov r1, r0, d16
98; CHECK-BE-NEXT:    bx lr
99    ret double 1.0
100}
101
102define <4 x i32> @return_v4i32() {
103; CHECK-LE-LABEL: return_v4i32:
104; CHECK-LE:       @ %bb.0:
105; CHECK-LE-NEXT:    adr r0, .LCPI6_0
106; CHECK-LE-NEXT:    vld1.64 {d16, d17}, [r0:128]
107; CHECK-LE-NEXT:    vmov r0, r1, d16
108; CHECK-LE-NEXT:    vmov r2, r3, d17
109; CHECK-LE-NEXT:    bx lr
110; CHECK-LE-NEXT:    .p2align 4
111; CHECK-LE-NEXT:  @ %bb.1:
112; CHECK-LE-NEXT:  .LCPI6_0:
113; CHECK-LE-NEXT:    .long 42 @ double 9.1245819032257467E-313
114; CHECK-LE-NEXT:    .long 43
115; CHECK-LE-NEXT:    .long 44 @ double 9.5489810615176143E-313
116; CHECK-LE-NEXT:    .long 45
117;
118; CHECK-BE-LABEL: return_v4i32:
119; CHECK-BE:       @ %bb.0:
120; CHECK-BE-NEXT:    adr r0, .LCPI6_0
121; CHECK-BE-NEXT:    vld1.64 {d16, d17}, [r0:128]
122; CHECK-BE-NEXT:    vmov r1, r0, d16
123; CHECK-BE-NEXT:    vmov r3, r2, d17
124; CHECK-BE-NEXT:    bx lr
125; CHECK-BE-NEXT:    .p2align 4
126; CHECK-BE-NEXT:  @ %bb.1:
127; CHECK-BE-NEXT:  .LCPI6_0:
128; CHECK-BE-NEXT:    .long 42 @ double 8.912382324178626E-313
129; CHECK-BE-NEXT:    .long 43
130; CHECK-BE-NEXT:    .long 44 @ double 9.3367814824704935E-313
131; CHECK-BE-NEXT:    .long 45
132   ret < 4 x i32> < i32 42, i32 43, i32 44, i32 45 >
133}
134
135define <2 x double> @return_v2f64() {
136; CHECK-LE-LABEL: return_v2f64:
137; CHECK-LE:       @ %bb.0:
138; CHECK-LE-NEXT:    vldr d16, .LCPI7_0
139; CHECK-LE-NEXT:    vldr d17, .LCPI7_1
140; CHECK-LE-NEXT:    vmov r0, r1, d16
141; CHECK-LE-NEXT:    vmov r2, r3, d17
142; CHECK-LE-NEXT:    bx lr
143; CHECK-LE-NEXT:    .p2align 3
144; CHECK-LE-NEXT:  @ %bb.1:
145; CHECK-LE-NEXT:  .LCPI7_0:
146; CHECK-LE-NEXT:    .long 1374389535 @ double 3.1400000000000001
147; CHECK-LE-NEXT:    .long 1074339512
148; CHECK-LE-NEXT:  .LCPI7_1:
149; CHECK-LE-NEXT:    .long 1374389535 @ double 6.2800000000000002
150; CHECK-LE-NEXT:    .long 1075388088
151;
152; CHECK-BE-LABEL: return_v2f64:
153; CHECK-BE:       @ %bb.0:
154; CHECK-BE-NEXT:    vldr d16, .LCPI7_0
155; CHECK-BE-NEXT:    vldr d17, .LCPI7_1
156; CHECK-BE-NEXT:    vmov r1, r0, d16
157; CHECK-BE-NEXT:    vmov r3, r2, d17
158; CHECK-BE-NEXT:    bx lr
159; CHECK-BE-NEXT:    .p2align 3
160; CHECK-BE-NEXT:  @ %bb.1:
161; CHECK-BE-NEXT:  .LCPI7_0:
162; CHECK-BE-NEXT:    .long 1074339512 @ double 3.1400000000000001
163; CHECK-BE-NEXT:    .long 1374389535
164; CHECK-BE-NEXT:  .LCPI7_1:
165; CHECK-BE-NEXT:    .long 1075388088 @ double 6.2800000000000002
166; CHECK-BE-NEXT:    .long 1374389535
167   ret <2 x double> < double 3.14, double 6.28 >
168}
169
170define void @caller_arg_longint() {
171; CHECK-LE-LABEL: caller_arg_longint:
172; CHECK-LE:       @ %bb.0:
173; CHECK-LE-NEXT:    .save {r11, lr}
174; CHECK-LE-NEXT:    push {r11, lr}
175; CHECK-LE-NEXT:    mov r0, #42
176; CHECK-LE-NEXT:    mov r1, #0
177; CHECK-LE-NEXT:    bl arg_longint
178; CHECK-LE-NEXT:    pop {r11, pc}
179;
180; CHECK-BE-LABEL: caller_arg_longint:
181; CHECK-BE:       @ %bb.0:
182; CHECK-BE-NEXT:    .save {r11, lr}
183; CHECK-BE-NEXT:    push {r11, lr}
184; CHECK-BE-NEXT:    mov r0, #0
185; CHECK-BE-NEXT:    mov r1, #42
186; CHECK-BE-NEXT:    bl arg_longint
187; CHECK-BE-NEXT:    pop {r11, pc}
188   call void @arg_longint( i64 42 )
189   ret void
190}
191
192define void @caller_arg_double() {
193; CHECK-LE-LABEL: caller_arg_double:
194; CHECK-LE:       @ %bb.0:
195; CHECK-LE-NEXT:    .save {r11, lr}
196; CHECK-LE-NEXT:    push {r11, lr}
197; CHECK-LE-NEXT:    vmov.f64 d16, #1.000000e+00
198; CHECK-LE-NEXT:    vmov r0, r1, d16
199; CHECK-LE-NEXT:    bl arg_double
200; CHECK-LE-NEXT:    pop {r11, pc}
201;
202; CHECK-BE-LABEL: caller_arg_double:
203; CHECK-BE:       @ %bb.0:
204; CHECK-BE-NEXT:    .save {r11, lr}
205; CHECK-BE-NEXT:    push {r11, lr}
206; CHECK-BE-NEXT:    vmov.f64 d16, #1.000000e+00
207; CHECK-BE-NEXT:    vmov r1, r0, d16
208; CHECK-BE-NEXT:    bl arg_double
209; CHECK-BE-NEXT:    pop {r11, pc}
210   call void @arg_double( double 1.0 )
211   ret void
212}
213
214define void @caller_return_longint() {
215; CHECK-LE-LABEL: caller_return_longint:
216; CHECK-LE:       @ %bb.0:
217; CHECK-LE-NEXT:    .save {r11, lr}
218; CHECK-LE-NEXT:    push {r11, lr}
219; CHECK-LE-NEXT:    bl return_longint
220; CHECK-LE-NEXT:    movw r1, :lower16:var32
221; CHECK-LE-NEXT:    movt r1, :upper16:var32
222; CHECK-LE-NEXT:    str r0, [r1]
223; CHECK-LE-NEXT:    pop {r11, pc}
224;
225; CHECK-BE-LABEL: caller_return_longint:
226; CHECK-BE:       @ %bb.0:
227; CHECK-BE-NEXT:    .save {r11, lr}
228; CHECK-BE-NEXT:    push {r11, lr}
229; CHECK-BE-NEXT:    bl return_longint
230; CHECK-BE-NEXT:    movw r0, :lower16:var32
231; CHECK-BE-NEXT:    movt r0, :upper16:var32
232; CHECK-BE-NEXT:    str r1, [r0]
233; CHECK-BE-NEXT:    pop {r11, pc}
234   %val = call i64 @return_longint()
235   %tmp = trunc i64 %val to i32
236   store i32 %tmp, i32* @var32
237   ret void
238}
239
240define void @caller_return_double() {
241; CHECK-LE-LABEL: caller_return_double:
242; CHECK-LE:       @ %bb.0:
243; CHECK-LE-NEXT:    .save {r11, lr}
244; CHECK-LE-NEXT:    push {r11, lr}
245; CHECK-LE-NEXT:    bl return_double
246; CHECK-LE-NEXT:    vmov d17, r0, r1
247; CHECK-LE-NEXT:    vldr d16, .LCPI11_0
248; CHECK-LE-NEXT:    movw r0, :lower16:vardouble
249; CHECK-LE-NEXT:    vadd.f64 d16, d17, d16
250; CHECK-LE-NEXT:    movt r0, :upper16:vardouble
251; CHECK-LE-NEXT:    vstr d16, [r0]
252; CHECK-LE-NEXT:    pop {r11, pc}
253; CHECK-LE-NEXT:    .p2align 3
254; CHECK-LE-NEXT:  @ %bb.1:
255; CHECK-LE-NEXT:  .LCPI11_0:
256; CHECK-LE-NEXT:    .long 1374389535 @ double 3.1400000000000001
257; CHECK-LE-NEXT:    .long 1074339512
258;
259; CHECK-BE-LABEL: caller_return_double:
260; CHECK-BE:       @ %bb.0:
261; CHECK-BE-NEXT:    .save {r11, lr}
262; CHECK-BE-NEXT:    push {r11, lr}
263; CHECK-BE-NEXT:    bl return_double
264; CHECK-BE-NEXT:    vmov d17, r1, r0
265; CHECK-BE-NEXT:    vldr d16, .LCPI11_0
266; CHECK-BE-NEXT:    movw r0, :lower16:vardouble
267; CHECK-BE-NEXT:    vadd.f64 d16, d17, d16
268; CHECK-BE-NEXT:    movt r0, :upper16:vardouble
269; CHECK-BE-NEXT:    vstr d16, [r0]
270; CHECK-BE-NEXT:    pop {r11, pc}
271; CHECK-BE-NEXT:    .p2align 3
272; CHECK-BE-NEXT:  @ %bb.1:
273; CHECK-BE-NEXT:  .LCPI11_0:
274; CHECK-BE-NEXT:    .long 1074339512 @ double 3.1400000000000001
275; CHECK-BE-NEXT:    .long 1374389535
276  %val = call double @return_double( )
277  %tmp = fadd double %val, 3.14
278  store double  %tmp, double* @vardouble
279  ret void
280}
281
282define void @caller_return_v2f64() {
283; CHECK-LABEL: caller_return_v2f64:
284; CHECK:       @ %bb.0:
285; CHECK-NEXT:    .save {r11, lr}
286; CHECK-NEXT:    push {r11, lr}
287; CHECK-NEXT:    bl return_v2f64
288; CHECK-NEXT:    movw r2, :lower16:vardouble
289; CHECK-NEXT:    movt r2, :upper16:vardouble
290; CHECK-NEXT:    strd r0, r1, [r2]
291; CHECK-NEXT:    pop {r11, pc}
292   %val = call <2 x double> @return_v2f64( )
293   %tmp = extractelement <2 x double> %val, i32 0
294    store double %tmp, double* @vardouble
295    ret void
296}
297