diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -43450,6 +43450,20 @@ } } + // Cast ptr32 and ptr64 pointers to the default address space before a load. + unsigned AddrSpace = Ld->getAddressSpace(); + if (AddrSpace == X86AS::PTR64 || AddrSpace == X86AS::PTR32_SPTR || + AddrSpace == X86AS::PTR32_UPTR) { + MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); + if (PtrVT != Ld->getBasePtr().getSimpleValueType()) { + SDValue Cast = + DAG.getAddrSpaceCast(dl, PtrVT, Ld->getBasePtr(), AddrSpace, 0); + return DAG.getLoad(RegVT, dl, Ld->getChain(), Cast, Ld->getPointerInfo(), + Ld->getOriginalAlign(), + Ld->getMemOperand()->getFlags()); + } + } + return SDValue(); } @@ -43877,6 +43891,20 @@ return SDValue(); } + // Cast ptr32 and ptr64 pointers to the default address space before a store. + unsigned AddrSpace = St->getAddressSpace(); + if (AddrSpace == X86AS::PTR64 || AddrSpace == X86AS::PTR32_SPTR || + AddrSpace == X86AS::PTR32_UPTR) { + MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); + if (PtrVT != St->getBasePtr().getSimpleValueType()) { + SDValue Cast = + DAG.getAddrSpaceCast(dl, PtrVT, St->getBasePtr(), AddrSpace, 0); + return DAG.getStore(St->getChain(), dl, StoredVal, Cast, + St->getPointerInfo(), St->getOriginalAlign(), + St->getMemOperand()->getFlags(), St->getAAInfo()); + } + } + // Turn load->store of MMX types into GPR load/stores. This avoids clobbering // the FP state in cases where an emms may be missing. // A preferable solution to the general problem is to figure out the right diff --git a/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll b/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll @@ -236,3 +236,111 @@ tail call void @use_foo(%struct.Foo* %f) ret void } + +define i32 @test_load_sptr32(i32 addrspace(270)* %i) { +; CHECK-LABEL: test_load_sptr32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl (%eax), %eax +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_load_sptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl (%eax), %eax +; CHECK-O0-NEXT: retl +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 {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl (%eax), %eax +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_load_uptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl (%eax), %eax +; CHECK-O0-NEXT: retl +entry: + %0 = load i32, i32 addrspace(271)* %i, align 4 + ret i32 %0 +} + +define i32 @test_load_ptr64(i32 addrspace(272)* %i) { +; CHECK-LABEL: test_load_ptr64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl (%eax), %eax +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_load_ptr64: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: pushl %eax +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-O0-NEXT: movl (%ecx), %ecx +; CHECK-O0-NEXT: movl %eax, (%esp) +; CHECK-O0-NEXT: movl %ecx, %eax +; CHECK-O0-NEXT: popl %ecx +; CHECK-O0-NEXT: retl +entry: + %0 = load i32, i32 addrspace(272)* %i, align 8 + ret i32 %0 +} + +define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) { +; CHECK-LABEL: test_store_sptr32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-NEXT: movl %eax, (%ecx) +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_store_sptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-O0-NEXT: movl %eax, (%ecx) +; CHECK-O0-NEXT: retl +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 {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-NEXT: movl %eax, (%ecx) +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_store_uptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-O0-NEXT: movl %eax, (%ecx) +; CHECK-O0-NEXT: retl +entry: + store i32 %i, i32 addrspace(271)* %s, align 4 + ret void +} + +define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) { +; CHECK-LABEL: test_store_ptr64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-NEXT: movl %eax, (%ecx) +; CHECK-NEXT: retl +; CHECK-O0-LABEL: test_store_ptr64: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %eax +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %ecx +; CHECK-O0-NEXT: movl {{[0-9]+}}(%esp), %edx +; CHECK-O0-NEXT: movl %edx, (%ecx) +; CHECK-O0-NEXT: retl +entry: + store i32 %i, i32 addrspace(272)* %s, align 8 + ret void +} diff --git a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll @@ -125,6 +125,23 @@ ; Test that null can be passed as a 32-bit pointer. define dso_local void @test_null_arg(%struct.Foo* %f) { +; CHECK-LABEL: test_null_arg: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: subq $40, %rsp +; CHECK: xorl %edx, %edx +; CHECK-NEXT: callq test_noop1 +; CHECK-NEXT: nop +; CHECK-NEXT: addq $40, %rsp +; CHECK-NEXT: retq +; +; CHECK-O0-LABEL: test_null_arg: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: subq $40, %rsp +; CHECK-O0: xorl %edx, %edx +; CHECK-O0-NEXT: callq test_noop1 +; CHECK-O0-NEXT: nop +; CHECK-O0-NEXT: addq $40, %rsp +; CHECK-O0-NEXT: retq entry: call void @test_noop1(%struct.Foo* %f, i32 addrspace(270)* null) ret void @@ -170,3 +187,97 @@ tail call void @use_foo(%struct.Foo* %f) ret void } + +define i32 @test_load_sptr32(i32 addrspace(270)* %i) { +; CHECK-LABEL: test_load_sptr32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movslq %ecx, %rax +; CHECK-NEXT: movl (%rax), %eax +; CHECK-NEXT: retq +; CHECK-O0-LABEL: test_load_sptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movslq %ecx, %rax +; CHECK-O0-NEXT: movl (%rax), %eax +; CHECK-O0-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) { +; CHECK-LABEL: test_load_ptr64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl (%rcx), %eax +; CHECK-NEXT: retq +; CHECK-O0-LABEL: test_load_ptr64: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl (%rcx), %eax +; CHECK-O0-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) { +; CHECK-LABEL: test_store_sptr32: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movslq %ecx, %rax +; CHECK-NEXT: movl %edx, (%rax) +; CHECK-NEXT: retq +; CHECK-O0-LABEL: test_store_sptr32: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movslq %ecx, %rax +; CHECK-O0-NEXT: movl %edx, (%rax) +; CHECK-O0-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) { +; CHECK-LABEL: test_store_ptr64: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: movl %edx, (%rcx) +; CHECK-NEXT: retq +; CHECK-O0-LABEL: test_store_ptr64: +; CHECK-O0: # %bb.0: # %entry +; CHECK-O0-NEXT: movl %edx, (%rcx) +; CHECK-O0-NEXT: retq +entry: + store i32 %i, i32 addrspace(272)* %s, align 8 + ret void +}