[TTI] getTypeBasedIntrinsicInstrCost - add basic handling for strided load/store...
[llvm-project.git] / llvm / test / CodeGen / X86 / mixed-ptr-sizes.ll
blob48d0ea49b70e67541aa7ed1f39f66c6fcf86336a
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 ; RUN: llc --fast-isel < %s | FileCheck %s --check-prefixes=ALL,CHECK
5 ; RUN: llc --global-isel --global-isel-abort=2 < %s | FileCheck %s --check-prefixes=ALL,CHECK
7 ; Source to regenerate:
8 ; struct Foo {
9 ;   int * __ptr32 p32;
10 ;   int * __ptr64 p64;
11 ;   __attribute__((address_space(9))) int *p_other;
12 ; };
13 ; void use_foo(Foo *f);
14 ; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) {
15 ;   f->p64 = i;
16 ;   use_foo(f);
17 ; }
18 ; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) {
19 ;   f->p64 = i;
20 ;   use_foo(f);
21 ; }
22 ; void test_trunc(Foo *f, int * __ptr64 i) {
23 ;   f->p32 = i;
24 ;   use_foo(f);
25 ; }
26 ; void test_noop1(Foo *f, int * __ptr32 i) {
27 ;   f->p32 = i;
28 ;   use_foo(f);
29 ; }
30 ; void test_noop2(Foo *f, int * __ptr64 i) {
31 ;   f->p64 = i;
32 ;   use_foo(f);
33 ; }
34 ; void test_null_arg(Foo *f, int * __ptr32 i) {
35 ;   test_noop1(f, 0);
36 ; }
37 ; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) {
38 ;   f->p32 = (int * __ptr32)i;
39 ;   use_foo(f);
40 ; }
42 ; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp
44 target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
45 target triple = "x86_64-unknown-windows-msvc"
47 %struct.Foo = type { ptr addrspace(270), ptr, ptr addrspace(9) }
48 declare dso_local void @use_foo(ptr)
50 define dso_local void @test_sign_ext(ptr %f, ptr addrspace(270) %i) {
51 ; ALL-LABEL: test_sign_ext:
52 ; ALL:       # %bb.0: # %entry
53 ; ALL-NEXT:    movslq %edx, %rax
54 ; ALL-NEXT:    movq %rax, 8(%rcx)
55 ; ALL-NEXT:    jmp use_foo # TAILCALL
56 entry:
57   %0 = addrspacecast ptr addrspace(270) %i to ptr
58   %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
59   store ptr %0, ptr %p64, align 8
60   tail call void @use_foo(ptr %f)
61   ret void
64 define dso_local void @test_zero_ext(ptr %f, ptr addrspace(271) %i) {
65 ; CHECK-LABEL: test_zero_ext:
66 ; CHECK:       # %bb.0: # %entry
67 ; CHECK-NEXT:    movl %edx, %eax
68 ; CHECK-NEXT:    movq %rax, 8(%rcx)
69 ; CHECK-NEXT:    jmp use_foo # TAILCALL
71 ; CHECK-O0-LABEL: test_zero_ext:
72 ; CHECK-O0:       # %bb.0: # %entry
73 ; CHECK-O0-NEXT:    movl %edx, %eax
74 ; CHECK-O0-NEXT:    # kill: def $rax killed $eax
75 ; CHECK-O0-NEXT:    movq %rax, 8(%rcx)
76 ; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
77 entry:
78   %0 = addrspacecast ptr addrspace(271) %i to ptr
79   %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
80   store ptr %0, ptr %p64, align 8
81   tail call void @use_foo(ptr %f)
82   ret void
85 define dso_local void @test_trunc(ptr %f, ptr %i) {
86 ; CHECK-LABEL: test_trunc:
87 ; CHECK:       # %bb.0: # %entry
88 ; CHECK-NEXT:    movl %edx, (%rcx)
89 ; CHECK-NEXT:    jmp use_foo # TAILCALL
91 ; CHECK-O0-LABEL: test_trunc:
92 ; CHECK-O0:       # %bb.0: # %entry
93 ; CHECK-O0-NEXT:    movl %edx, %eax
94 ; CHECK-O0-NEXT:    movl %eax, (%rcx)
95 ; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
96 entry:
97   %0 = addrspacecast ptr %i to ptr addrspace(270)
98   store ptr addrspace(270) %0, ptr %f, align 8
99   tail call void @use_foo(ptr %f)
100   ret void
103 define dso_local void @test_noop1(ptr %f, ptr addrspace(270) %i) {
104 ; ALL-LABEL: test_noop1:
105 ; ALL:       # %bb.0: # %entry
106 ; ALL-NEXT:    movl %edx, (%rcx)
107 ; ALL-NEXT:    jmp use_foo # TAILCALL
108 entry:
109   store ptr addrspace(270) %i, ptr %f, align 8
110   tail call void @use_foo(ptr %f)
111   ret void
114 define dso_local void @test_noop2(ptr %f, ptr %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
119 entry:
120   %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1
121   store ptr %i, ptr %p64, align 8
122   tail call void @use_foo(ptr %f)
123   ret void
126 ; Test that null can be passed as a 32-bit pointer.
127 define dso_local void @test_null_arg(ptr %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:    .seh_startepilogue
137 ; ALL-NEXT:    addq $40, %rsp
138 ; ALL-NEXT:    .seh_endepilogue
139 ; ALL-NEXT:    retq
140 ; ALL-NEXT:    .seh_endproc
141 entry:
142   call void @test_noop1(ptr %f, ptr addrspace(270) null)
143   ret void
146 ; Test casts between unrecognized address spaces.
147 define void @test_unrecognized(ptr %f, ptr addrspace(14) %i) {
148 ; CHECK-LABEL: test_unrecognized:
149 ; CHECK:       # %bb.0: # %entry
150 ; CHECK-NEXT:    movl %edx, (%rcx)
151 ; CHECK-NEXT:    jmp use_foo # TAILCALL
153 ; CHECK-O0-LABEL: test_unrecognized:
154 ; CHECK-O0:       # %bb.0: # %entry
155 ; CHECK-O0-NEXT:    movl %edx, %eax
156 ; CHECK-O0-NEXT:    movl %eax, (%rcx)
157 ; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
158 entry:
159   %0 = addrspacecast ptr addrspace(14) %i to ptr addrspace(270)
160   store ptr addrspace(270) %0, ptr %f, align 8
161   tail call void @use_foo(ptr %f)
162   ret void
165 define void @test_unrecognized2(ptr %f, ptr addrspace(271) %i) {
166 ; CHECK-LABEL: test_unrecognized2:
167 ; CHECK:       # %bb.0: # %entry
168 ; CHECK-NEXT:    movl %edx, %eax
169 ; CHECK-NEXT:    movq %rax, 16(%rcx)
170 ; CHECK-NEXT:    jmp use_foo # TAILCALL
172 ; CHECK-O0-LABEL: test_unrecognized2:
173 ; CHECK-O0:       # %bb.0: # %entry
174 ; CHECK-O0-NEXT:    movl %edx, %eax
175 ; CHECK-O0-NEXT:    # kill: def $rax killed $eax
176 ; CHECK-O0-NEXT:    movq %rax, 16(%rcx)
177 ; CHECK-O0-NEXT:    jmp use_foo # TAILCALL
178 entry:
179   %0 = addrspacecast ptr addrspace(271) %i to ptr addrspace(9)
180   %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2
181   store ptr addrspace(9) %0, ptr %p32, align 8
182   tail call void @use_foo(ptr %f)
183   ret void
186 define i32 @test_load_sptr32(ptr addrspace(270) %i) {
187 ; ALL-LABEL: test_load_sptr32:
188 ; ALL:       # %bb.0: # %entry
189 ; ALL-NEXT:    movslq %ecx, %rax
190 ; ALL-NEXT:    movl (%rax), %eax
191 ; ALL-NEXT:    retq
192 entry:
193   %0 = load i32, ptr addrspace(270) %i, align 4
194   ret i32 %0
197 define i32 @test_load_uptr32(ptr addrspace(271) %i) {
198 ; CHECK-LABEL: test_load_uptr32:
199 ; CHECK:       # %bb.0: # %entry
200 ; CHECK-NEXT:    movl %ecx, %eax
201 ; CHECK-NEXT:    movl (%rax), %eax
202 ; CHECK-NEXT:    retq
204 ; CHECK-O0-LABEL: test_load_uptr32:
205 ; CHECK-O0:       # %bb.0: # %entry
206 ; CHECK-O0-NEXT:    movl %ecx, %eax
207 ; CHECK-O0-NEXT:    # kill: def $rax killed $eax
208 ; CHECK-O0-NEXT:    movl (%rax), %eax
209 ; CHECK-O0-NEXT:    retq
210 entry:
211   %0 = load i32, ptr addrspace(271) %i, align 4
212   ret i32 %0
215 define i32 @test_load_ptr64(ptr addrspace(272) %i) {
216 ; ALL-LABEL: test_load_ptr64:
217 ; ALL:       # %bb.0: # %entry
218 ; ALL-NEXT:    movl (%rcx), %eax
219 ; ALL-NEXT:    retq
220 entry:
221   %0 = load i32, ptr addrspace(272) %i, align 8
222   ret i32 %0
225 define void @test_store_sptr32(ptr addrspace(270) %s, i32 %i) {
226 ; ALL-LABEL: test_store_sptr32:
227 ; ALL:       # %bb.0: # %entry
228 ; ALL-NEXT:    movslq %ecx, %rax
229 ; ALL-NEXT:    movl %edx, (%rax)
230 ; ALL-NEXT:    retq
231 entry:
232   store i32 %i, ptr addrspace(270) %s, align 4
233   ret void
236 define void @test_store_uptr32(ptr addrspace(271) %s, i32 %i) {
237 ; CHECK-LABEL: test_store_uptr32:
238 ; CHECK:       # %bb.0: # %entry
239 ; CHECK-NEXT:    movl %ecx, %eax
240 ; CHECK-NEXT:    movl %edx, (%rax)
241 ; CHECK-NEXT:    retq
243 ; CHECK-O0-LABEL: test_store_uptr32:
244 ; CHECK-O0:       # %bb.0: # %entry
245 ; CHECK-O0-NEXT:    movl %ecx, %eax
246 ; CHECK-O0-NEXT:    # kill: def $rax killed $eax
247 ; CHECK-O0-NEXT:    movl %edx, (%rax)
248 ; CHECK-O0-NEXT:    retq
249 entry:
250   store i32 %i, ptr addrspace(271) %s, align 4
251   ret void
254 define void @test_store_ptr64(ptr addrspace(272) %s, i32 %i) {
255 ; ALL-LABEL: test_store_ptr64:
256 ; ALL:       # %bb.0: # %entry
257 ; ALL-NEXT:    movl %edx, (%rcx)
258 ; ALL-NEXT:    retq
259 entry:
260   store i32 %i, ptr addrspace(272) %s, align 8
261   ret void
264 define i64 @test_load_sptr32_zext_i64(ptr addrspace(270) %i) {
265 ; CHECK-LABEL: test_load_sptr32_zext_i64:
266 ; CHECK:       # %bb.0: # %entry
267 ; CHECK-NEXT:    movslq %ecx, %rax
268 ; CHECK-NEXT:    movl (%rax), %eax
269 ; CHECK-NEXT:    retq
271 ; CHECK-O0-LABEL: test_load_sptr32_zext_i64:
272 ; CHECK-O0:       # %bb.0: # %entry
273 ; CHECK-O0-NEXT:    movslq %ecx, %rax
274 ; CHECK-O0-NEXT:    movl (%rax), %eax
275 ; CHECK-O0-NEXT:    movl %eax, %eax
276 ; CHECK-O0-NEXT:    # kill: def $rax killed $eax
277 ; CHECK-O0-NEXT:    retq
278 entry:
279   %0 = load i32, ptr addrspace(270) %i, align 4
280   %1 = zext i32 %0 to i64
281   ret i64 %1
284 define void @test_store_sptr32_trunc_i1(ptr addrspace(270) %s, i32 %i) {
285 ; CHECK-LABEL: test_store_sptr32_trunc_i1:
286 ; CHECK:       # %bb.0: # %entry
287 ; CHECK-NEXT:    movslq %ecx, %rax
288 ; CHECK-NEXT:    andl $1, %edx
289 ; CHECK-NEXT:    movb %dl, (%rax)
290 ; CHECK-NEXT:    retq
292 ; CHECK-O0-LABEL: test_store_sptr32_trunc_i1:
293 ; CHECK-O0:       # %bb.0: # %entry
294 ; CHECK-O0-NEXT:    movslq %ecx, %rax
295 ; CHECK-O0-NEXT:    andl $1, %edx
296 ; CHECK-O0-NEXT:    movb %dl, %cl
297 ; CHECK-O0-NEXT:    movb %cl, (%rax)
298 ; CHECK-O0-NEXT:    retq
299 entry:
300   %0 = trunc i32 %i to i1
301   store i1 %0, ptr addrspace(270) %s
302   ret void