1; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve -stop-after=finalize-isel < %s 2>%t | FileCheck %s
2; RUN: FileCheck --check-prefix=WARN --allow-empty %s <%t
3
4; If this check fails please read test/CodeGen/AArch64/README for instructions on how to resolve it.
5; WARN-NOT: warning
6
7; Test that z8 and z9, passed in by reference, are correctly loaded from x0 and x1.
8; i.e. z0 =  %z0
9;         :
10;      z7 =  %z7
11;      x0 = &%z8
12;      x1 = &%z9
13define aarch64_sve_vector_pcs <vscale x 4 x i32> @callee_with_many_sve_arg(<vscale x 4 x i32> %z0, <vscale x 4 x i32> %z1, <vscale x 4 x i32> %z2, <vscale x 4 x i32> %z3, <vscale x 4 x i32> %z4, <vscale x 4 x i32> %z5, <vscale x 4 x i32> %z6, <vscale x 4 x i32> %z7, <vscale x 4 x i32> %z8, <vscale x 4 x i32> %z9) {
14; CHECK: name: callee_with_many_sve_arg
15; CHECK-DAG: [[BASE:%[0-9]+]]:gpr64common = COPY $x1
16; CHECK-DAG: [[PTRUE:%[0-9]+]]:ppr_3b = PTRUE_S 31
17; CHECK-DAG: [[RES:%[0-9]+]]:zpr = LD1W_IMM killed [[PTRUE]], [[BASE]]
18; CHECK-DAG: $z0 = COPY [[RES]]
19; CHECK:     RET_ReallyLR implicit $z0
20  ret <vscale x 4 x i32> %z9
21}
22
23; Test that z8 and z9 are passed by reference.
24define aarch64_sve_vector_pcs <vscale x 4 x i32> @caller_with_many_sve_arg(<vscale x 4 x i32> %z) {
25; CHECK: name: caller_with_many_sve_arg
26; CHECK: stack:
27; CHECK:      - { id: 0, name: '', type: default, offset: 0, size: 16, alignment: 16,
28; CHECK-NEXT:     stack-id: sve-vec
29; CHECK:      - { id: 1, name: '', type: default, offset: 0, size: 16, alignment: 16,
30; CHECK-NEXT:     stack-id: sve-vec
31; CHECK-DAG:  [[PTRUE:%[0-9]+]]:ppr_3b = PTRUE_S 31
32; CHECK-DAG:  ST1W_IMM %{{[0-9]+}}, [[PTRUE]], %stack.1, 0
33; CHECK-DAG:  ST1W_IMM %{{[0-9]+}}, [[PTRUE]], %stack.0, 0
34; CHECK-DAG:  [[BASE2:%[0-9]+]]:gpr64sp = ADDXri %stack.1, 0
35; CHECK-DAG:  [[BASE1:%[0-9]+]]:gpr64sp = ADDXri %stack.0, 0
36; CHECK-DAG:  $x0 = COPY [[BASE1]]
37; CHECK-DAG:  $x1 = COPY [[BASE2]]
38; CHECK-NEXT: BL @callee_with_many_sve_arg
39; CHECK:      RET_ReallyLR implicit $z0
40  %ret = call aarch64_sve_vector_pcs <vscale x 4 x i32> @callee_with_many_sve_arg(<vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z)
41  ret <vscale x 4 x i32> %ret
42}
43
44; Test that p4 and p5, passed in by reference, are correctly loaded from register x0 and x1.
45; i.e. p0 =  %p0
46;         :
47;      p3 =  %p3
48;      x0 = &%p4
49;      x1 = &%p5
50define aarch64_sve_vector_pcs <vscale x 4 x i1> @callee_with_many_svepred_arg(<vscale x 4 x i1> %p0, <vscale x 4 x i1> %p1, <vscale x 4 x i1> %p2, <vscale x 4 x i1> %p3, <vscale x 4 x i1> %p4, <vscale x 4 x i1> %p5) {
51; CHECK: name: callee_with_many_svepred_arg
52; CHECK-DAG: [[BASE:%[0-9]+]]:gpr64common = COPY $x1
53; CHECK-DAG: [[RES:%[0-9]+]]:ppr = LDR_PXI [[BASE]], 0
54; CHECK-DAG: $p0 = COPY [[RES]]
55; CHECK:     RET_ReallyLR implicit $p0
56  ret <vscale x 4 x i1> %p5
57}
58
59; Test that p4 and p5 are passed by reference.
60define aarch64_sve_vector_pcs <vscale x 4 x i1> @caller_with_many_svepred_arg(<vscale x 4 x i1> %p) {
61; CHECK: name: caller_with_many_svepred_arg
62; CHECK: stack:
63; CHECK:      - { id: 0, name: '', type: default, offset: 0, size: 1, alignment: 4,
64; CHECK-NEXT:     stack-id: sve-vec
65; CHECK:      - { id: 1, name: '', type: default, offset: 0, size: 1, alignment: 4,
66; CHECK-NEXT:     stack-id: sve-vec
67; CHECK-DAG: STR_PXI %{{[0-9]+}}, %stack.0, 0
68; CHECK-DAG: STR_PXI %{{[0-9]+}}, %stack.1, 0
69; CHECK-DAG: [[BASE1:%[0-9]+]]:gpr64sp = ADDXri %stack.0, 0
70; CHECK-DAG: [[BASE2:%[0-9]+]]:gpr64sp = ADDXri %stack.1, 0
71; CHECK-DAG: $x0 = COPY [[BASE1]]
72; CHECK-DAG: $x1 = COPY [[BASE2]]
73; CHECK-NEXT: BL @callee_with_many_svepred_arg
74; CHECK:     RET_ReallyLR implicit $p0
75  %ret = call aarch64_sve_vector_pcs <vscale x 4 x i1> @callee_with_many_svepred_arg(<vscale x 4 x i1> %p, <vscale x 4 x i1> %p, <vscale x 4 x i1> %p, <vscale x 4 x i1> %p, <vscale x 4 x i1> %p, <vscale x 4 x i1> %p)
76  ret <vscale x 4 x i1> %ret
77}
78
79; Test that z8 and z9, passed by reference, are loaded from a location that is passed on the stack.
80; i.e.     x0 =   %x0
81;             :
82;          x7 =   %x7
83;          z0 =   %z0
84;             :
85;          z7 =   %z7
86;        [sp] =  &%z8
87;      [sp+8] =  &%z9
88;
89define aarch64_sve_vector_pcs <vscale x 4 x i32> @callee_with_many_gpr_sve_arg(i64 %x0, i64 %x1, i64 %x2, i64 %x3, i64 %x4, i64 %x5, i64 %x6, i64 %x7, <vscale x 4 x i32> %z0, <vscale x 4 x i32> %z1, <vscale x 4 x i32> %z2, <vscale x 4 x i32> %z3, <vscale x 4 x i32> %z4, <vscale x 4 x i32> %z5, <vscale x 4 x i32> %z6, <vscale x 4 x i32> %z7, <vscale x 2 x i64> %z8, <vscale x 4 x i32> %z9) {
90; CHECK: name: callee_with_many_gpr_sve_arg
91; CHECK: fixedStack:
92; CHECK:      - { id: 0, type: default, offset: 8, size: 8, alignment: 8, stack-id: default,
93; CHECK-DAG: [[BASE:%[0-9]+]]:gpr64common = LDRXui %fixed-stack.0, 0
94; CHECK-DAG: [[PTRUE:%[0-9]+]]:ppr_3b = PTRUE_S 31
95; CHECK-DAG: [[RES:%[0-9]+]]:zpr = LD1W_IMM killed [[PTRUE]], killed [[BASE]]
96; CHECK-DAG: $z0 = COPY [[RES]]
97; CHECK: RET_ReallyLR implicit $z0
98  ret <vscale x 4 x i32> %z9
99}
100
101; Test that z8 and z9 are passed by reference, where reference is passed on the stack.
102define aarch64_sve_vector_pcs <vscale x 4 x i32> @caller_with_many_gpr_sve_arg(i64 %x, <vscale x 4 x i32> %z, <vscale x 2 x i64> %z2) {
103; CHECK: name: caller_with_many_gpr_sve_arg
104; CHECK: stack:
105; CHECK:      - { id: 0, name: '', type: default, offset: 0, size: 16, alignment: 16,
106; CHECK-NEXT:     stack-id: sve-vec
107; CHECK:      - { id: 1, name: '', type: default, offset: 0, size: 16, alignment: 16,
108; CHECK-NEXT:     stack-id: sve-vec
109; CHECK-DAG: [[PTRUE_S:%[0-9]+]]:ppr_3b = PTRUE_S 31
110; CHECK-DAG: [[PTRUE_D:%[0-9]+]]:ppr_3b = PTRUE_D 31
111; CHECK-DAG: ST1D_IMM %{{[0-9]+}}, killed [[PTRUE_D]], %stack.0, 0
112; CHECK-DAG: ST1W_IMM %{{[0-9]+}}, killed [[PTRUE_S]], %stack.1, 0
113; CHECK-DAG: [[BASE1:%[0-9]+]]:gpr64common = ADDXri %stack.0, 0
114; CHECK-DAG: [[BASE2:%[0-9]+]]:gpr64common = ADDXri %stack.1, 0
115; CHECK-DAG: [[SP:%[0-9]+]]:gpr64sp = COPY $sp
116; CHECK-DAG: STRXui killed [[BASE1]], [[SP]], 0
117; CHECK-DAG: STRXui killed [[BASE2]], [[SP]], 1
118; CHECK:     BL @callee_with_many_gpr_sve_arg
119; CHECK:     RET_ReallyLR implicit $z0
120  %ret = call aarch64_sve_vector_pcs <vscale x 4 x i32> @callee_with_many_gpr_sve_arg(i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, i64 %x, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 4 x i32> %z, <vscale x 2 x i64> %z2, <vscale x 4 x i32> %z)
121  ret <vscale x 4 x i32> %ret
122}
123