From 8b59c26bf347be5d96487c89849c0c1108bb3c42 Mon Sep 17 00:00:00 2001 From: Amy Huang Date: Mon, 11 May 2020 14:13:37 -0700 Subject: [PATCH] Extend or truncate __ptr32/__ptr64 pointers when dereferenced. Summary: A while ago I implemented the functionality to lower Microsoft __ptr32 and __ptr64 pointers, which are stored as 32-bit and 64-bit pointer and are extended/truncated to the appropriate pointer size when dereferenced. This patch adds an addrspacecast to cast from the __ptr32/__ptr64 pointer to a default address space when dereferencing. Bug: https://bugs.llvm.org/show_bug.cgi?id=42359 Reviewers: hans, arsenm, RKSimon Subscribers: wdng, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D81517 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 28 +++++++ llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll | 108 +++++++++++++++++++++++++ llvm/test/CodeGen/X86/mixed-ptr-sizes.ll | 111 ++++++++++++++++++++++++++ 3 files changed, 247 insertions(+) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index c3e8985..54cbacc 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -43443,6 +43443,20 @@ static SDValue combineLoad(SDNode *N, SelectionDAG &DAG, } } + // 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(); } @@ -43870,6 +43884,20 @@ static SDValue combineStore(SDNode *N, SelectionDAG &DAG, 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 index 8b92376..14a233e 100644 --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll @@ -236,3 +236,111 @@ entry: 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 index 7a470fb..ac55e1a 100644 --- a/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll +++ b/llvm/test/CodeGen/X86/mixed-ptr-sizes.ll @@ -125,6 +125,23 @@ entry: ; 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 @@ entry: 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 +} -- 2.7.4