; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s | FileCheck %s --check-prefixes=ALL,CHECK ; RUN: llc -O0 < %s | FileCheck %s --check-prefixes=ALL,CHECK-O0 ; Source to regenerate: ; struct Foo { ; int * __ptr32 p32; ; int * __ptr64 p64; ; __attribute__((address_space(9))) int *p_other; ; }; ; void use_foo(Foo *f); ; void test_sign_ext(Foo *f, int * __ptr32 __sptr i) { ; f->p64 = i; ; use_foo(f); ; } ; void test_zero_ext(Foo *f, int * __ptr32 __uptr i) { ; f->p64 = i; ; use_foo(f); ; } ; void test_trunc(Foo *f, int * __ptr64 i) { ; f->p32 = i; ; use_foo(f); ; } ; void test_noop1(Foo *f, int * __ptr32 i) { ; f->p32 = i; ; use_foo(f); ; } ; void test_noop2(Foo *f, int * __ptr64 i) { ; f->p64 = i; ; use_foo(f); ; } ; void test_null_arg(Foo *f, int * __ptr32 i) { ; test_noop1(f, 0); ; } ; void test_unrecognized(Foo *f, __attribute__((address_space(14))) int *i) { ; f->p32 = (int * __ptr32)i; ; use_foo(f); ; } ; ; $ clang -cc1 -triple x86_64-windows-msvc -fms-extensions -O2 -S t.cpp target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-windows-msvc" %struct.Foo = type { ptr addrspace(270), ptr, ptr addrspace(9) } declare dso_local void @use_foo(ptr) define dso_local void @test_sign_ext(ptr %f, ptr addrspace(270) %i) { ; ALL-LABEL: test_sign_ext: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movslq %edx, %rax ; ALL-NEXT: movq %rax, 8(%rcx) ; ALL-NEXT: jmp use_foo # TAILCALL entry: %0 = addrspacecast ptr addrspace(270) %i to ptr %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 store ptr %0, ptr %p64, align 8 tail call void @use_foo(ptr %f) ret void } define dso_local void @test_zero_ext(ptr %f, ptr addrspace(271) %i) { ; CHECK-LABEL: test_zero_ext: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: movq %rax, 8(%rcx) ; CHECK-NEXT: jmp use_foo # TAILCALL ; ; CHECK-O0-LABEL: test_zero_ext: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %edx, %eax ; CHECK-O0-NEXT: # kill: def $rax killed $eax ; CHECK-O0-NEXT: movq %rax, 8(%rcx) ; CHECK-O0-NEXT: jmp use_foo # TAILCALL entry: %0 = addrspacecast ptr addrspace(271) %i to ptr %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 store ptr %0, ptr %p64, align 8 tail call void @use_foo(ptr %f) ret void } define dso_local void @test_trunc(ptr %f, ptr %i) { ; CHECK-LABEL: test_trunc: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %edx, (%rcx) ; CHECK-NEXT: jmp use_foo # TAILCALL ; ; CHECK-O0-LABEL: test_trunc: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %edx, %eax ; CHECK-O0-NEXT: movl %eax, (%rcx) ; CHECK-O0-NEXT: jmp use_foo # TAILCALL entry: %0 = addrspacecast ptr %i to ptr addrspace(270) store ptr addrspace(270) %0, ptr %f, align 8 tail call void @use_foo(ptr %f) ret void } define dso_local void @test_noop1(ptr %f, ptr addrspace(270) %i) { ; ALL-LABEL: test_noop1: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movl %edx, (%rcx) ; ALL-NEXT: jmp use_foo # TAILCALL entry: store ptr addrspace(270) %i, ptr %f, align 8 tail call void @use_foo(ptr %f) ret void } define dso_local void @test_noop2(ptr %f, ptr %i) { ; ALL-LABEL: test_noop2: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movq %rdx, 8(%rcx) ; ALL-NEXT: jmp use_foo # TAILCALL entry: %p64 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 1 store ptr %i, ptr %p64, align 8 tail call void @use_foo(ptr %f) ret void } ; Test that null can be passed as a 32-bit pointer. define dso_local void @test_null_arg(ptr %f) { ; ALL-LABEL: test_null_arg: ; ALL: # %bb.0: # %entry ; ALL-NEXT: subq $40, %rsp ; ALL-NEXT: .seh_stackalloc 40 ; ALL-NEXT: .seh_endprologue ; ALL-NEXT: xorl %edx, %edx ; ALL-NEXT: callq test_noop1 ; ALL-NEXT: nop ; ALL-NEXT: addq $40, %rsp ; ALL-NEXT: retq ; ALL-NEXT: .seh_endproc entry: call void @test_noop1(ptr %f, ptr addrspace(270) null) ret void } ; Test casts between unrecognized address spaces. define void @test_unrecognized(ptr %f, ptr addrspace(14) %i) { ; CHECK-LABEL: test_unrecognized: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %edx, (%rcx) ; CHECK-NEXT: jmp use_foo # TAILCALL ; ; CHECK-O0-LABEL: test_unrecognized: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %edx, %eax ; CHECK-O0-NEXT: movl %eax, (%rcx) ; CHECK-O0-NEXT: jmp use_foo # TAILCALL entry: %0 = addrspacecast ptr addrspace(14) %i to ptr addrspace(270) store ptr addrspace(270) %0, ptr %f, align 8 tail call void @use_foo(ptr %f) ret void } define void @test_unrecognized2(ptr %f, ptr addrspace(271) %i) { ; CHECK-LABEL: test_unrecognized2: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %edx, %eax ; CHECK-NEXT: movq %rax, 16(%rcx) ; CHECK-NEXT: jmp use_foo # TAILCALL ; ; CHECK-O0-LABEL: test_unrecognized2: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %edx, %eax ; CHECK-O0-NEXT: # kill: def $rax killed $eax ; CHECK-O0-NEXT: movq %rax, 16(%rcx) ; CHECK-O0-NEXT: jmp use_foo # TAILCALL entry: %0 = addrspacecast ptr addrspace(271) %i to ptr addrspace(9) %p32 = getelementptr inbounds %struct.Foo, ptr %f, i64 0, i32 2 store ptr addrspace(9) %0, ptr %p32, align 8 tail call void @use_foo(ptr %f) ret void } define i32 @test_load_sptr32(ptr addrspace(270) %i) { ; ALL-LABEL: test_load_sptr32: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movslq %ecx, %rax ; ALL-NEXT: movl (%rax), %eax ; ALL-NEXT: retq entry: %0 = load i32, ptr addrspace(270) %i, align 4 ret i32 %0 } define i32 @test_load_uptr32(ptr addrspace(271) %i) { ; CHECK-LABEL: test_load_uptr32: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: movl (%rax), %eax ; CHECK-NEXT: retq ; ; CHECK-O0-LABEL: test_load_uptr32: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %ecx, %eax ; CHECK-O0-NEXT: # kill: def $rax killed $eax ; CHECK-O0-NEXT: movl (%rax), %eax ; CHECK-O0-NEXT: retq entry: %0 = load i32, ptr addrspace(271) %i, align 4 ret i32 %0 } define i32 @test_load_ptr64(ptr addrspace(272) %i) { ; ALL-LABEL: test_load_ptr64: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movl (%rcx), %eax ; ALL-NEXT: retq entry: %0 = load i32, ptr addrspace(272) %i, align 8 ret i32 %0 } define void @test_store_sptr32(ptr addrspace(270) %s, i32 %i) { ; ALL-LABEL: test_store_sptr32: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movslq %ecx, %rax ; ALL-NEXT: movl %edx, (%rax) ; ALL-NEXT: retq entry: store i32 %i, ptr addrspace(270) %s, align 4 ret void } define void @test_store_uptr32(ptr addrspace(271) %s, i32 %i) { ; CHECK-LABEL: test_store_uptr32: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movl %ecx, %eax ; CHECK-NEXT: movl %edx, (%rax) ; CHECK-NEXT: retq ; ; CHECK-O0-LABEL: test_store_uptr32: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movl %ecx, %eax ; CHECK-O0-NEXT: # kill: def $rax killed $eax ; CHECK-O0-NEXT: movl %edx, (%rax) ; CHECK-O0-NEXT: retq entry: store i32 %i, ptr addrspace(271) %s, align 4 ret void } define void @test_store_ptr64(ptr addrspace(272) %s, i32 %i) { ; ALL-LABEL: test_store_ptr64: ; ALL: # %bb.0: # %entry ; ALL-NEXT: movl %edx, (%rcx) ; ALL-NEXT: retq entry: store i32 %i, ptr addrspace(272) %s, align 8 ret void } define i64 @test_load_sptr32_zext_i64(ptr addrspace(270) %i) { ; CHECK-LABEL: test_load_sptr32_zext_i64: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movslq %ecx, %rax ; CHECK-NEXT: movl (%rax), %eax ; CHECK-NEXT: retq ; ; CHECK-O0-LABEL: test_load_sptr32_zext_i64: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movslq %ecx, %rax ; CHECK-O0-NEXT: movl (%rax), %eax ; CHECK-O0-NEXT: movl %eax, %eax ; CHECK-O0-NEXT: # kill: def $rax killed $eax ; CHECK-O0-NEXT: retq entry: %0 = load i32, ptr addrspace(270) %i, align 4 %1 = zext i32 %0 to i64 ret i64 %1 } define void @test_store_sptr32_trunc_i1(ptr addrspace(270) %s, i32 %i) { ; CHECK-LABEL: test_store_sptr32_trunc_i1: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: movslq %ecx, %rax ; CHECK-NEXT: andl $1, %edx ; CHECK-NEXT: movb %dl, (%rax) ; CHECK-NEXT: retq ; ; CHECK-O0-LABEL: test_store_sptr32_trunc_i1: ; CHECK-O0: # %bb.0: # %entry ; CHECK-O0-NEXT: movslq %ecx, %rax ; CHECK-O0-NEXT: andl $1, %edx ; CHECK-O0-NEXT: movb %dl, %cl ; CHECK-O0-NEXT: movb %cl, (%rax) ; CHECK-O0-NEXT: retq entry: %0 = trunc i32 %i to i1 store i1 %0, ptr addrspace(270) %s ret void }