xref: /llvm-project/llvm/test/CodeGen/ARM/GlobalISel/arm-param-lowering.ll (revision 05d17a1c705e1053f95b90aa37d91ce4f94a9287)
1; RUN: llc -O0 -mtriple arm-unknown -mattr=+vfp2,+v4t -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ARM -check-prefix=LITTLE
2; RUN: llc -O0 -mtriple armeb-unknown -mattr=+vfp2,+v4t -global-isel -global-isel-abort=0 -enable-arm-gisel-bigendian -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=ARM -check-prefix=BIG
3; RUN: llc -O0 -mtriple thumb-unknown -mattr=+vfp2,+v6t2 -global-isel -stop-after=irtranslator -verify-machineinstrs %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LITTLE -check-prefix=THUMB
4
5declare arm_aapcscc ptr @simple_reg_params_target(i32, ptr)
6
7define arm_aapcscc ptr @test_call_simple_reg_params(ptr %a, i32 %b) {
8; CHECK-LABEL: name: test_call_simple_reg_params
9; CHECK-DAG: [[AVREG:%[0-9]+]]:_(p0) = COPY $r0
10; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r1
11; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
12; CHECK-DAG: $r0 = COPY [[BVREG]]
13; CHECK-DAG: $r1 = COPY [[AVREG]]
14; ARM: BL @simple_reg_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0
15; THUMB: tBL 14 /* CC::al */, $noreg, @simple_reg_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0
16; CHECK: [[RVREG:%[0-9]+]]:_(p0) = COPY $r0
17; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
18; CHECK: $r0 = COPY [[RVREG]]
19; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0
20; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
21entry:
22  %r = notail call arm_aapcscc ptr @simple_reg_params_target(i32 %b, ptr %a)
23  ret ptr %r
24}
25
26declare arm_aapcscc ptr @simple_stack_params_target(i32, ptr, i32, ptr, i32, ptr)
27
28define arm_aapcscc ptr @test_call_simple_stack_params(ptr %a, i32 %b) {
29; CHECK-LABEL: name: test_call_simple_stack_params
30; CHECK-DAG: [[AVREG:%[0-9]+]]:_(p0) = COPY $r0
31; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r1
32; CHECK: ADJCALLSTACKDOWN 8, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
33; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
34; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
35; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32)
36; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0){{.*}}store (s32)
37; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp
38; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
39; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32)
40; CHECK: G_STORE [[AVREG]](p0), [[FI2]](p0){{.*}}store (p0)
41; CHECK-DAG: $r0 = COPY [[BVREG]]
42; CHECK-DAG: $r1 = COPY [[AVREG]]
43; CHECK-DAG: $r2 = COPY [[BVREG]]
44; CHECK-DAG: $r3 = COPY [[AVREG]]
45; ARM: BL @simple_stack_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
46; THUMB: tBL 14 /* CC::al */, $noreg, @simple_stack_params_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
47; CHECK: [[RVREG:%[0-9]+]]:_(p0) = COPY $r0
48; CHECK: ADJCALLSTACKUP 8, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
49; CHECK: $r0 = COPY [[RVREG]]
50; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0
51; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
52entry:
53  %r = notail call arm_aapcscc ptr @simple_stack_params_target(i32 %b, ptr %a, i32 %b, ptr %a, i32 %b, ptr %a)
54  ret ptr %r
55}
56
57declare arm_aapcscc signext i16 @ext_target(i8 signext, i8 zeroext, i16 signext, i16 zeroext, i8 signext, i8 zeroext, i16 signext, i16 zeroext, i1 zeroext)
58
59define arm_aapcscc signext i16 @test_call_ext_params(i8 %a, i16 %b, i1 %c) {
60; CHECK-LABEL: name: test_call_ext_params
61; CHECK-DAG: [[R0VREG:%[0-9]+]]:_(s32) = COPY $r0
62; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s8) = G_TRUNC [[R0VREG]]
63; CHECK-DAG: [[R1VREG:%[0-9]+]]:_(s32) = COPY $r1
64; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s16) = G_TRUNC [[R1VREG]]
65; CHECK-DAG: [[R2VREG:%[0-9]+]]:_(s32) = COPY $r2
66; CHECK-DAG: [[CVREG:%[0-9]+]]:_(s1) = G_TRUNC [[R2VREG]]
67; CHECK: ADJCALLSTACKDOWN 20, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
68; CHECK: [[SEXTA:%[0-9]+]]:_(s32) = G_SEXT [[AVREG]](s8)
69; CHECK: [[ZEXTA:%[0-9]+]]:_(s32) = G_ZEXT [[AVREG]](s8)
70; CHECK: [[SEXTB:%[0-9]+]]:_(s32) = G_SEXT [[BVREG]](s16)
71; CHECK: [[ZEXTB:%[0-9]+]]:_(s32) = G_ZEXT [[BVREG]](s16)
72; CHECK: [[SEXTA2:%[0-9]+]]:_(s32) = G_SEXT [[AVREG]]
73; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
74; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
75; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32)
76; CHECK: G_STORE [[SEXTA2]](s32), [[FI1]](p0){{.*}}store (s32)
77; CHECK: [[ZEXTA2:%[0-9]+]]:_(s32) = G_ZEXT [[AVREG]]
78; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp
79; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
80; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32)
81; CHECK: G_STORE [[ZEXTA2]](s32), [[FI2]](p0){{.*}}store (s32)
82; CHECK: [[SEXTB2:%[0-9]+]]:_(s32) = G_SEXT [[BVREG]]
83; CHECK: [[SP3:%[0-9]+]]:_(p0) = COPY $sp
84; CHECK: [[OFF3:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
85; CHECK: [[FI3:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP3]], [[OFF3]](s32)
86; CHECK: G_STORE [[SEXTB2]](s32), [[FI3]](p0){{.*}}store (s32)
87; CHECK: [[ZEXTB2:%[0-9]+]]:_(s32) = G_ZEXT [[BVREG]]
88; CHECK: [[SP4:%[0-9]+]]:_(p0) = COPY $sp
89; CHECK: [[OFF4:%[0-9]+]]:_(s32) = G_CONSTANT i32 12
90; CHECK: [[FI4:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP4]], [[OFF4]](s32)
91; CHECK: G_STORE [[ZEXTB2]](s32), [[FI4]](p0){{.*}}store (s32)
92; CHECK: [[ZEXTC:%[0-9]+]]:_(s32) = G_ZEXT [[CVREG]]
93; CHECK: [[SP5:%[0-9]+]]:_(p0) = COPY $sp
94; CHECK: [[OFF5:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
95; CHECK: [[FI5:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP5]], [[OFF5]](s32)
96; CHECK: G_STORE [[ZEXTC]](s32), [[FI5]](p0){{.*}}store (s32)
97; CHECK: $r0 = COPY [[SEXTA]]
98; CHECK: $r1 = COPY [[ZEXTA]]
99; CHECK: $r2 = COPY [[SEXTB]]
100; CHECK: $r3 = COPY [[ZEXTB]]
101; ARM: BL @ext_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
102; THUMB: tBL 14 /* CC::al */, $noreg, @ext_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0
103; CHECK: [[R0VREG:%[0-9]+]]:_(s32) = COPY $r0
104; CHECK: [[R0VREG_ASSERT:%[0-9]+]]:_(s32) = G_ASSERT_SEXT [[R0VREG]], 16
105; CHECK: [[RVREG:%[0-9]+]]:_(s16) = G_TRUNC [[R0VREG_ASSERT]]
106; CHECK: ADJCALLSTACKUP 20, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
107; CHECK: [[RExtVREG:%[0-9]+]]:_(s32) = G_SEXT [[RVREG]]
108; CHECK: $r0 = COPY [[RExtVREG]]
109; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0
110; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0
111entry:
112  %r = notail call arm_aapcscc signext i16 @ext_target(i8 signext %a, i8 zeroext %a, i16 signext %b, i16 zeroext %b, i8 signext %a, i8 zeroext %a, i16 signext %b, i16 zeroext %b, i1 zeroext %c)
113  ret i16 %r
114}
115
116declare arm_aapcs_vfpcc double @vfpcc_fp_target(float, double)
117
118define arm_aapcs_vfpcc double @test_call_vfpcc_fp_params(double %a, float %b) {
119; CHECK-LABEL: name: test_call_vfpcc_fp_params
120; CHECK-DAG: [[AVREG:%[0-9]+]]:_(s64) = COPY $d0
121; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $s2
122; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
123; CHECK-DAG: $s0 = COPY [[BVREG]]
124; CHECK-DAG: $d1 = COPY [[AVREG]]
125; ARM: BL @vfpcc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $s0, implicit $d1, implicit-def $d0
126; THUMB: tBL 14 /* CC::al */, $noreg, @vfpcc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $s0, implicit $d1, implicit-def $d0
127; CHECK: [[RVREG:%[0-9]+]]:_(s64) = COPY $d0
128; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
129; CHECK: $d0 = COPY [[RVREG]]
130; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $d0
131; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $d0
132entry:
133  %r = notail call arm_aapcs_vfpcc double @vfpcc_fp_target(float %b, double %a)
134  ret double %r
135}
136
137declare arm_aapcscc double @aapcscc_fp_target(float, double, float, double)
138
139define arm_aapcscc double @test_call_aapcs_fp_params(double %a, float %b) {
140; CHECK-LABEL: name: test_call_aapcs_fp_params
141; CHECK-DAG: [[A1:%[0-9]+]]:_(s32) = COPY $r0
142; CHECK-DAG: [[A2:%[0-9]+]]:_(s32) = COPY $r1
143; LITTLE-DAG: [[AVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[A1]](s32), [[A2]](s32)
144; BIG-DAG: [[AVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[A2]](s32), [[A1]](s32)
145; CHECK-DAG: [[BVREG:%[0-9]+]]:_(s32) = COPY $r2
146; CHECK: ADJCALLSTACKDOWN 16, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
147; CHECK-DAG: [[A1:%[0-9]+]]:_(s32), [[A2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[AVREG]](s64)
148; CHECK: [[SP1:%[0-9]+]]:_(p0) = COPY $sp
149; CHECK: [[OFF1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
150; CHECK: [[FI1:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP1]], [[OFF1]](s32)
151; CHECK: G_STORE [[BVREG]](s32), [[FI1]](p0){{.*}}store (s32)
152; CHECK: [[SP2:%[0-9]+]]:_(p0) = COPY $sp
153; CHECK: [[OFF2:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
154; CHECK: [[FI2:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP2]], [[OFF2]](s32)
155; CHECK: G_STORE [[AVREG]](s64), [[FI2]](p0){{.*}}store (s64)
156; CHECK-DAG: $r0 = COPY [[BVREG]]
157; LITTLE-DAG: $r2 = COPY [[A1]]
158; LITTLE-DAG: $r3 = COPY [[A2]]
159; BIG-DAG: $r2 = COPY [[A2]]
160; BIG-DAG: $r3 = COPY [[A1]]
161; ARM: BL @aapcscc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
162; THUMB: tBL 14 /* CC::al */, $noreg, @aapcscc_fp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
163; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r0
164; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r1
165; LITTLE: [[RVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R1]](s32), [[R2]](s32)
166; BIG: [[RVREG:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[R2]](s32), [[R1]](s32)
167; CHECK: ADJCALLSTACKUP 16, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
168; CHECK: [[R1:%[0-9]+]]:_(s32), [[R2:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[RVREG]](s64)
169; LITTLE-DAG: $r0 = COPY [[R1]]
170; LITTLE-DAG: $r1 = COPY [[R2]]
171; BIG-DAG: $r0 = COPY [[R2]]
172; BIG-DAG: $r1 = COPY [[R1]]
173; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
174; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
175entry:
176  %r = notail call arm_aapcscc double @aapcscc_fp_target(float %b, double %a, float %b, double %a)
177  ret double %r
178}
179
180declare arm_aapcscc float @different_call_conv_target(float)
181
182define arm_aapcs_vfpcc float @test_call_different_call_conv(float %x) {
183; CHECK-LABEL: name: test_call_different_call_conv
184; CHECK: [[X:%[0-9]+]]:_(s32) = COPY $s0
185; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
186; CHECK: $r0 = COPY [[X]]
187; ARM: BL @different_call_conv_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit-def $r0
188; THUMB: tBL 14 /* CC::al */, $noreg, @different_call_conv_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit-def $r0
189; CHECK: [[R:%[0-9]+]]:_(s32) = COPY $r0
190; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
191; CHECK: $s0 = COPY [[R]]
192; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $s0
193; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $s0
194entry:
195  %r = notail call arm_aapcscc float @different_call_conv_target(float %x)
196  ret float %r
197}
198
199declare arm_aapcscc [3 x i32] @tiny_int_arrays_target([2 x i32])
200
201define arm_aapcscc [3 x i32] @test_tiny_int_arrays([2 x i32] %arr) {
202; CHECK-LABEL: name: test_tiny_int_arrays
203; CHECK: liveins: $r0, $r1
204; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
205; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
206; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
207; CHECK: $r0 = COPY [[R0]]
208; CHECK: $r1 = COPY [[R1]]
209; ARM: BL @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
210; THUMB: tBL 14 /* CC::al */, $noreg, @tiny_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
211; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
212; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
213; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2
214; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
215; FIXME: This doesn't seem correct with regard to the AAPCS docs (which say
216; that composite types larger than 4 bytes should be passed through memory),
217; but it's what DAGISel does. We should fix it in the common code for both.
218; CHECK: $r0 = COPY [[R0]]
219; CHECK: $r1 = COPY [[R1]]
220; CHECK: $r2 = COPY [[R2]]
221; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1, implicit $r2
222; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1, implicit $r2
223entry:
224  %r = notail call arm_aapcscc [3 x i32] @tiny_int_arrays_target([2 x i32] %arr)
225  ret [3 x i32] %r
226}
227
228declare arm_aapcscc void @multiple_int_arrays_target([2 x i32], [2 x i32])
229
230define arm_aapcscc void @test_multiple_int_arrays([2 x i32] %arr0, [2 x i32] %arr1) {
231; CHECK-LABEL: name: test_multiple_int_arrays
232; CHECK: liveins: $r0, $r1
233; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
234; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
235; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $r2
236; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $r3
237; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
238; CHECK: $r0 = COPY [[R0]]
239; CHECK: $r1 = COPY [[R1]]
240; CHECK: $r2 = COPY [[R2]]
241; CHECK: $r3 = COPY [[R3]]
242; ARM: BL @multiple_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3
243; THUMB: tBL 14 /* CC::al */, $noreg, @multiple_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3
244; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
245; ARM: BX_RET 14 /* CC::al */, $noreg
246; THUMB: tBX_RET 14 /* CC::al */, $noreg
247entry:
248  notail call arm_aapcscc void @multiple_int_arrays_target([2 x i32] %arr0, [2 x i32] %arr1)
249  ret void
250}
251
252declare arm_aapcscc void @large_int_arrays_target([20 x i32])
253
254define arm_aapcscc void @test_large_int_arrays([20 x i32] %arr) {
255; CHECK-LABEL: name: test_large_int_arrays
256; CHECK: fixedStack:
257; The parameters live in separate stack locations, one for each element that
258; doesn't fit in the registers.
259; CHECK-DAG: id: [[FIRST_STACK_ID:[0-9]+]], type: default, offset: 0, size: 4,
260; CHECK-DAG: id: [[LAST_STACK_ID:[-0]+]], type: default, offset: 60, size: 4
261; CHECK: liveins: $r0, $r1, $r2, $r3
262; CHECK-DAG: [[R0:%[0-9]+]]:_(s32) = COPY $r0
263; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r1
264; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r2
265; CHECK-DAG: [[R3:%[0-9]+]]:_(s32) = COPY $r3
266; CHECK: [[FIRST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[FIRST_STACK_ID]]
267; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[FIRST_STACK_ID]]
268; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
269; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[LAST_STACK_ID]]
270; CHECK: ADJCALLSTACKDOWN 64, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
271; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
272; CHECK: [[OFF_FIRST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
273; CHECK: [[FIRST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_FIRST_ELEMENT]](s32)
274; CHECK: G_STORE [[FIRST_STACK_ELEMENT]](s32), [[FIRST_STACK_ARG_ADDR]]{{.*}}store (s32)
275; Match the second-to-last offset, so we can get the correct SP for the last element
276; CHECK: G_CONSTANT i32 56
277; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
278; CHECK: [[OFF_LAST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 60
279; CHECK: [[LAST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_LAST_ELEMENT]](s32)
280; CHECK: G_STORE [[LAST_STACK_ELEMENT]](s32), [[LAST_STACK_ARG_ADDR]]{{.*}}store (s32)
281; CHECK: $r0 = COPY [[R0]]
282; CHECK: $r1 = COPY [[R1]]
283; CHECK: $r2 = COPY [[R2]]
284; CHECK: $r3 = COPY [[R3]]
285; ARM: BL @large_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3
286; THUMB: tBL 14 /* CC::al */, $noreg, @large_int_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3
287; CHECK: ADJCALLSTACKUP 64, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
288; ARM: BX_RET 14 /* CC::al */, $noreg
289; THUMB: tBX_RET 14 /* CC::al */, $noreg
290entry:
291  notail call arm_aapcscc void @large_int_arrays_target([20 x i32] %arr)
292  ret void
293}
294
295declare arm_aapcscc [2 x float] @fp_arrays_aapcs_target([3 x double])
296
297define arm_aapcscc [2 x float] @test_fp_arrays_aapcs([3 x double] %arr) {
298; CHECK-LABEL: name: test_fp_arrays_aapcs
299; CHECK: fixedStack:
300; CHECK: id: [[ARR2_ID:[0-9]+]], type: default, offset: 0, size: 8,
301; CHECK: liveins: $r0, $r1, $r2, $r3
302; CHECK: [[ARR0_0:%[0-9]+]]:_(s32) = COPY $r0
303; CHECK: [[ARR0_1:%[0-9]+]]:_(s32) = COPY $r1
304; LITTLE: [[ARR0:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR0_0]](s32), [[ARR0_1]](s32)
305; BIG: [[ARR0:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR0_1]](s32), [[ARR0_0]](s32)
306; CHECK: [[ARR1_0:%[0-9]+]]:_(s32) = COPY $r2
307; CHECK: [[ARR1_1:%[0-9]+]]:_(s32) = COPY $r3
308; LITTLE: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_0]](s32), [[ARR1_1]](s32)
309; BIG: [[ARR1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[ARR1_1]](s32), [[ARR1_0]](s32)
310; CHECK: [[ARR2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[ARR2_ID]]
311; CHECK: [[ARR2:%[0-9]+]]:_(s64) = G_LOAD [[ARR2_FI]]{{.*}}load (s64) from %fixed-stack.[[ARR2_ID]]
312; CHECK: ADJCALLSTACKDOWN 8, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
313; CHECK: [[ARR0_0:%[0-9]+]]:_(s32), [[ARR0_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR0]](s64)
314; CHECK: [[ARR1_0:%[0-9]+]]:_(s32), [[ARR1_1:%[0-9]+]]:_(s32) = G_UNMERGE_VALUES [[ARR1]](s64)
315; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
316; CHECK: [[ARR2_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
317; CHECK: [[ARR2_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[ARR2_OFFSET]](s32)
318; CHECK: G_STORE [[ARR2]](s64), [[ARR2_ADDR]](p0){{.*}}store (s64)
319; LITTLE: $r0 = COPY [[ARR0_0]](s32)
320; LITTLE: $r1 = COPY [[ARR0_1]](s32)
321; BIG: $r0 = COPY [[ARR0_1]](s32)
322; BIG: $r1 = COPY [[ARR0_0]](s32)
323; LITTLE: $r2 = COPY [[ARR1_0]](s32)
324; LITTLE: $r3 = COPY [[ARR1_1]](s32)
325; BIG: $r2 = COPY [[ARR1_1]](s32)
326; BIG: $r3 = COPY [[ARR1_0]](s32)
327; ARM: BL @fp_arrays_aapcs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
328; THUMB: tBL 14 /* CC::al */, $noreg, @fp_arrays_aapcs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
329; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
330; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
331; CHECK: ADJCALLSTACKUP 8, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
332; CHECK: $r0 = COPY [[R0]]
333; CHECK: $r1 = COPY [[R1]]
334; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
335; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
336entry:
337  %r = notail call arm_aapcscc [2 x float] @fp_arrays_aapcs_target([3 x double] %arr)
338  ret [2 x float] %r
339}
340
341declare arm_aapcs_vfpcc [4 x float] @fp_arrays_aapcs_vfp_target([3 x double], [3 x float], [4 x double])
342
343define arm_aapcs_vfpcc [4 x float] @test_fp_arrays_aapcs_vfp([3 x double] %x, [3 x float] %y, [4 x double] %z) {
344; CHECK-LABEL: name: test_fp_arrays_aapcs_vfp
345; CHECK: fixedStack:
346; CHECK-DAG: id: [[Z0_ID:[0-9]+]], type: default, offset: 0, size: 8,
347; CHECK-DAG: id: [[Z1_ID:[0-9]+]], type: default, offset: 8, size: 8,
348; CHECK-DAG: id: [[Z2_ID:[0-9]+]], type: default, offset: 16, size: 8,
349; CHECK-DAG: id: [[Z3_ID:[0-9]+]], type: default, offset: 24, size: 8,
350; CHECK: liveins: $d0, $d1, $d2, $s6, $s7, $s8
351; CHECK: [[X0:%[0-9]+]]:_(s64) = COPY $d0
352; CHECK: [[X1:%[0-9]+]]:_(s64) = COPY $d1
353; CHECK: [[X2:%[0-9]+]]:_(s64) = COPY $d2
354; CHECK: [[Y0:%[0-9]+]]:_(s32) = COPY $s6
355; CHECK: [[Y1:%[0-9]+]]:_(s32) = COPY $s7
356; CHECK: [[Y2:%[0-9]+]]:_(s32) = COPY $s8
357; CHECK: [[Z0_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z0_ID]]
358; CHECK: [[Z0:%[0-9]+]]:_(s64) = G_LOAD [[Z0_FI]]{{.*}}load (s64)
359; CHECK: [[Z1_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z1_ID]]
360; CHECK: [[Z1:%[0-9]+]]:_(s64) = G_LOAD [[Z1_FI]]{{.*}}load (s64)
361; CHECK: [[Z2_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z2_ID]]
362; CHECK: [[Z2:%[0-9]+]]:_(s64) = G_LOAD [[Z2_FI]]{{.*}}load (s64)
363; CHECK: [[Z3_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[Z3_ID]]
364; CHECK: [[Z3:%[0-9]+]]:_(s64) = G_LOAD [[Z3_FI]]{{.*}}load (s64)
365; CHECK: ADJCALLSTACKDOWN 32, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
366; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
367; CHECK: [[Z0_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
368; CHECK: [[Z0_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z0_OFFSET]](s32)
369; CHECK: G_STORE [[Z0]](s64), [[Z0_ADDR]](p0){{.*}}store (s64)
370; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
371; CHECK: [[Z1_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
372; CHECK: [[Z1_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z1_OFFSET]](s32)
373; CHECK: G_STORE [[Z1]](s64), [[Z1_ADDR]](p0){{.*}}store (s64)
374; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
375; CHECK: [[Z2_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
376; CHECK: [[Z2_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z2_OFFSET]](s32)
377; CHECK: G_STORE [[Z2]](s64), [[Z2_ADDR]](p0){{.*}}store (s64)
378; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
379; CHECK: [[Z3_OFFSET:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
380; CHECK: [[Z3_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[Z3_OFFSET]](s32)
381; CHECK: G_STORE [[Z3]](s64), [[Z3_ADDR]](p0){{.*}}store (s64)
382; CHECK: $d0 = COPY [[X0]](s64)
383; CHECK: $d1 = COPY [[X1]](s64)
384; CHECK: $d2 = COPY [[X2]](s64)
385; CHECK: $s6 = COPY [[Y0]](s32)
386; CHECK: $s7 = COPY [[Y1]](s32)
387; CHECK: $s8 = COPY [[Y2]](s32)
388; ARM: BL @fp_arrays_aapcs_vfp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $d0, implicit $d1, implicit $d2, implicit $s6, implicit $s7, implicit $s8, implicit-def $s0, implicit-def $s1, implicit-def $s2, implicit-def $s3
389; THUMB: tBL 14 /* CC::al */, $noreg, @fp_arrays_aapcs_vfp_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $d0, implicit $d1, implicit $d2, implicit $s6, implicit $s7, implicit $s8, implicit-def $s0, implicit-def $s1, implicit-def $s2, implicit-def $s3
390; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $s0
391; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $s1
392; CHECK: [[R2:%[0-9]+]]:_(s32) = COPY $s2
393; CHECK: [[R3:%[0-9]+]]:_(s32) = COPY $s3
394; CHECK: ADJCALLSTACKUP 32, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
395; CHECK: $s0 = COPY [[R0]]
396; CHECK: $s1 = COPY [[R1]]
397; CHECK: $s2 = COPY [[R2]]
398; CHECK: $s3 = COPY [[R3]]
399; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3
400; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $s0, implicit $s1, implicit $s2, implicit $s3
401entry:
402  %r = notail call arm_aapcs_vfpcc [4 x float] @fp_arrays_aapcs_vfp_target([3 x double] %x, [3 x float] %y, [4 x double] %z)
403  ret [4 x float] %r
404}
405
406declare arm_aapcscc [2 x ptr] @tough_arrays_target([6 x [4 x i32]] %arr)
407
408define arm_aapcscc [2 x ptr] @test_tough_arrays([6 x [4 x i32]] %arr) {
409; CHECK-LABEL: name: test_tough_arrays
410; CHECK: fixedStack:
411; The parameters live in separate stack locations, one for each element that
412; doesn't fit in the registers.
413; CHECK-DAG: id: [[FIRST_STACK_ID:[0-9]+]], type: default, offset: 0, size: 4,
414; CHECK-DAG: id: [[LAST_STACK_ID:[-0]+]], type: default, offset: 76, size: 4
415; CHECK: liveins: $r0, $r1, $r2, $r3
416; CHECK-DAG: [[R0:%[0-9]+]]:_(s32) = COPY $r0
417; CHECK-DAG: [[R1:%[0-9]+]]:_(s32) = COPY $r1
418; CHECK-DAG: [[R2:%[0-9]+]]:_(s32) = COPY $r2
419; CHECK-DAG: [[R3:%[0-9]+]]:_(s32) = COPY $r3
420; CHECK: [[FIRST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[FIRST_STACK_ID]]
421; CHECK: [[FIRST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[FIRST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[FIRST_STACK_ID]]
422; CHECK: [[LAST_STACK_ELEMENT_FI:%[0-9]+]]:_(p0) = G_FRAME_INDEX %fixed-stack.[[LAST_STACK_ID]]
423; CHECK: [[LAST_STACK_ELEMENT:%[0-9]+]]:_(s32) = G_LOAD [[LAST_STACK_ELEMENT_FI]]{{.*}}load (s32) from %fixed-stack.[[LAST_STACK_ID]]
424; CHECK: ADJCALLSTACKDOWN 80, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
425; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
426; CHECK: [[OFF_FIRST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
427; CHECK: [[FIRST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_FIRST_ELEMENT]](s32)
428; CHECK: G_STORE [[FIRST_STACK_ELEMENT]](s32), [[FIRST_STACK_ARG_ADDR]]{{.*}}store (s32)
429; Match the second-to-last offset, so we can get the correct SP for the last element
430; CHECK: G_CONSTANT i32 72
431; CHECK: [[SP:%[0-9]+]]:_(p0) = COPY $sp
432; CHECK: [[OFF_LAST_ELEMENT:%[0-9]+]]:_(s32) = G_CONSTANT i32 76
433; CHECK: [[LAST_STACK_ARG_ADDR:%[0-9]+]]:_(p0) = G_PTR_ADD [[SP]], [[OFF_LAST_ELEMENT]](s32)
434; CHECK: G_STORE [[LAST_STACK_ELEMENT]](s32), [[LAST_STACK_ARG_ADDR]]{{.*}}store (s32)
435; CHECK: $r0 = COPY [[R0]]
436; CHECK: $r1 = COPY [[R1]]
437; CHECK: $r2 = COPY [[R2]]
438; CHECK: $r3 = COPY [[R3]]
439; ARM: BL @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
440; THUMB: tBL 14 /* CC::al */, $noreg, @tough_arrays_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit $r2, implicit $r3, implicit-def $r0, implicit-def $r1
441; CHECK: [[R0:%[0-9]+]]:_(p0) = COPY $r0
442; CHECK: [[R1:%[0-9]+]]:_(p0) = COPY $r1
443; CHECK: ADJCALLSTACKUP 80, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
444; CHECK: $r0 = COPY [[R0]]
445; CHECK: $r1 = COPY [[R1]]
446; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
447; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
448entry:
449  %r = notail call arm_aapcscc [2 x ptr] @tough_arrays_target([6 x [4 x i32]] %arr)
450  ret [2 x ptr] %r
451}
452
453declare arm_aapcscc {i32, i32} @structs_target({i32, i32})
454
455define arm_aapcscc {i32, i32} @test_structs({i32, i32} %x) {
456; CHECK-LABEL: test_structs
457; CHECK: liveins: $r0, $r1
458; CHECK-DAG: [[X0:%[0-9]+]]:_(s32) = COPY $r0
459; CHECK-DAG: [[X1:%[0-9]+]]:_(s32) = COPY $r1
460; CHECK: ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
461; CHECK-DAG: $r0 = COPY [[X0]](s32)
462; CHECK-DAG: $r1 = COPY [[X1]](s32)
463; ARM: BL @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
464; THUMB: tBL 14 /* CC::al */, $noreg, @structs_target, csr_aapcs, implicit-def $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $r0, implicit-def $r1
465; CHECK: [[R0:%[0-9]+]]:_(s32) = COPY $r0
466; CHECK: [[R1:%[0-9]+]]:_(s32) = COPY $r1
467; CHECK: ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def $sp, implicit $sp
468; CHECK: $r0 = COPY [[R0]](s32)
469; CHECK: $r1 = COPY [[R1]](s32)
470; ARM: BX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
471; THUMB: tBX_RET 14 /* CC::al */, $noreg, implicit $r0, implicit $r1
472  %r = notail call arm_aapcscc {i32, i32} @structs_target({i32, i32} %x)
473  ret {i32, i32} %r
474}
475