| ; 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 { i32 addrspace(270)*, i32*, i32 addrspace(9)* } |
| declare dso_local void @use_foo(%struct.Foo*) |
| |
| define dso_local void @test_sign_ext(%struct.Foo* %f, i32 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 i32 addrspace(270)* %i to i32* |
| %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1 |
| store i32* %0, i32** %p64, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define dso_local void @test_zero_ext(%struct.Foo* %f, i32 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 i32 addrspace(271)* %i to i32* |
| %p64 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 1 |
| store i32* %0, i32** %p64, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define dso_local void @test_trunc(%struct.Foo* %f, i32* %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 i32* %i to i32 addrspace(270)* |
| %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 |
| store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define dso_local void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* %i) { |
| ; ALL-LABEL: test_noop1: |
| ; ALL: # %bb.0: # %entry |
| ; ALL-NEXT: movl %edx, (%rcx) |
| ; ALL-NEXT: jmp use_foo # TAILCALL |
| entry: |
| %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 |
| store i32 addrspace(270)* %i, i32 addrspace(270)** %p32, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define dso_local void @test_noop2(%struct.Foo* %f, i32* %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, %struct.Foo* %f, i64 0, i32 1 |
| store i32* %i, i32** %p64, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| ; Test that null can be passed as a 32-bit pointer. |
| define dso_local void @test_null_arg(%struct.Foo* %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(%struct.Foo* %f, i32 addrspace(270)* null) |
| ret void |
| } |
| |
| ; Test casts between unrecognized address spaces. |
| define void @test_unrecognized(%struct.Foo* %f, i32 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 i32 addrspace(14)* %i to i32 addrspace(270)* |
| %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 0 |
| store i32 addrspace(270)* %0, i32 addrspace(270)** %p32, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define void @test_unrecognized2(%struct.Foo* %f, i32 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 i32 addrspace(271)* %i to i32 addrspace(9)* |
| %p32 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i64 0, i32 2 |
| store i32 addrspace(9)* %0, i32 addrspace(9)** %p32, align 8 |
| tail call void @use_foo(%struct.Foo* %f) |
| ret void |
| } |
| |
| define i32 @test_load_sptr32(i32 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, i32 addrspace(270)* %i, align 4 |
| ret i32 %0 |
| } |
| |
| define i32 @test_load_uptr32(i32 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, i32 addrspace(271)* %i, align 4 |
| ret i32 %0 |
| } |
| |
| define i32 @test_load_ptr64(i32 addrspace(272)* %i) { |
| ; ALL-LABEL: test_load_ptr64: |
| ; ALL: # %bb.0: # %entry |
| ; ALL-NEXT: movl (%rcx), %eax |
| ; ALL-NEXT: retq |
| entry: |
| %0 = load i32, i32 addrspace(272)* %i, align 8 |
| ret i32 %0 |
| } |
| |
| define void @test_store_sptr32(i32 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, i32 addrspace(270)* %s, align 4 |
| ret void |
| } |
| |
| define void @test_store_uptr32(i32 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, i32 addrspace(271)* %s, align 4 |
| ret void |
| } |
| |
| define void @test_store_ptr64(i32 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, i32 addrspace(272)* %s, align 8 |
| ret void |
| } |