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
4
5; Source to regenerate:
6; struct Foo {
7;   int * __ptr32 p32;
8;   int * __ptr64 p64;
9;   __attribute__((address_space(9))) int *p_other;
10; };
11; void use_foo(Foo *f);
12; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
13;   f->p64 = i;
14;   use_foo(f);
15; }
16; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
17;   f->p64 = i;
18;   use_foo(f);
19; }
20; void test_trunc(Foo *f, int * __ptr64 i) {
21;   f->p32 = i;
22;   use_foo(f);
23; }
24; void test_noop1(Foo *f, int * __ptr32 i) {
25;   f->p32 = i;
26;   use_foo(f);
27; }
28; void test_noop2(Foo *f, int * __ptr64 i) {
29;   f->p64 = i;
30;   use_foo(f);
31; }
32; void test_null_arg(Foo *f, int * __ptr32 i) {
33;   test_noop1(f, 0);
34; }
35; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
36;   f->p32 = (int * __ptr32)i;
37;   use_foo(f);
38; }
39;
40; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
41
42target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
43target triple = "x86_64-unknown-windows-msvc"
44
45%struct.Foo = type { i32 addrspace(270)*, i32*, i32 addrspace(9)* }
46declare dso_local void @use_foo(%struct.Foo*)
47
48define dso_local void @test_sign_ext(%struct.Foo* %f, i32 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
54entry:
55  %0 = addrspacecast i32 addrspace(270)* %i to i32*
56  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
57  store i32* %0, i32** %p64, align 8
58  tail call void @use_foo(%struct.Foo* %f)
59  ret void
60}
61
62define dso_local void @test_zero_ext(%struct.Foo* %f, i32 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
68;
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
75entry:
76  %0 = addrspacecast i32 addrspace(271)* %i to i32*
77  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
78  store i32* %0, i32** %p64, align 8
79  tail call void @use_foo(%struct.Foo* %f)
80  ret void
81}
82
83define dso_local void @test_trunc(%struct.Foo* %f, i32* %i) {
84; CHECK-LABEL: test_trunc:
85; CHECK:       # %bb.0: # %entry
86; CHECK-NEXT:    movl %edx, (%rcx)
87; CHECK-NEXT:    jmp use_foo # TAILCALL
88;
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
94entry:
95  %0 = addrspacecast i32* %i to i32 addrspace(270)*
96  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
97  store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
98  tail call void @use_foo(%struct.Foo* %f)
99  ret void
100}
101
102define dso_local void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* %i) {
103; ALL-LABEL: test_noop1:
104; ALL:       # %bb.0: # %entry
105; ALL-NEXT:    movl %edx, (%rcx)
106; ALL-NEXT:    jmp use_foo # TAILCALL
107entry:
108  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
109  store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8
110  tail call void @use_foo(%struct.Foo* %f)
111  ret void
112}
113
114define dso_local void @test_noop2(%struct.Foo* %f, i32* %i) {
115; ALL-LABEL: test_noop2:
116; ALL:       # %bb.0: # %entry
117; ALL-NEXT:    movq %rdx, 8(%rcx)
118; ALL-NEXT:    jmp use_foo # TAILCALL
119entry:
120  %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1
121  store i32* %i, i32** %p64, align 8
122  tail call void @use_foo(%struct.Foo* %f)
123  ret void
124}
125
126; Test that null can be passed as a 32-bit pointer.
127define dso_local void @test_null_arg(%struct.Foo* %f) {
128; ALL-LABEL: test_null_arg:
129; ALL:       # %bb.0: # %entry
130; ALL-NEXT:    subq $40, %rsp
131; ALL-NEXT:    .seh_stackalloc 40
132; ALL-NEXT:    .seh_endprologue
133; ALL-NEXT:    xorl %edx, %edx
134; ALL-NEXT:    callq test_noop1
135; ALL-NEXT:    nop
136; ALL-NEXT:    addq $40, %rsp
137; ALL-NEXT:    retq
138; ALL-NEXT:    .seh_endproc
139entry:
140  call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null)
141  ret void
142}
143
144; Test casts between unrecognized address spaces.
145define void @test_unrecognized(%struct.Foo* %f, i32 addrspace(14)* %i) {
146; CHECK-LABEL: test_unrecognized:
147; CHECK:       # %bb.0: # %entry
148; CHECK-NEXT:    movl %edx, (%rcx)
149; CHECK-NEXT:    jmp use_foo # TAILCALL
150;
151; CHECK-O0-LABEL: test_unrecognized:
152; CHECK-O0:       # %bb.0: # %entry
153; CHECK-O0-NEXT:    movl %edx, %eax
154; CHECK-O0-NEXT:    movl %eax, (%rcx)
155; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
156entry:
157  %0 = addrspacecast i32 addrspace(14)* %i to i32 addrspace(270)*
158  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0
159  store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8
160  tail call void @use_foo(%struct.Foo* %f)
161  ret void
162}
163
164define void @test_unrecognized2(%struct.Foo* %f, i32 addrspace(271)* %i) {
165; CHECK-LABEL: test_unrecognized2:
166; CHECK:       # %bb.0: # %entry
167; CHECK-NEXT:    movl %edx, %eax
168; CHECK-NEXT:    movq %rax, 16(%rcx)
169; CHECK-NEXT:    jmp use_foo # TAILCALL
170;
171; CHECK-O0-LABEL: test_unrecognized2:
172; CHECK-O0:       # %bb.0: # %entry
173; CHECK-O0-NEXT:    movl %edx, %eax
174; CHECK-O0-NEXT:    # kill: def $rax killed $eax
175; CHECK-O0-NEXT:    movq %rax, 16(%rcx)
176; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
177entry:
178  %0 = addrspacecast i32 addrspace(271)* %i to i32 addrspace(9)*
179  %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 2
180  store i32 addrspace(9)* %0, i32 addrspace(9)** %p32, align 8
181  tail call void @use_foo(%struct.Foo* %f)
182  ret void
183}
184
185define i32 @test_load_sptr32(i32 addrspace(270)* %i) {
186; ALL-LABEL: test_load_sptr32:
187; ALL:       # %bb.0: # %entry
188; ALL-NEXT:    movslq %ecx, %rax
189; ALL-NEXT:    movl (%rax), %eax
190; ALL-NEXT:    retq
191entry:
192  %0 = load i32, i32 addrspace(270)* %i, align 4
193  ret i32 %0
194}
195
196define i32 @test_load_uptr32(i32 addrspace(271)* %i) {
197; CHECK-LABEL: test_load_uptr32:
198; CHECK:       # %bb.0: # %entry
199; CHECK-NEXT:    movl %ecx, %eax
200; CHECK-NEXT:    movl (%rax), %eax
201; CHECK-NEXT:    retq
202;
203; CHECK-O0-LABEL: test_load_uptr32:
204; CHECK-O0:       # %bb.0: # %entry
205; CHECK-O0-NEXT:    movl %ecx, %eax
206; CHECK-O0-NEXT:    # kill: def $rax killed $eax
207; CHECK-O0-NEXT:    movl (%rax), %eax
208; CHECK-O0-NEXT:    retq
209entry:
210  %0 = load i32, i32 addrspace(271)* %i, align 4
211  ret i32 %0
212}
213
214define i32 @test_load_ptr64(i32 addrspace(272)* %i) {
215; ALL-LABEL: test_load_ptr64:
216; ALL:       # %bb.0: # %entry
217; ALL-NEXT:    movl (%rcx), %eax
218; ALL-NEXT:    retq
219entry:
220  %0 = load i32, i32 addrspace(272)* %i, align 8
221  ret i32 %0
222}
223
224define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) {
225; ALL-LABEL: test_store_sptr32:
226; ALL:       # %bb.0: # %entry
227; ALL-NEXT:    movslq %ecx, %rax
228; ALL-NEXT:    movl %edx, (%rax)
229; ALL-NEXT:    retq
230entry:
231  store i32 %i, i32 addrspace(270)* %s, align 4
232  ret void
233}
234
235define void @test_store_uptr32(i32 addrspace(271)* %s, i32 %i) {
236; CHECK-LABEL: test_store_uptr32:
237; CHECK:       # %bb.0: # %entry
238; CHECK-NEXT:    movl %ecx, %eax
239; CHECK-NEXT:    movl %edx, (%rax)
240; CHECK-NEXT:    retq
241;
242; CHECK-O0-LABEL: test_store_uptr32:
243; CHECK-O0:       # %bb.0: # %entry
244; CHECK-O0-NEXT:    movl %ecx, %eax
245; CHECK-O0-NEXT:    # kill: def $rax killed $eax
246; CHECK-O0-NEXT:    movl %edx, (%rax)
247; CHECK-O0-NEXT:    retq
248entry:
249  store i32 %i, i32 addrspace(271)* %s, align 4
250  ret void
251}
252
253define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) {
254; ALL-LABEL: test_store_ptr64:
255; ALL:       # %bb.0: # %entry
256; ALL-NEXT:    movl %edx, (%rcx)
257; ALL-NEXT:    retq
258entry:
259  store i32 %i, i32 addrspace(272)* %s, align 8
260  ret void
261}
262