diff --git a/llvm/docs/GlobalISel/GenericOpcode.rst b/llvm/docs/GlobalISel/GenericOpcode.rst index a39994ca8f33d..add4a89bd845e 100644 --- a/llvm/docs/GlobalISel/GenericOpcode.rst +++ b/llvm/docs/GlobalISel/GenericOpcode.rst @@ -169,6 +169,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 571ec6dd7e9ba..c9bb04fa941bd 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 41d03c9fb3ed5..3f465b824ece5 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h @@ -486,7 +486,9 @@ class IRTranslator : public MachineFunctionPass { bool translatePtrToInt(const User &U, MachineIRBuilder &MIRBuilder) { return translateCast(TargetOpcode::G_PTRTOINT, U, MIRBuilder); } - bool translatePtrToAddr(const User &U, MachineIRBuilder &MIRBuilder); + bool translatePtrToAddr(const User &U, MachineIRBuilder &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 4106be4c81cea..cfd7b10536ba7 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h @@ -429,6 +429,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 25fef99699fdf..d60ba107f5f1a 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -715,6 +715,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 92fd60e03112a..cbcf0b2743e9c 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 a462b07461b41..b122ed58b0724 100644 --- a/llvm/include/llvm/Target/GenericOpcodes.td +++ b/llvm/include/llvm/Target/GenericOpcodes.td @@ -134,6 +134,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 efd88524a159e..f55051dea9ae8 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -440,8 +440,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 7577792003d2e..5e58865e97861 100644 --- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -54,6 +54,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 b1e851183de0d..4fe3cd54ad9c2 100644 --- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp @@ -4814,7 +4814,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 6650ad25bed04..0fe2a0955883c 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp @@ -491,6 +491,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/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 1c7507c60384e..fe5dcd14d8804 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -1583,20 +1583,6 @@ bool IRTranslator::translateCast(unsigned Opcode, const User &U, return true; } -bool IRTranslator::translatePtrToAddr(const User &U, - MachineIRBuilder &MIRBuilder) { - Register Op = getOrCreateVReg(*U.getOperand(0)); - Type *PtrTy = U.getOperand(0)->getType(); - LLT AddrTy = getLLTForType(*DL->getAddressType(PtrTy), *DL); - auto IntPtrTy = getLLTForType(*DL->getIntPtrType(PtrTy), *DL); - auto PtrToInt = MIRBuilder.buildPtrToInt(IntPtrTy, Op); - auto Addr = PtrToInt; - if (AddrTy != IntPtrTy) - Addr = MIRBuilder.buildTrunc(AddrTy, PtrToInt.getReg(0)); - MIRBuilder.buildZExtOrTrunc(getOrCreateVReg(U), Addr.getReg(0)); - return true; -} - bool IRTranslator::translateGetElementPtr(const User &U, MachineIRBuilder &MIRBuilder) { Value &Op0 = *U.getOperand(0); 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 83ba71e4c9d49..39fc2001128bc 100644 --- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -1670,6 +1670,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; @@ -3305,6 +3306,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; @@ -4691,6 +4693,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: @@ -5420,6 +5424,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: @@ -7407,6 +7412,34 @@ 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_PTROINT 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 SrcTy = MRI.getType(SrcReg); + + LLT AddrTy = getLLTForType( + *DL.getAddressType(MIRBuilder.getContext(), SrcTy.getAddressSpace()), DL); + LLT IntPtrTy = getLLTForType( + *DL.getIntPtrType(MIRBuilder.getContext(), SrcTy.getAddressSpace()), DL); + if (SrcTy.isVector()) { + AddrTy = LLT::vector(SrcTy.getElementCount(), AddrTy); + IntPtrTy = LLT::vector(SrcTy.getElementCount(), IntPtrTy); + } + auto PtrToInt = MIRBuilder.buildPtrToInt(IntPtrTy, SrcReg); + auto Addr = PtrToInt; + if (AddrTy != IntPtrTy) + Addr = MIRBuilder.buildTrunc(AddrTy, PtrToInt.getReg(0)); + MIRBuilder.buildZExtOrTrunc(DstReg, Addr.getReg(0)); + 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 109988246d0ab..c2a64b8b9af10 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())