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