1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s | FileCheck %s --check-prefixes=ALL,CHECK
3 ; RUN: llc -O0 < %s | FileCheck %s --check-prefixes=ALL,CHECK-O0
5 ; Source to regenerate:
9 ; __attribute__((address_space(9))) int *p_other;
11 ; void use_foo(Foo *f);
12 ; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
16 ; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
20 ; void test_trunc(Foo *f, int * __ptr64 i) {
24 ; void test_noop1(Foo *f, int * __ptr32 i) {
28 ; void test_noop2(Foo *f, int * __ptr64 i) {
32 ; void test_null_arg(Foo *f, int * __ptr32 i) {
35 ; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
36 ; f->p32 = (int * __ptr32)i;
40 ; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
42 target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
43 target triple = "x86_64-unknown-windows-msvc"
45 %struct.Foo = type { ptr addrspace(270), ptr, ptr addrspace(9) }
46 declare dso_local void @use_foo(ptr)
48 define dso_local void @test_sign_ext(ptr %f, ptr addrspace(270) %i) {
49 ; ALL-LABEL: test_sign_ext:
50 ; ALL: # %bb.0: # %entry
51 ; ALL-NEXT: movslq %edx, %rax
52 ; ALL-NEXT: movq %rax, 8(%rcx)
53 ; ALL-NEXT: jmp use_foo # TAILCALL
55 %0 = addrspacecast ptr addrspace(270) %i to ptr
56 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
57 store ptr %0, ptr %p64, align 8
58 tail call void @use_foo(ptr %f)
62 define dso_local void @test_zero_ext(ptr %f, ptr addrspace(271) %i) {
63 ; CHECK-LABEL: test_zero_ext:
64 ; CHECK: # %bb.0: # %entry
65 ; CHECK-NEXT: movl %edx, %eax
66 ; CHECK-NEXT: movq %rax, 8(%rcx)
67 ; CHECK-NEXT: jmp use_foo # TAILCALL
69 ; CHECK-O0-LABEL: test_zero_ext:
70 ; CHECK-O0: # %bb.0: # %entry
71 ; CHECK-O0-NEXT: movl %edx, %eax
72 ; CHECK-O0-NEXT: # kill: def $rax killed $eax
73 ; CHECK-O0-NEXT: movq %rax, 8(%rcx)
74 ; CHECK-O0-NEXT: jmp use_foo # TAILCALL
76 %0 = addrspacecast ptr addrspace(271) %i to ptr
77 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
78 store ptr %0, ptr %p64, align 8
79 tail call void @use_foo(ptr %f)
83 define dso_local void @test_trunc(ptr %f, ptr %i) {
84 ; CHECK-LABEL: test_trunc:
85 ; CHECK: # %bb.0: # %entry
86 ; CHECK-NEXT: movl %edx, (%rcx)
87 ; CHECK-NEXT: jmp use_foo # TAILCALL
89 ; CHECK-O0-LABEL: test_trunc:
90 ; CHECK-O0: # %bb.0: # %entry
91 ; CHECK-O0-NEXT: movl %edx, %eax
92 ; CHECK-O0-NEXT: movl %eax, (%rcx)
93 ; CHECK-O0-NEXT: jmp use_foo # TAILCALL
95 %0 = addrspacecast ptr %i to ptr addrspace(270)
96 store ptr addrspace(270) %0, ptr %f, align 8
97 tail call void @use_foo(ptr %f)
101 define dso_local void @test_noop1(ptr %f, ptr addrspace(270) %i) {
102 ; ALL-LABEL: test_noop1:
103 ; ALL: # %bb.0: # %entry
104 ; ALL-NEXT: movl %edx, (%rcx)
105 ; ALL-NEXT: jmp use_foo # TAILCALL
107 store ptr addrspace(270) %i, ptr %f, align 8
108 tail call void @use_foo(ptr %f)
112 define dso_local void @test_noop2(ptr %f, ptr %i) {
113 ; ALL-LABEL: test_noop2:
114 ; ALL: # %bb.0: # %entry
115 ; ALL-NEXT: movq %rdx, 8(%rcx)
116 ; ALL-NEXT: jmp use_foo # TAILCALL
118 %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
119 store ptr %i, ptr %p64, align 8
120 tail call void @use_foo(ptr %f)
124 ; Test that null can be passed as a 32-bit pointer.
125 define dso_local void @test_null_arg(ptr %f) {
126 ; ALL-LABEL: test_null_arg:
127 ; ALL: # %bb.0: # %entry
128 ; ALL-NEXT: subq $40, %rsp
129 ; ALL-NEXT: .seh_stackalloc 40
130 ; ALL-NEXT: .seh_endprologue
131 ; ALL-NEXT: xorl %edx, %edx
132 ; ALL-NEXT: callq test_noop1
134 ; ALL-NEXT: addq $40, %rsp
136 ; ALL-NEXT: .seh_endproc
138 call void @test_noop1(ptr %f, ptr addrspace(270) null)
142 ; Test casts between unrecognized address spaces.
143 define void @test_unrecognized(ptr %f, ptr addrspace(14) %i) {
144 ; CHECK-LABEL: test_unrecognized:
145 ; CHECK: # %bb.0: # %entry
146 ; CHECK-NEXT: movl %edx, (%rcx)
147 ; CHECK-NEXT: jmp use_foo # TAILCALL
149 ; CHECK-O0-LABEL: test_unrecognized:
150 ; CHECK-O0: # %bb.0: # %entry
151 ; CHECK-O0-NEXT: movl %edx, %eax
152 ; CHECK-O0-NEXT: movl %eax, (%rcx)
153 ; CHECK-O0-NEXT: jmp use_foo # TAILCALL
155 %0 = addrspacecast ptr addrspace(14) %i to ptr addrspace(270)
156 store ptr addrspace(270) %0, ptr %f, align 8
157 tail call void @use_foo(ptr %f)
161 define void @test_unrecognized2(ptr %f, ptr addrspace(271) %i) {
162 ; CHECK-LABEL: test_unrecognized2:
163 ; CHECK: # %bb.0: # %entry
164 ; CHECK-NEXT: movl %edx, %eax
165 ; CHECK-NEXT: movq %rax, 16(%rcx)
166 ; CHECK-NEXT: jmp use_foo # TAILCALL
168 ; CHECK-O0-LABEL: test_unrecognized2:
169 ; CHECK-O0: # %bb.0: # %entry
170 ; CHECK-O0-NEXT: movl %edx, %eax
171 ; CHECK-O0-NEXT: # kill: def $rax killed $eax
172 ; CHECK-O0-NEXT: movq %rax, 16(%rcx)
173 ; CHECK-O0-NEXT: jmp use_foo # TAILCALL
175 %0 = addrspacecast ptr addrspace(271) %i to ptr addrspace(9)
176 %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
177 store ptr addrspace(9) %0, ptr %p32, align 8
178 tail call void @use_foo(ptr %f)
182 define i32 @test_load_sptr32(ptr addrspace(270) %i) {
183 ; ALL-LABEL: test_load_sptr32:
184 ; ALL: # %bb.0: # %entry
185 ; ALL-NEXT: movslq %ecx, %rax
186 ; ALL-NEXT: movl (%rax), %eax
189 %0 = load i32, ptr addrspace(270) %i, align 4
193 define i32 @test_load_uptr32(ptr addrspace(271) %i) {
194 ; CHECK-LABEL: test_load_uptr32:
195 ; CHECK: # %bb.0: # %entry
196 ; CHECK-NEXT: movl %ecx, %eax
197 ; CHECK-NEXT: movl (%rax), %eax
200 ; CHECK-O0-LABEL: test_load_uptr32:
201 ; CHECK-O0: # %bb.0: # %entry
202 ; CHECK-O0-NEXT: movl %ecx, %eax
203 ; CHECK-O0-NEXT: # kill: def $rax killed $eax
204 ; CHECK-O0-NEXT: movl (%rax), %eax
205 ; CHECK-O0-NEXT: retq
207 %0 = load i32, ptr addrspace(271) %i, align 4
211 define i32 @test_load_ptr64(ptr addrspace(272) %i) {
212 ; ALL-LABEL: test_load_ptr64:
213 ; ALL: # %bb.0: # %entry
214 ; ALL-NEXT: movl (%rcx), %eax
217 %0 = load i32, ptr addrspace(272) %i, align 8
221 define void @test_store_sptr32(ptr addrspace(270) %s, i32 %i) {
222 ; ALL-LABEL: test_store_sptr32:
223 ; ALL: # %bb.0: # %entry
224 ; ALL-NEXT: movslq %ecx, %rax
225 ; ALL-NEXT: movl %edx, (%rax)
228 store i32 %i, ptr addrspace(270) %s, align 4
232 define void @test_store_uptr32(ptr addrspace(271) %s, i32 %i) {
233 ; CHECK-LABEL: test_store_uptr32:
234 ; CHECK: # %bb.0: # %entry
235 ; CHECK-NEXT: movl %ecx, %eax
236 ; CHECK-NEXT: movl %edx, (%rax)
239 ; CHECK-O0-LABEL: test_store_uptr32:
240 ; CHECK-O0: # %bb.0: # %entry
241 ; CHECK-O0-NEXT: movl %ecx, %eax
242 ; CHECK-O0-NEXT: # kill: def $rax killed $eax
243 ; CHECK-O0-NEXT: movl %edx, (%rax)
244 ; CHECK-O0-NEXT: retq
246 store i32 %i, ptr addrspace(271) %s, align 4
250 define void @test_store_ptr64(ptr addrspace(272) %s, i32 %i) {
251 ; ALL-LABEL: test_store_ptr64:
252 ; ALL: # %bb.0: # %entry
253 ; ALL-NEXT: movl %edx, (%rcx)
256 store i32 %i, ptr addrspace(272) %s, align 8
260 define i64 @test_load_sptr32_zext_i64(ptr addrspace(270) %i) {
261 ; CHECK-LABEL: test_load_sptr32_zext_i64:
262 ; CHECK: # %bb.0: # %entry
263 ; CHECK-NEXT: movslq %ecx, %rax
264 ; CHECK-NEXT: movl (%rax), %eax
267 ; CHECK-O0-LABEL: test_load_sptr32_zext_i64:
268 ; CHECK-O0: # %bb.0: # %entry
269 ; CHECK-O0-NEXT: movslq %ecx, %rax
270 ; CHECK-O0-NEXT: movl (%rax), %eax
271 ; CHECK-O0-NEXT: movl %eax, %eax
272 ; CHECK-O0-NEXT: # kill: def $rax killed $eax
273 ; CHECK-O0-NEXT: retq
275 %0 = load i32, ptr addrspace(270) %i, align 4
276 %1 = zext i32 %0 to i64
280 define void @test_store_sptr32_trunc_i1(ptr addrspace(270) %s, i32 %i) {
281 ; CHECK-LABEL: test_store_sptr32_trunc_i1:
282 ; CHECK: # %bb.0: # %entry
283 ; CHECK-NEXT: movslq %ecx, %rax
284 ; CHECK-NEXT: andl $1, %edx
285 ; CHECK-NEXT: movb %dl, (%rax)
288 ; CHECK-O0-LABEL: test_store_sptr32_trunc_i1:
289 ; CHECK-O0: # %bb.0: # %entry
290 ; CHECK-O0-NEXT: movslq %ecx, %rax
291 ; CHECK-O0-NEXT: andl $1, %edx
292 ; CHECK-O0-NEXT: movb %dl, %cl
293 ; CHECK-O0-NEXT: movb %cl, (%rax)
294 ; CHECK-O0-NEXT: retq
296 %0 = trunc i32 %i to i1
297 store i1 %0, ptr addrspace(270) %s