diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2455,15 +2455,28 @@ Parent->getOpcode() != X86ISD::ENQCMDS && // Fixme Parent->getOpcode() != X86ISD::EH_SJLJ_SETJMP && // setjmp Parent->getOpcode() != X86ISD::EH_SJLJ_LONGJMP) { // longjmp + unsigned AddrSpace = cast(Parent)->getPointerInfo().getAddrSpace(); - // AddrSpace 256 -> GS, 257 -> FS, 258 -> SS. - if (AddrSpace == 256) + if (AddrSpace == X86AS::GS) AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16); - if (AddrSpace == 257) + if (AddrSpace == X86AS::FS) AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16); - if (AddrSpace == 258) + if (AddrSpace == X86AS::SS) AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16); + + // If loading from a ptr32 address space, add a sign or zero extend. + if (AddrSpace == X86AS::PTR32_SPTR || AddrSpace == X86AS::PTR32_UPTR) { + unsigned ExtType = (AddrSpace == X86AS::PTR32_SPTR) ? ISD::SIGN_EXTEND + : ISD::ZERO_EXTEND; + MVT PtrVT = + CurDAG->getTargetLoweringInfo().getPointerTy(CurDAG->getDataLayout()); + if (PtrVT != MVT::i32) { + SDValue Ext = CurDAG->getNode(ExtType, SDLoc(N), PtrVT, N); + insertDAGNode(*CurDAG, N, Ext); + N = Ext; + } + } } // Save the DL and VT before calling matchAddress, it can invalidate N. 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 @@ -859,6 +859,12 @@ setOperationAction(ISD::STRICT_FSQRT, MVT::v4f32, Legal); } + // Do custom load/store lowering for ptr64 pointers in a 32-bit target. + if (Subtarget.is32Bit()) { + setOperationAction(ISD::LOAD, MVT::i64, Custom); + setOperationAction(ISD::STORE, MVT::i64, Custom); + } + if (!Subtarget.useSoftFloat() && Subtarget.hasSSE2()) { addRegisterClass(MVT::v2f64, Subtarget.hasVLX() ? &X86::VR128XRegClass : &X86::VR128RegClass); @@ -23358,6 +23364,16 @@ SDLoc dl(St); SDValue StoredVal = St->getValue(); + // Custom lower stores from the ptr64 address space by truncating the pointer. + if (St->getAddressSpace() == X86AS::PTR64) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, PtrVT, St->getBasePtr()); + return DAG.getStore(St->getChain(), dl, StoredVal, Trunc, + St->getPointerInfo(), St->getOriginalAlign(), + St->getMemOperand()->getFlags(), St->getAAInfo()); + } + // Without AVX512DQ, we need to use a scalar type for v2i1/v4i1/v8i1 stores. if (StoredVal.getValueType().isVector() && StoredVal.getValueType().getVectorElementType() == MVT::i1) { @@ -23395,6 +23411,9 @@ return SDValue(); } + if (!StoreVT.isVector()) + return SDValue(); + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); assert(StoreVT.isVector() && StoreVT.getSizeInBits() == 64 && "Unexpected VT"); @@ -23435,13 +23454,24 @@ static SDValue LowerLoad(SDValue Op, const X86Subtarget &Subtarget, SelectionDAG &DAG) { MVT RegVT = Op.getSimpleValueType(); - assert(RegVT.isVector() && "We only custom lower vector loads."); - assert(RegVT.isInteger() && - "We only custom lower integer vector loads."); - LoadSDNode *Ld = cast(Op.getNode()); SDLoc dl(Ld); + // Custom lower loads from the ptr64 address space by truncating the pointer. + if (Ld->getAddressSpace() == X86AS::PTR64) { + const TargetLowering &TLI = DAG.getTargetLoweringInfo(); + MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); + SDValue Trunc = DAG.getNode(ISD::TRUNCATE, dl, PtrVT, Ld->getBasePtr()); + return DAG.getLoad(PtrVT, dl, Ld->getChain(), Trunc, Ld->getPointerInfo(), + Ld->getOriginalAlign(), Ld->getMemOperand()->getFlags(), + Ld->getAAInfo()); + } + + if (!RegVT.isVector()) + return SDValue(); + + assert(RegVT.isInteger() && "We only custom lower integer vector loads."); + // Without AVX512DQ, we need to use a scalar type for v2i1/v4i1/v8i1 loads. if (RegVT.getVectorElementType() == MVT::i1) { assert(EVT(RegVT) == Ld->getMemoryVT() && "Expected non-extending load"); @@ -23455,7 +23485,6 @@ // Replace chain users with the new chain. assert(NewLd->getNumValues() == 2 && "Loads must carry a chain!"); - SDValue Val = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i16, NewLd); Val = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, RegVT, DAG.getBitcast(MVT::v16i1, Val), @@ -30058,6 +30087,8 @@ // avoids scalarizing in 32-bit mode. In 64-bit mode this avoids a int->fp // cast since type legalization will try to use an i64 load. MVT VT = N->getSimpleValueType(0); + if (!VT.isVector()) + return; assert(VT.isVector() && VT.getSizeInBits() == 64 && "Unexpected VT"); assert(getTypeAction(*DAG.getContext(), VT) == TypeWidenVector && "Unexpected type action!"); 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 @@ -1,4 +1,5 @@ -; RUN: llc < %s | FileCheck --check-prefixes=CHECK %s +; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck --check-prefixes=CHECK,X64 %s +; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck --check-prefixes=X86 %s ; RUN: llc -O0 < %s | FileCheck --check-prefixes=CHECK %s ; Source to regenerate: @@ -126,3 +127,52 @@ tail call void @use_foo(%struct.Foo* %f) ret void } + +; X64-LABEL: test_load_sptr32: +; X64: movslq %ecx, %rax +define i32 @test_load_sptr32(i32 addrspace(270)* %i) { +entry: + %0 = load i32, i32 addrspace(270)* %i, align 4 + ret i32 %0 +} + +; X64-LABEL: test_load_uptr32: +; X64: movl %ecx, %eax +define i32 @test_load_uptr32(i32 addrspace(271)* %i) { +entry: + %0 = load i32, i32 addrspace(271)* %i, align 4 + ret i32 %0 +} + +; X86-LABEL: _test_load_ptr64: +; X86: movl 4(%esp), %eax +define i32 @test_load_ptr64(i32 addrspace(272)* %i) { +entry: + %0 = load i32, i32 addrspace(272)* %i, align 8 + ret i32 %0 +} + +; X64-LABEL: test_store_sptr32: +; X64: movslq %ecx, %rax +define void @test_store_sptr32(i32 addrspace(270)* %s, i32 %i) { +entry: + store i32 %i, i32 addrspace(270)* %s, align 4 + ret void +} + +; X64-LABEL: test_store_uptr32: +; X64: movl %ecx, %eax +define void @test_store_uptr32(i32 addrspace(271)* %s, i32 %i) { +entry: + store i32 %i, i32 addrspace(271)* %s, align 4 + ret void +} + +; X86-LABEL: _test_store_ptr64: +; X86: movl 4(%esp), %ecx +; X86: movl %eax, (%ecx) +define void @test_store_ptr64(i32 addrspace(272)* %s, i32 %i) { +entry: + store i32 %i, i32 addrspace(272)* %s, align 8 + ret void +}