xref: /llvm-project/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll (revision 255f826d6f656bad17cc0aeacbd20306c266f653)
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 { ptr addrspace(270), ptr, ptr addrspace(9) }
46declare dso_local void @use_foo(ptr)
47
48define 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
54entry:
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)
59  ret void
60}
61
62define 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
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 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)
80  ret void
81}
82
83define 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
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 ptr %i to ptr addrspace(270)
96  store ptr addrspace(270) %0, ptr %f, align 8
97  tail call void @use_foo(ptr %f)
98  ret void
99}
100
101define 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
106entry:
107  store ptr addrspace(270) %i, ptr %f, align 8
108  tail call void @use_foo(ptr %f)
109  ret void
110}
111
112define 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
117entry:
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)
121  ret void
122}
123
124; Test that null can be passed as a 32-bit pointer.
125define 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
133; ALL-NEXT:    nop
134; ALL-NEXT:    addq $40, %rsp
135; ALL-NEXT:    retq
136; ALL-NEXT:    .seh_endproc
137entry:
138  call void @test_noop1(ptr %f, ptr addrspace(270) null)
139  ret void
140}
141
142; Test casts between unrecognized address spaces.
143define 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
148;
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
154entry:
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)
158  ret void
159}
160
161define 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
167;
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
174entry:
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)
179  ret void
180}
181
182define 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
187; ALL-NEXT:    retq
188entry:
189  %0 = load i32, ptr addrspace(270) %i, align 4
190  ret i32 %0
191}
192
193define 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
198; CHECK-NEXT:    retq
199;
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
206entry:
207  %0 = load i32, ptr addrspace(271) %i, align 4
208  ret i32 %0
209}
210
211define 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
215; ALL-NEXT:    retq
216entry:
217  %0 = load i32, ptr addrspace(272) %i, align 8
218  ret i32 %0
219}
220
221define 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)
226; ALL-NEXT:    retq
227entry:
228  store i32 %i, ptr addrspace(270) %s, align 4
229  ret void
230}
231
232define 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)
237; CHECK-NEXT:    retq
238;
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
245entry:
246  store i32 %i, ptr addrspace(271) %s, align 4
247  ret void
248}
249
250define 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)
254; ALL-NEXT:    retq
255entry:
256  store i32 %i, ptr addrspace(272) %s, align 8
257  ret void
258}
259
260define 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
265; CHECK-NEXT:    retq
266;
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
274entry:
275  %0 = load i32, ptr addrspace(270) %i, align 4
276  %1 = zext i32 %0 to i64
277  ret i64 %1
278}
279
280define 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)
286; CHECK-NEXT:    retq
287;
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
295entry:
296  %0 = trunc i32 %i to i1
297  store i1 %0, ptr addrspace(270) %s
298  ret void
299}
300