diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index b055327466739..7fb99116f2120 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -196,6 +196,15 @@ Convert a pointer to an integer. %1:_(s32) = G_PTRTOINT %0:_(p0) +G_PTRTOADDR +^^^^^^^^^^^ + +Extract the address part of a pointer to an integer. + +.. code-block:: none + + %1:_(s32) = G_PTRTOADDR %0:_(p0) + G_BITCAST ^^^^^^^^^ diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h index 5faf57fd06228..0a620fdc54d31 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h @@ -870,6 +870,7 @@ class GCastOp : public GenericMachineInstr { case TargetOpcode::G_FPTOUI_SAT: case TargetOpcode::G_FPTRUNC: case TargetOpcode::G_INTTOPTR: + case TargetOpcode::G_PTRTOADDR: case TargetOpcode::G_PTRTOINT: case TargetOpcode::G_SEXT: case TargetOpcode::G_SITOFP: diff --git a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h index 3d7ccd55ee042..722e3e61e542e 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -487,8 +487,7 @@ class IRTranslator : public MachineFunctionPass { return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder); } bool translatePtrToAddr(const User &U, MachineIRBuilder &MIRBuilder) { - // FIXME: this is not correct for pointers with addr width != pointer width - return translatePtrToInt(U, MIRBuilder); + return translateCast(TargetOpcode::G_PTRTOADDR, U, MIRBuilder); } bool translateTrunc(const User &U, MachineIRBuilder &MIRBuilder) { return translateCast(TargetOpcode::G_TRUNC, U, MIRBuilder); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h index c0e426c4a8db3..dc2f6db2313f4 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -475,6 +475,7 @@ class LegalizerHelper { LLVM_ABI LegalizeResult lowerFunnelShift(MachineInstr &MI); LLVM_ABI LegalizeResult lowerEXT(MachineInstr &MI); LLVM_ABI LegalizeResult lowerTRUNC(MachineInstr &MI); + LLVM_ABI LegalizeResult lowerPTRTOADDR(MachineInstr &MI); LLVM_ABI LegalizeResult lowerRotateWithReverseRotate(MachineInstr &MI); LLVM_ABI LegalizeResult lowerRotate(MachineInstr &MI); diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h index 40c7792f7e8a2..850ab1dbcc773 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -749,6 +749,11 @@ class LLVM_ABI MachineIRBuilder { return buildInstr(TargetOpcode::G_PTRTOINT, {Dst}, {Src}); } + /// Build and insert a G_PTRTOADDR instruction. + MachineInstrBuilder buildPtrToAddr(const DstOp &Dst, const SrcOp &Src) { + return buildInstr(TargetOpcode::G_PTRTOADDR, {Dst}, {Src}); + } + /// Build and insert a G_INTTOPTR instruction. MachineInstrBuilder buildIntToPtr(const DstOp &Dst, const SrcOp &Src) { return buildInstr(TargetOpcode::G_INTTOPTR, {Dst}, {Src}); diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index e55314568d683..7d6baf7545ae8 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -343,6 +343,9 @@ HANDLE_TARGET_OPCODE(G_CONCAT_VECTORS) /// Generic pointer to int conversion. HANDLE_TARGET_OPCODE(G_PTRTOINT) +/// Generic pointer to address conversion. +HANDLE_TARGET_OPCODE(G_PTRTOADDR) + /// Generic int to pointer conversion. HANDLE_TARGET_OPCODE(G_INTTOPTR) diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td index e3f995d53484f..aa6c99f6da3cb 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -155,6 +155,12 @@ def G_PTRTOINT : GenericInstruction { let hasSideEffects = false; } +def G_PTRTOADDR : GenericInstruction { + let OutOperandList = (outs type0:$dst); + let InOperandList = (ins type1:$src); + let hasSideEffects = false; +} + def G_BITCAST : GenericInstruction { let OutOperandList = (outs type0:$dst); let InOperandList = (ins type1:$src); diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 3d21f522e97ce..042de83d3345b 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -453,8 +453,8 @@ def unary_undef_to_zero: GICombineRule< def unary_undef_to_undef_frags : GICombinePatFrag< (outs root:$dst), (ins), !foreach(op, - [G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT, G_INTTOPTR, G_FPTOSI, - G_FPTOUI], + [G_TRUNC, G_BITCAST, G_ANYEXT, G_PTRTOINT, G_PTRTOADDR, G_INTTOPTR, + G_FPTOSI, G_FPTOUI], (pattern (op $dst, $x), (G_IMPLICIT_DEF $x)))>; def unary_undef_to_undef : GICombineRule< (defs root:$dst), diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index c0d480294dd8b..5399731d63ff4 100644 --- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -57,6 +57,7 @@ def : GINodeEquiv; def : GINodeEquiv; // G_INTTOPTR - SelectionDAG has no equivalent. // G_PTRTOINT - SelectionDAG has no equivalent. +// G_PTRTOADDR - SelectionDAG has no equivalent. def : GINodeEquiv; // timm must not be materialized and therefore has no GlobalISel equivalent def : GINodeEquiv; diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp index b425b952bfc1d..26f18487392f0 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4909,7 +4909,8 @@ bool CombinerHelper::reassociationCanBreakAddressingModePattern( MachineInstr *ConvUseMI = &UseMI; unsigned ConvUseOpc = ConvUseMI->getOpcode(); while (ConvUseOpc == TargetOpcode::G_INTTOPTR || - ConvUseOpc == TargetOpcode::G_PTRTOINT) { + ConvUseOpc == TargetOpcode::G_PTRTOINT || + ConvUseOpc == TargetOpcode::G_PTRTOADDR) { Register DefReg = ConvUseMI->getOperand(0).getReg(); if (!MRI.hasOneNonDBGUse(DefReg)) break; diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp index 04d93098a5260..309bf470deb66 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp @@ -485,6 +485,7 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known, } case TargetOpcode::G_INTTOPTR: case TargetOpcode::G_PTRTOINT: + case TargetOpcode::G_PTRTOADDR: if (DstTy.isVector()) break; // Fall through and handle them the same as zext/trunc. diff --git a/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp b/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp index 05923e5fc97cc..134c0cea92a35 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegacyLegalizerInfo.cpp @@ -100,6 +100,9 @@ LegacyLegalizerInfo::LegacyLegalizerInfo() { setLegalizeScalarToDifferentSizeStrategy( TargetOpcode::G_EXTRACT, 1, narrowToSmallerAndUnsupportedIfTooSmall); setScalarAction(TargetOpcode::G_FNEG, 0, {{1, Lower}}); + + setScalarAction(TargetOpcode::G_PTRTOADDR, 0, {{1, Lower}}); + // FIXME: Lower G_PTRTOADDR for vector types using less hacky approach } void LegacyLegalizerInfo::computeTables() { @@ -204,6 +207,10 @@ LegacyLegalizerInfo::getAspectAction(const InstrAspect &Aspect) const { if (Aspect.Type.isScalar() || Aspect.Type.isPointer()) return findScalarLegalAction(Aspect); assert(Aspect.Type.isVector()); + if (Aspect.Opcode == TargetOpcode::G_PTRTOADDR) { + // FIXME: need to handle this better + return {Lower, Aspect.Type}; + } return findVectorLegalAction(Aspect); } @@ -382,4 +389,3 @@ LegacyLegalizerInfo::getAction(const LegalityQuery &Query) const { LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n"); return {Legal, 0, LLT{}}; } - diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 38ec83f81f471..e74531a5ad1b8 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1792,6 +1792,7 @@ LegalizerHelper::LegalizeResult LegalizerHelper::narrowScalar(MachineInstr &MI, narrowScalarSrc(MI, NarrowTy, 1); Observer.changedInstr(MI); return Legalized; + case TargetOpcode::G_PTRTOADDR: case TargetOpcode::G_PTRTOINT: if (TypeIdx != 0) return UnableToLegalize; @@ -3439,6 +3440,7 @@ LegalizerHelper::widenScalar(MachineInstr &MI, unsigned TypeIdx, LLT WideTy) { widenScalarSrc(MI, WideTy, 1, TargetOpcode::G_ZEXT); Observer.changedInstr(MI); return Legalized; + case TargetOpcode::G_PTRTOADDR: case TargetOpcode::G_PTRTOINT: if (TypeIdx != 0) return UnableToLegalize; @@ -4853,6 +4855,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) { return lowerEXT(MI); case G_TRUNC: return lowerTRUNC(MI); + case G_PTRTOADDR: + return lowerPTRTOADDR(MI); GISEL_VECREDUCE_CASES_NONSEQ return lowerVectorReduction(MI); case G_VAARG: @@ -5600,6 +5604,7 @@ LegalizerHelper::fewerElementsVector(MachineInstr &MI, unsigned TypeIdx, case G_FPTOUI_SAT: case G_INTTOPTR: case G_PTRTOINT: + case G_PTRTOADDR: case G_ADDRSPACE_CAST: case G_UADDO: case G_USUBO: @@ -7966,6 +7971,32 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerTRUNC(MachineInstr &MI) { return UnableToLegalize; } +LegalizerHelper::LegalizeResult +LegalizerHelper::lowerPTRTOADDR(MachineInstr &MI) { + // Lower G_PTRTOADDR as a truncate to address width of G_PTRTOINT and then + // zero extend to the target width if there is no native support for it. + MachineRegisterInfo &MRI = *MIRBuilder.getMRI(); + const DataLayout &DL = MIRBuilder.getDataLayout(); + assert(MI.getOpcode() == TargetOpcode::G_PTRTOADDR); + auto DstReg = MI.getOperand(0).getReg(); + auto SrcReg = MI.getOperand(1).getReg(); + LLT AddrTy = MRI.getType(DstReg); + LLT SrcTy = MRI.getType(SrcReg); + LLT IntPtrTy = getLLTForType( + *DL.getIntPtrType(MIRBuilder.getContext(), SrcTy.getAddressSpace()), DL); + if (SrcTy.isVector()) { + IntPtrTy = LLT::vector(SrcTy.getElementCount(), IntPtrTy); + } + if (AddrTy != IntPtrTy) { + auto PtrToInt = MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg); + MIRBuilder.buildTrunc(DstReg, PtrToInt.getReg(0)); + } else { + MIRBuilder.buildPtrToInt(DstReg, SrcReg); + } + MI.eraseFromParent(); + return Legalized; +} + LegalizerHelper::LegalizeResult LegalizerHelper::lowerRotateWithReverseRotate(MachineInstr &MI) { auto [Dst, DstTy, Src, SrcTy, Amt, AmtTy] = MI.getFirst3RegLLTs(); diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index 115485509c4a5..2f3037adcf533 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -1344,6 +1344,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { break; } case TargetOpcode::G_INTTOPTR: + case TargetOpcode::G_PTRTOADDR: case TargetOpcode::G_PTRTOINT: case TargetOpcode::G_ADDRSPACE_CAST: { LLT DstTy = MRI->getType(MI->getOperand(0).getReg()); @@ -1366,6 +1367,11 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) { report("ptrtoint source type must be a pointer", MI); if (DstTy.isPointer()) report("ptrtoint result type must not be a pointer", MI); + } else if (MI->getOpcode() == TargetOpcode::G_PTRTOADDR) { + if (!SrcTy.isPointer()) + report("ptrtoaddr source type must be a pointer", MI); + if (DstTy.isPointer()) + report("ptrtoaddr result type must not be a pointer", MI); } else { assert(MI->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST); if (!SrcTy.isPointer() || !DstTy.isPointer()) diff --git a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp index 2d3cb71fbc3fd..21344e973ba66 100644 --- a/llvm/lib/Target/ARM/ARMInstructionSelector.cpp +++ b/llvm/lib/Target/ARM/ARMInstructionSelector.cpp @@ -1018,6 +1018,7 @@ bool ARMInstructionSelector::select(MachineInstr &I) { break; } case G_INTTOPTR: + case G_PTRTOADDR: case G_PTRTOINT: { auto SrcReg = I.getOperand(1).getReg(); auto DstReg = I.getOperand(0).getReg(); diff --git a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp index 0493fd9e317d5..637a578bfdeb5 100644 --- a/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp +++ b/llvm/lib/Target/ARM/ARMRegisterBankInfo.cpp @@ -215,6 +215,7 @@ ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_PTR_ADD: case G_INTTOPTR: case G_PTRTOINT: + case G_PTRTOADDR: case G_CTLZ: // FIXME: We're abusing the fact that everything lives in a GPR for now; in // the real world we would use different mappings. diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp index 332749165a3ff..7109cbeffa463 100644 --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -347,6 +347,7 @@ bool MipsInstructionSelector::select(MachineInstr &I) { break; } case G_INTTOPTR: + case G_PTRTOADDR: case G_PTRTOINT: { I.setDesc(TII.get(COPY)); return selectCopy(I, MRI); diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp index 4aecaf18db480..752ee7db00e66 100644 --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -422,6 +422,7 @@ MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { case G_SEXTLOAD: case G_PTR_ADD: case G_INTTOPTR: + case G_PTRTOADDR: case G_PTRTOINT: case G_AND: case G_OR: