xref: /llvm-project/llvm/test/CodeGen/AArch64/arm64-abi.ll (revision 5ddce70ef0e5a641d7fea95e31fc5e2439cb98cb)
1; RUN: llc     -mtriple=arm64-apple-darwin -mcpu=cyclone -enable-misched=false < %s | FileCheck %s
2; RUN: llc -O0 -fast-isel -mtriple=arm64-apple-darwin                          < %s | FileCheck --check-prefix=FAST %s
3; RUN: llc -global-isel -mtriple=arm64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=GISEL
4
5; rdar://9932559
6define i64 @i8i16callee(i64 %a1, i64 %a2, i64 %a3, i8 signext %a4, i16 signext %a5, i64 %a6, i64 %a7, i64 %a8, i8 signext %b1, i16 signext %b2, i8 signext %b3, i8 signext %b4) nounwind readnone noinline {
7entry:
8; CHECK-LABEL: i8i16callee:
9; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5.
10; They are i8, i16, i8 and i8.
11; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #5]
12; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp, #4]
13; CHECK-DAG: ldrsh {{w[0-9]+}}, [sp, #2]
14; CHECK-DAG: ldrsb {{w[0-9]+}}, [sp]
15; FAST-LABEL: i8i16callee:
16; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp, #5]
17; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp, #4]
18; FAST-DAG: ldrsh  {{w[0-9]+}}, [sp, #2]
19; FAST-DAG: ldrsb  {{w[0-9]+}}, [sp]
20; GISEL-LABEL: i8i16callee:
21; GISEL-DAG: ldrsb  {{w[0-9]+}}, [sp, #5]
22; GISEL-DAG: ldrsb  {{w[0-9]+}}, [sp, #4]
23; GISEL-DAG: ldrsh  {{w[0-9]+}}, [sp, #2]
24; GISEL-DAG: ldrsb  {{w[0-9]+}}, [sp]
25  %conv = sext i8 %a4 to i64
26  %conv3 = sext i16 %a5 to i64
27  %conv8 = sext i8 %b1 to i64
28  %conv9 = sext i16 %b2 to i64
29  %conv11 = sext i8 %b3 to i64
30  %conv13 = sext i8 %b4 to i64
31  %add10 = add i64 %a2, %a1
32  %add12 = add i64 %add10, %a3
33  %add14 = add i64 %add12, %conv
34  %add = add i64 %add14, %conv3
35  %add1 = add i64 %add, %a6
36  %add2 = add i64 %add1, %a7
37  %add4 = add i64 %add2, %a8
38  %add5 = add i64 %add4, %conv8
39  %add6 = add i64 %add5, %conv9
40  %add7 = add i64 %add6, %conv11
41  %add15 = add i64 %add7, %conv13
42  %sext = shl i64 %add15, 32
43  %conv17 = ashr exact i64 %sext, 32
44  ret i64 %conv17
45}
46
47define i32 @i8i16caller() nounwind readnone {
48entry:
49; CHECK-LABEL: i8i16caller
50; The 8th, 9th, 10th and 11th arguments are passed at sp, sp+2, sp+4, sp+5.
51; They are i8, i16, i8 and i8.
52; CHECK-DAG: stur {{w[0-9]+}}, [sp, #2]
53; CHECK-DAG: strb {{w[0-9]+}}, [sp]
54; CHECK: bl
55; FAST-LABEL: i8i16caller
56; FAST: strb {{w[0-9]+}}, [sp]
57; FAST: strh {{w[0-9]+}}, [sp, #2]
58; FAST: strb {{w[0-9]+}}, [sp, #4]
59; FAST: strb {{w[0-9]+}}, [sp, #5]
60; FAST: bl
61  %call = tail call i64 @i8i16callee(i64 0, i64 1, i64 2, i8 signext 3, i16 signext 4, i64 5, i64 6, i64 7, i8 signext 97, i16 signext 98, i8 signext 99, i8 signext 100)
62  %conv = trunc i64 %call to i32
63  ret i32 %conv
64}
65
66; rdar://12651543
67define double @circle_center([2 x float] %a) nounwind ssp {
68  %call = tail call double @ext([2 x float] %a) nounwind
69; CHECK-LABEL: circle_center
70; CHECK: bl
71  ret double %call
72}
73declare double @ext([2 x float])
74
75; rdar://12656141
76; 16-byte vector should be aligned at 16-byte when passing on stack.
77; A double argument will be passed on stack, so vecotr should be at sp+16.
78define double @fixed_4i(ptr nocapture %in) nounwind {
79entry:
80; CHECK-LABEL: fixed_4i
81; CHECK: str [[REG_1:q[0-9]+]], [sp, #16]
82; FAST-LABEL: fixed_4i
83; FAST: sub sp, sp
84; FAST: mov x[[ADDR:[0-9]+]], sp
85; FAST: str [[REG_1:q[0-9]+]], [x[[ADDR]], #16]
86  %0 = load <4 x i32>, ptr %in, align 16
87  %call = tail call double @args_vec_4i(double 3.000000e+00, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, <4 x i32> %0, double 3.000000e+00, <4 x i32> %0, i8 signext 3)
88  ret double %call
89}
90declare double @args_vec_4i(double, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32>, double, <4 x i32>, i8 signext)
91
92; rdar://12695237
93; d8 at sp, i in register w0.
94@g_d = common global double 0.000000e+00, align 8
95define void @test1(float %f1, double %d1, double %d2, double %d3, double %d4,
96       double %d5, double %d6, double %d7, double %d8, i32 %i) nounwind ssp {
97entry:
98; CHECK-LABEL: test1
99; CHECK: ldr [[REG_1:d[0-9]+]], [sp]
100; CHECK: scvtf [[REG_2:s[0-9]+]], w0
101; CHECK: fadd s0, [[REG_2]], s0
102  %conv = sitofp i32 %i to float
103  %add = fadd float %conv, %f1
104  %conv1 = fpext float %add to double
105  %add2 = fadd double %conv1, %d7
106  %add3 = fadd double %add2, %d8
107  store double %add3, ptr @g_d, align 8
108  ret void
109}
110
111; i9 at sp, d1 in register s0.
112define void @test2(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6,
113            i32 %i7, i32 %i8, i32 %i9, float %d1) nounwind ssp {
114entry:
115; CHECK-LABEL: test2
116; CHECK: scvtf [[REG_2:s[0-9]+]], w0
117; CHECK: fadd s0, [[REG_2]], s0
118; CHECK: ldr [[REG_1:s[0-9]+]], [sp]
119  %conv = sitofp i32 %i1 to float
120  %add = fadd float %conv, %d1
121  %conv1 = fpext float %add to double
122  %conv2 = sitofp i32 %i8 to double
123  %add3 = fadd double %conv2, %conv1
124  %conv4 = sitofp i32 %i9 to double
125  %add5 = fadd double %conv4, %add3
126  store double %add5, ptr @g_d, align 8
127  ret void
128}
129
130; rdar://12648441
131; Check alignment on stack for v64, f64, i64, f32, i32.
132define double @test3(ptr nocapture %in) nounwind {
133entry:
134; CHECK-LABEL: test3
135; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
136; FAST-LABEL: test3
137; FAST: sub sp, sp, #{{[0-9]+}}
138; FAST: mov x[[ADDR:[0-9]+]], sp
139; FAST: str [[REG_1:d[0-9]+]], [x[[ADDR]], #8]
140  %0 = load <2 x i32>, ptr %in, align 8
141  %call = tail call double @args_vec_2i(double 3.000000e+00, <2 x i32> %0,
142          <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0, <2 x i32> %0,
143          <2 x i32> %0, float 3.000000e+00, <2 x i32> %0, i8 signext 3)
144  ret double %call
145}
146declare double @args_vec_2i(double, <2 x i32>, <2 x i32>, <2 x i32>, <2 x i32>,
147               <2 x i32>, <2 x i32>, <2 x i32>, float, <2 x i32>, i8 signext)
148
149define double @test4(ptr nocapture %in) nounwind {
150entry:
151; CHECK-LABEL: test4
152; CHECK: str [[REG_1:d[0-9]+]], [sp, #8]
153; CHECK: str [[REG_2:w[0-9]+]], [sp]
154; CHECK: mov w0, #3
155  %0 = load double, ptr %in, align 8
156  %call = tail call double @args_f64(double 3.000000e+00, double %0, double %0,
157          double %0, double %0, double %0, double %0, double %0,
158          float 3.000000e+00, double %0, i8 signext 3)
159  ret double %call
160}
161declare double @args_f64(double, double, double, double, double, double, double,
162               double, float, double, i8 signext)
163
164define i64 @test5(ptr nocapture %in) nounwind {
165entry:
166; CHECK-LABEL: test5
167; CHECK: strb [[REG_3:w[0-9]+]], [sp, #16]
168; CHECK: str [[REG_1:x[0-9]+]], [sp, #8]
169; CHECK: str [[REG_2:w[0-9]+]], [sp]
170  %0 = load i64, ptr %in, align 8
171  %call = tail call i64 @args_i64(i64 3, i64 %0, i64 %0, i64 %0, i64 %0, i64 %0,
172                         i64 %0, i64 %0, i32 3, i64 %0, i8 signext 3)
173  ret i64 %call
174}
175declare i64 @args_i64(i64, i64, i64, i64, i64, i64, i64, i64, i32, i64,
176             i8 signext)
177
178define i32 @test6(ptr nocapture %in) nounwind {
179entry:
180; CHECK-LABEL: test6
181; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
182; CHECK: str [[REG_1:s[0-9]+]], [sp, #4]
183; CHECK: strh [[REG_3:w[0-9]+]], [sp]
184  %0 = load float, ptr %in, align 4
185  %call = tail call i32 @args_f32(i32 1, i32 2, i32 3, i32 4, i32 5, i32 6,
186          i32 7, i32 8, float 1.0, float 2.0, float 3.0, float 4.0, float 5.0,
187          float 6.0, float 7.0, float 8.0, i16 signext 3, float %0,
188          i8 signext 3)
189  ret i32 %call
190}
191declare i32 @args_f32(i32, i32, i32, i32, i32, i32, i32, i32,
192                      float, float, float, float, float, float, float, float,
193                      i16 signext, float, i8 signext)
194
195define i32 @test7(ptr nocapture %in) nounwind {
196entry:
197; CHECK-LABEL: test7
198; CHECK: strb [[REG_2:w[0-9]+]], [sp, #8]
199; CHECK: str [[REG_1:w[0-9]+]], [sp, #4]
200; CHECK: strh [[REG_3:w[0-9]+]], [sp]
201  %0 = load i32, ptr %in, align 4
202  %call = tail call i32 @args_i32(i32 3, i32 %0, i32 %0, i32 %0, i32 %0, i32 %0,
203                         i32 %0, i32 %0, i16 signext 3, i32 %0, i8 signext 4)
204  ret i32 %call
205}
206declare i32 @args_i32(i32, i32, i32, i32, i32, i32, i32, i32, i16 signext, i32,
207             i8 signext)
208
209define i32 @test8(i32 %argc, ptr nocapture %argv) nounwind {
210entry:
211; CHECK-LABEL: test8
212; CHECK: str w8, [sp]
213; CHECK: bl
214; FAST-LABEL: test8
215; FAST: strb {{w[0-9]+}}, [sp]
216; FAST: strb {{w[0-9]+}}, [sp, #1]
217; FAST: strb {{w[0-9]+}}, [sp, #2]
218; FAST: strb {{w[0-9]+}}, [sp, #3]
219; FAST: bl
220  tail call void @args_i1(i1 zeroext false, i1 zeroext true, i1 zeroext false,
221                  i1 zeroext true, i1 zeroext false, i1 zeroext true,
222                  i1 zeroext false, i1 zeroext true, i1 zeroext false,
223                  i1 zeroext true, i1 zeroext false, i1 zeroext true)
224  ret i32 0
225}
226
227declare void @args_i1(i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
228                      i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext,
229                      i1 zeroext, i1 zeroext, i1 zeroext, i1 zeroext)
230
231define i32 @i1_stack_incoming(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e, i64 %f,
232                               i64 %g, i64 %h, i64 %i, i1 zeroext %j) {
233; CHECK-LABEL: i1_stack_incoming:
234; CHECK: ldrb w0, [sp, #8]
235; CHECK: ret
236; GISEL-LABEL: i1_stack_incoming:
237; GISEL: ldrb w0, [sp, #8]
238; GISEL: ret
239  %v = zext i1 %j to i32
240  ret i32 %v
241}
242