[RISCV][VLOPT] Add vector narrowing integer right shift instructions to isSupportedIn...
[llvm-project.git] / llvm / test / CodeGen / AArch64 / arm64-windows-calls.ll
blobbf559da91901cf4190482de075ce4a8345982155
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2
2 ; FIXME: Add tests for global-isel/fast-isel.
4 ; RUN: llc < %s -mtriple=arm64-windows | FileCheck %s
6 ; Returns <= 8 bytes should be in X0.
7 %struct.S1 = type { i32, i32 }
8 define dso_local i64 @"?f1"() {
9 entry:
10 ; CHECK-LABEL: f1
11 ; CHECK-DAG: str xzr, [sp, #8]
12 ; CHECK-DAG: mov x0, xzr
14   %retval = alloca %struct.S1, align 4
15   store i32 0, ptr %retval, align 4
16   %b = getelementptr inbounds %struct.S1, ptr %retval, i32 0, i32 1
17   store i32 0, ptr %b, align 4
18   %0 = load i64, ptr %retval, align 4
19   ret i64 %0
22 ; Returns <= 16 bytes should be in X0/X1.
23 %struct.S2 = type { i32, i32, i32, i32 }
24 define dso_local [2 x i64] @"?f2"() {
25 entry:
26 ; FIXME: Missed optimization, the entire SP push/pop could be removed
27 ; CHECK-LABEL: f2
28 ; CHECK:         sub     sp, sp, #16
29 ; CHECK-NEXT:    .seh_stackalloc 16
30 ; CHECK-NEXT:    .seh_endprologue
31 ; CHECK-DAG:     stp     xzr, xzr, [sp]
32 ; CHECK-DAG:     mov     x0, xzr
33 ; CHECK-DAG:     mov     x1, xzr
34 ; CHECK:         .seh_startepilogue
35 ; CHECK-NEXT:    add     sp, sp, #16
37   %retval = alloca %struct.S2, align 4
38   store i32 0, ptr %retval, align 4
39   %b = getelementptr inbounds %struct.S2, ptr %retval, i32 0, i32 1
40   store i32 0, ptr %b, align 4
41   %c = getelementptr inbounds %struct.S2, ptr %retval, i32 0, i32 2
42   store i32 0, ptr %c, align 4
43   %d = getelementptr inbounds %struct.S2, ptr %retval, i32 0, i32 3
44   store i32 0, ptr %d, align 4
45   %0 = load [2 x i64], ptr %retval, align 4
46   ret [2 x i64] %0
49 ; Arguments > 16 bytes should be passed in X8.
50 %struct.S3 = type { i32, i32, i32, i32, i32 }
51 define dso_local void @"?f3"(ptr noalias sret(%struct.S3) %agg.result) {
52 entry:
53 ; CHECK-LABEL: f3
54 ; CHECK: stp xzr, xzr, [x8]
55 ; CHECK: str wzr, [x8, #16]
57   store i32 0, ptr %agg.result, align 4
58   %b = getelementptr inbounds %struct.S3, ptr %agg.result, i32 0, i32 1
59   store i32 0, ptr %b, align 4
60   %c = getelementptr inbounds %struct.S3, ptr %agg.result, i32 0, i32 2
61   store i32 0, ptr %c, align 4
62   %d = getelementptr inbounds %struct.S3, ptr %agg.result, i32 0, i32 3
63   store i32 0, ptr %d, align 4
64   %e = getelementptr inbounds %struct.S3, ptr %agg.result, i32 0, i32 4
65   store i32 0, ptr %e, align 4
66   ret void
69 ; InReg arguments to non-instance methods must be passed in X0 and returns in
70 ; X0.
71 %class.B = type { i32 }
72 define dso_local void @"?f4"(ptr inreg noalias nocapture sret(%class.B) %agg.result) {
73 entry:
74 ; CHECK-LABEL: f4
75 ; CHECK: mov w8, #1
76 ; CHECK: str w8, [x0]
77   store i32 1, ptr %agg.result, align 4
78   ret void
81 ; InReg arguments to instance methods must be passed in X1 and returns in X0.
82 %class.C = type { i8 }
83 %class.A = type { i8 }
85 define dso_local void @"?inst@C"(ptr %this, ptr inreg noalias sret(%class.A) %agg.result) {
86 entry:
87 ; CHECK-LABEL: inst@C
88 ; CHECK-DAG: mov x0, x1
89 ; CHECK-DAG: str x8, [sp, #8]
91   %this.addr = alloca ptr, align 8
92   store ptr %this, ptr %this.addr, align 8
93   %this1 = load ptr, ptr %this.addr, align 8
94   ret void
97 ; The following tests correspond to tests in
98 ; clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
100 ; Pod is a trivial HFA
101 %struct.Pod = type { [2 x double] }
102 ; Not an aggregate according to C++14 spec => not HFA according to MSVC
103 %struct.NotCXX14Aggregate  = type { %struct.Pod }
104 ; NotPod is a C++14 aggregate. But not HFA, because it contains
105 ; NotCXX14Aggregate (which itself is not HFA because it's not a C++14
106 ; aggregate).
107 %struct.NotPod = type { %struct.NotCXX14Aggregate }
109 define dso_local %struct.Pod @copy_pod(ptr %x) {
110 ; CHECK-LABEL: copy_pod:
111 ; CHECK:       // %bb.0:
112 ; CHECK-NEXT:    ldp d0, d1, [x0]
113 ; CHECK-NEXT:    ret
114   %x1 = load %struct.Pod, ptr %x, align 8
115   ret %struct.Pod %x1
118 declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)
120 define dso_local void @copy_notcxx14aggregate(ptr inreg noalias sret(%struct.NotCXX14Aggregate) align 8 %agg.result, ptr %x) {
121 ; CHECK-LABEL: copy_notcxx14aggregate:
122 ; CHECK:       // %bb.0:
123 ; CHECK-NEXT:    ldr q0, [x1]
124 ; CHECK-NEXT:    str q0, [x0]
125 ; CHECK-NEXT:    ret
126   call void @llvm.memcpy.p0.p0.i64(ptr align 8 %agg.result, ptr align 8 %x, i64 16, i1 false)
127   ret void
130 define dso_local [2 x i64] @copy_notpod(ptr %x) {
131 ; CHECK-LABEL: copy_notpod:
132 ; CHECK:       // %bb.0:
133 ; CHECK-NEXT:    ldp x8, x1, [x0]
134 ; CHECK-NEXT:    mov x0, x8
135 ; CHECK-NEXT:    ret
136   %x2 = load [2 x i64], ptr %x
137   ret [2 x i64] %x2
140 @Pod = external global %struct.Pod
142 define void @call_copy_pod() {
143 ; CHECK-LABEL: call_copy_pod:
144 ; CHECK:       .seh_proc call_copy_pod
145 ; CHECK-NEXT:  // %bb.0:
146 ; CHECK-NEXT:    str x19, [sp, #-16]! // 8-byte Folded Spill
147 ; CHECK-NEXT:    .seh_save_reg_x x19, 16
148 ; CHECK-NEXT:    str x30, [sp, #8] // 8-byte Folded Spill
149 ; CHECK-NEXT:    .seh_save_reg x30, 8
150 ; CHECK-NEXT:    .seh_endprologue
151 ; CHECK-NEXT:    adrp x19, Pod
152 ; CHECK-NEXT:    add x19, x19, :lo12:Pod
153 ; CHECK-NEXT:    mov x0, x19
154 ; CHECK-NEXT:    bl copy_pod
155 ; CHECK-NEXT:    stp d0, d1, [x19]
156 ; CHECK-NEXT:    .seh_startepilogue
157 ; CHECK-NEXT:    ldr x30, [sp, #8] // 8-byte Folded Reload
158 ; CHECK-NEXT:    .seh_save_reg x30, 8
159 ; CHECK-NEXT:    ldr x19, [sp], #16 // 8-byte Folded Reload
160 ; CHECK-NEXT:    .seh_save_reg_x x19, 16
161 ; CHECK-NEXT:    .seh_endepilogue
162 ; CHECK-NEXT:    ret
163 ; CHECK-NEXT:    .seh_endfunclet
164 ; CHECK-NEXT:    .seh_endproc
165   %x = call %struct.Pod @copy_pod(ptr @Pod)
166   store %struct.Pod %x, ptr @Pod
167   ret void
170 @NotCXX14Aggregate = external global %struct.NotCXX14Aggregate
172 define void @call_copy_notcxx14aggregate() {
173 ; CHECK-LABEL: call_copy_notcxx14aggregate:
174 ; CHECK:       .seh_proc call_copy_notcxx14aggregate
175 ; CHECK-NEXT:  // %bb.0:
176 ; CHECK-NEXT:    sub sp, sp, #32
177 ; CHECK-NEXT:    .seh_stackalloc 32
178 ; CHECK-NEXT:    str x19, [sp, #16] // 8-byte Folded Spill
179 ; CHECK-NEXT:    .seh_save_reg x19, 16
180 ; CHECK-NEXT:    str x30, [sp, #24] // 8-byte Folded Spill
181 ; CHECK-NEXT:    .seh_save_reg x30, 24
182 ; CHECK-NEXT:    .seh_endprologue
183 ; CHECK-NEXT:    adrp x19, NotCXX14Aggregate
184 ; CHECK-NEXT:    add x19, x19, :lo12:NotCXX14Aggregate
185 ; CHECK-NEXT:    mov x0, sp
186 ; CHECK-NEXT:    mov x1, x19
187 ; CHECK-NEXT:    bl copy_notcxx14aggregate
188 ; CHECK-NEXT:    ldp d0, d1, [sp]
189 ; CHECK-NEXT:    stp d0, d1, [x19]
190 ; CHECK-NEXT:    .seh_startepilogue
191 ; CHECK-NEXT:    ldr x30, [sp, #24] // 8-byte Folded Reload
192 ; CHECK-NEXT:    .seh_save_reg x30, 24
193 ; CHECK-NEXT:    ldr x19, [sp, #16] // 8-byte Folded Reload
194 ; CHECK-NEXT:    .seh_save_reg x19, 16
195 ; CHECK-NEXT:    add sp, sp, #32
196 ; CHECK-NEXT:    .seh_stackalloc 32
197 ; CHECK-NEXT:    .seh_endepilogue
198 ; CHECK-NEXT:    ret
199 ; CHECK-NEXT:    .seh_endfunclet
200 ; CHECK-NEXT:    .seh_endproc
201   %x = alloca %struct.NotCXX14Aggregate
202   call void @copy_notcxx14aggregate(ptr %x, ptr @NotCXX14Aggregate)
203   %x1 = load %struct.NotCXX14Aggregate, ptr %x
204   store %struct.NotCXX14Aggregate %x1, ptr @NotCXX14Aggregate
205   ret void
208 @NotPod = external global %struct.NotPod
210 define void @call_copy_notpod() {
211 ; CHECK-LABEL: call_copy_notpod:
212 ; CHECK:       .seh_proc call_copy_notpod
213 ; CHECK-NEXT:  // %bb.0:
214 ; CHECK-NEXT:    str x19, [sp, #-16]! // 8-byte Folded Spill
215 ; CHECK-NEXT:    .seh_save_reg_x x19, 16
216 ; CHECK-NEXT:    str x30, [sp, #8] // 8-byte Folded Spill
217 ; CHECK-NEXT:    .seh_save_reg x30, 8
218 ; CHECK-NEXT:    .seh_endprologue
219 ; CHECK-NEXT:    adrp x19, NotPod
220 ; CHECK-NEXT:    add x19, x19, :lo12:NotPod
221 ; CHECK-NEXT:    mov x0, x19
222 ; CHECK-NEXT:    bl copy_notpod
223 ; CHECK-NEXT:    stp x0, x1, [x19]
224 ; CHECK-NEXT:    .seh_startepilogue
225 ; CHECK-NEXT:    ldr x30, [sp, #8] // 8-byte Folded Reload
226 ; CHECK-NEXT:    .seh_save_reg x30, 8
227 ; CHECK-NEXT:    ldr x19, [sp], #16 // 8-byte Folded Reload
228 ; CHECK-NEXT:    .seh_save_reg_x x19, 16
229 ; CHECK-NEXT:    .seh_endepilogue
230 ; CHECK-NEXT:    ret
231 ; CHECK-NEXT:    .seh_endfunclet
232 ; CHECK-NEXT:    .seh_endproc
233   %x = call [2 x i64] @copy_notpod(ptr @NotPod)
234   store [2 x i64] %x, ptr @NotPod
235   ret void
238 ; We shouldn't return the argument
239 ; when it has only inreg attribute
240 define i64 @foobar(ptr inreg %0) {
241 ; CHECK-LABEL: foobar:
242 ; CHECK:       // %bb.0: // %entry
243 ; CHECK-NEXT:    ldr x0, [x0]
244 ; CHECK-NEXT:    ret
245 entry:
246   %1 = load i64, ptr %0
247   ret i64 %1