Skip to content

Commit

Permalink
Extend or truncate __ptr32/__ptr64 pointers when dereferenced.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
amykhuang committed Jun 26, 2020
1 parent 903cf14 commit 8b59c26
Show file tree
Hide file tree
Showing 3 changed files with 247 additions and 0 deletions.
28 changes: 28 additions & 0 deletions llvm/lib/Target/X86/X86ISelLowering.cpp
Expand Up @@ -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();
}

Expand Down Expand Up @@ -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
Expand Down
108 changes: 108 additions & 0 deletions llvm/test/CodeGen/X86/mixed-ptr-sizes-i686.ll
Expand Up @@ -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
}
111 changes: 111 additions & 0 deletions llvm/test/CodeGen/X86/mixed-ptr-sizes.ll
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

0 comments on commit 8b59c26

Please sign in to comment.