diff --git a/llvm/lib/Target/Hexagon/CMakeLists.txt b/llvm/lib/Target/Hexagon/CMakeLists.txt index 1a5f09642ea66..85ec5c7c2d45e 100644 --- a/llvm/lib/Target/Hexagon/CMakeLists.txt +++ b/llvm/lib/Target/Hexagon/CMakeLists.txt @@ -11,6 +11,7 @@ tablegen(LLVM HexagonGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM HexagonGenInstrInfo.inc -gen-instr-info) tablegen(LLVM HexagonGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM HexagonGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM HexagonGenSDNodeInfo.inc -gen-sd-node-info) tablegen(LLVM HexagonGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(HexagonCommonTableGen) diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index 894a07e6b68c2..87fbcfec600e7 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1914,66 +1914,6 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM, computeRegisterProperties(&HRI); } -const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch ((HexagonISD::NodeType)Opcode) { - case HexagonISD::ADDC: return "HexagonISD::ADDC"; - case HexagonISD::SUBC: return "HexagonISD::SUBC"; - case HexagonISD::ALLOCA: return "HexagonISD::ALLOCA"; - case HexagonISD::AT_GOT: return "HexagonISD::AT_GOT"; - case HexagonISD::AT_PCREL: return "HexagonISD::AT_PCREL"; - case HexagonISD::BARRIER: return "HexagonISD::BARRIER"; - case HexagonISD::CALL: return "HexagonISD::CALL"; - case HexagonISD::CALLnr: return "HexagonISD::CALLnr"; - case HexagonISD::CALLR: return "HexagonISD::CALLR"; - case HexagonISD::COMBINE: return "HexagonISD::COMBINE"; - case HexagonISD::CONST32_GP: return "HexagonISD::CONST32_GP"; - case HexagonISD::CONST32: return "HexagonISD::CONST32"; - case HexagonISD::CP: return "HexagonISD::CP"; - case HexagonISD::DCFETCH: return "HexagonISD::DCFETCH"; - case HexagonISD::EH_RETURN: return "HexagonISD::EH_RETURN"; - case HexagonISD::TSTBIT: return "HexagonISD::TSTBIT"; - case HexagonISD::EXTRACTU: return "HexagonISD::EXTRACTU"; - case HexagonISD::INSERT: return "HexagonISD::INSERT"; - case HexagonISD::JT: return "HexagonISD::JT"; - case HexagonISD::RET_GLUE: return "HexagonISD::RET_GLUE"; - case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN"; - case HexagonISD::VASL: return "HexagonISD::VASL"; - case HexagonISD::VASR: return "HexagonISD::VASR"; - case HexagonISD::VLSR: return "HexagonISD::VLSR"; - case HexagonISD::MFSHL: return "HexagonISD::MFSHL"; - case HexagonISD::MFSHR: return "HexagonISD::MFSHR"; - case HexagonISD::SSAT: return "HexagonISD::SSAT"; - case HexagonISD::USAT: return "HexagonISD::USAT"; - case HexagonISD::SMUL_LOHI: return "HexagonISD::SMUL_LOHI"; - case HexagonISD::UMUL_LOHI: return "HexagonISD::UMUL_LOHI"; - case HexagonISD::USMUL_LOHI: return "HexagonISD::USMUL_LOHI"; - case HexagonISD::VEXTRACTW: return "HexagonISD::VEXTRACTW"; - case HexagonISD::VINSERTW0: return "HexagonISD::VINSERTW0"; - case HexagonISD::VROR: return "HexagonISD::VROR"; - case HexagonISD::READCYCLE: return "HexagonISD::READCYCLE"; - case HexagonISD::READTIMER: return "HexagonISD::READTIMER"; - case HexagonISD::THREAD_POINTER: - return "HexagonISD::THREAD_POINTER"; - case HexagonISD::PTRUE: return "HexagonISD::PTRUE"; - case HexagonISD::PFALSE: return "HexagonISD::PFALSE"; - case HexagonISD::D2P: return "HexagonISD::D2P"; - case HexagonISD::P2D: return "HexagonISD::P2D"; - case HexagonISD::V2Q: return "HexagonISD::V2Q"; - case HexagonISD::Q2V: return "HexagonISD::Q2V"; - case HexagonISD::QCAT: return "HexagonISD::QCAT"; - case HexagonISD::QTRUE: return "HexagonISD::QTRUE"; - case HexagonISD::QFALSE: return "HexagonISD::QFALSE"; - case HexagonISD::TL_EXTEND: return "HexagonISD::TL_EXTEND"; - case HexagonISD::TL_TRUNCATE: return "HexagonISD::TL_TRUNCATE"; - case HexagonISD::TYPECAST: return "HexagonISD::TYPECAST"; - case HexagonISD::VALIGN: return "HexagonISD::VALIGN"; - case HexagonISD::VALIGNADDR: return "HexagonISD::VALIGNADDR"; - case HexagonISD::ISEL: return "HexagonISD::ISEL"; - case HexagonISD::OP_END: break; - } - return nullptr; -} - bool HexagonTargetLowering::validateConstPtrAlignment(SDValue Ptr, Align NeedAlign, const SDLoc &dl, SelectionDAG &DAG) const { @@ -3368,8 +3308,6 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { default: #ifndef NDEBUG Op.getNode()->dumpr(&DAG); - if (Opc > HexagonISD::OP_BEGIN && Opc < HexagonISD::OP_END) - errs() << "Error: check for a non-legal type in this operation\n"; #endif llvm_unreachable("Should not custom lower this!"); diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h index f4d2a79051c10..580cb48e37465 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -29,102 +29,6 @@ namespace llvm { -namespace HexagonISD { - -// clang-format off -enum NodeType : unsigned { - OP_BEGIN = ISD::BUILTIN_OP_END, - - CONST32 = OP_BEGIN, - CONST32_GP, // For marking data present in GP. - ADDC, // Add with carry: (X, Y, Cin) -> (X+Y, Cout). - SUBC, // Sub with carry: (X, Y, Cin) -> (X+~Y+Cin, Cout). - ALLOCA, - - AT_GOT, // Index in GOT. - AT_PCREL, // Offset relative to PC. - - CALL, // Function call. - CALLnr, // Function call that does not return. - CALLR, - - RET_GLUE, // Return with a glue operand. - BARRIER, // Memory barrier. - JT, // Jump table. - CP, // Constant pool. - - COMBINE, - VASL, // Vector shifts by a scalar value - VASR, - VLSR, - MFSHL, // Funnel shifts with the shift amount guaranteed to be - MFSHR, // within the range of the bit width of the element. - - SSAT, // Signed saturate. - USAT, // Unsigned saturate. - SMUL_LOHI, // Same as ISD::SMUL_LOHI, but opaque to the combiner. - UMUL_LOHI, // Same as ISD::UMUL_LOHI, but opaque to the combiner. - // We want to legalize MULH[SU] to [SU]MUL_LOHI, but the - // combiner will keep rewriting it back to MULH[SU]. - USMUL_LOHI, // Like SMUL_LOHI, but unsigned*signed. - - TSTBIT, - INSERT, - EXTRACTU, - VEXTRACTW, - VINSERTW0, - VROR, - TC_RETURN, - EH_RETURN, - DCFETCH, - READCYCLE, - READTIMER, - THREAD_POINTER, - PTRUE, - PFALSE, - D2P, // Convert 8-byte value to 8-bit predicate register. [*] - P2D, // Convert 8-bit predicate register to 8-byte value. [*] - V2Q, // Convert HVX vector to a vector predicate reg. [*] - Q2V, // Convert vector predicate to an HVX vector. [*] - // [*] The equivalence is defined as "Q <=> (V != 0)", - // where the != operation compares bytes. - // Note: V != 0 is implemented as V >u 0. - QCAT, - QTRUE, - QFALSE, - - TL_EXTEND, // Wrappers for ISD::*_EXTEND and ISD::TRUNCATE to prevent DAG - TL_TRUNCATE, // from auto-folding operations, e.g. - // (i32 ext (i16 ext i8)) would be folded to (i32 ext i8). - // To simplify the type legalization, we want to keep these - // single steps separate during type legalization. - // TL_[EXTEND|TRUNCATE] Inp, i128 _, i32 Opc - // * Inp is the original input to extend/truncate, - // * _ is a dummy operand with an illegal type (can be undef), - // * Opc is the original opcode. - // The legalization process (in Hexagon lowering code) will - // first deal with the "real" types (i.e. Inp and the result), - // and once all of them are processed, the wrapper node will - // be replaced with the original ISD node. The dummy illegal - // operand is there to make sure that the legalization hooks - // are called again after everything else is legal, giving - // us the opportunity to undo the wrapping. - - TYPECAST, // No-op that's used to convert between different legal - // types in a register. - VALIGN, // Align two vectors (in Op0, Op1) to one that would have - // been loaded from address in Op2. - VALIGNADDR, // Align vector address: Op0 & -Op1, except when it is - // an address in a vector load, then it's a no-op. - ISEL, // Marker for nodes that were created during ISel, and - // which need explicit selection (would have been left - // unselected otherwise). - OP_END -}; - -} // end namespace HexagonISD -// clang-format on - class HexagonSubtarget; class HexagonTargetLowering : public TargetLowering { @@ -189,7 +93,6 @@ class HexagonTargetLowering : public TargetLowering { void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const override; - const char *getTargetNodeName(unsigned Opcode) const override; std::pair handleMaskRegisterForCallingConv(const HexagonSubtarget &Subtarget, EVT VT) const; diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td index e40dbd251b5b7..b4ad58d4c2f84 100644 --- a/llvm/lib/Target/Hexagon/HexagonPatterns.td +++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td @@ -92,16 +92,47 @@ def SDTVecLeaf: def SDTVecVecIntOp: SDTypeProfile<1, 3, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1,2>, SDTCisVT<3,i32>]>; +def SDTIntBinOpWithCarryInOut: + SDTypeProfile<2, 3, [SDTCisInt<0>, SDTCisVT<1, i1>, SDTCisSameAs<2, 0>, + SDTCisSameAs<3, 0>, SDTCisVT<4, i1>]>; + +// Add with carry: (X, Y, Cin) -> (X+Y, Cout). +def HexagonADDC: SDNode<"HexagonISD::ADDC", SDTIntBinOpWithCarryInOut>; + +// Sub with carry: (X, Y, Cin) -> (X+~Y+Cin, Cout). +def HexagonSUBC: SDNode<"HexagonISD::SUBC", SDTIntBinOpWithCarryInOut>; + +// Same as ISD::SMUL_LOHI, but opaque to the combiner. +// We want to legalize MULH[SU] to [SU]MUL_LOHI, but the +// combiner will keep rewriting it back to MULH[SU]. +def HexagonSMUL_LOHI: SDNode<"HexagonISD::SMUL_LOHI", SDTIntBinHiLoOp>; + +// Same as ISD::UMUL_LOHI, but opaque to the combiner. +def HexagonUMUL_LOHI: SDNode<"HexagonISD::UMUL_LOHI", SDTIntBinHiLoOp>; + +// Like SMUL_LOHI, but unsigned*signed. +def HexagonUSMUL_LOHI: SDNode<"HexagonISD::USMUL_LOHI", SDTIntBinHiLoOp>; def HexagonPTRUE: SDNode<"HexagonISD::PTRUE", SDTVecLeaf>; def HexagonPFALSE: SDNode<"HexagonISD::PFALSE", SDTVecLeaf>; + +// Align two vectors (in Op0, Op1) to one that would have +// been loaded from address in Op2. def HexagonVALIGN: SDNode<"HexagonISD::VALIGN", SDTVecVecIntOp>; + +// Align vector address: Op0 & -Op1, except when it is +// an address in a vector load, then it's a no-op. def HexagonVALIGNADDR: SDNode<"HexagonISD::VALIGNADDR", SDTIntUnaryOp>; + def HexagonMULHUS: SDNode<"HexagonISD::MULHUS", SDTIntBinOp>; def SDTSaturate: SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisInt<1>, SDTCisVT<2, OtherVT>]>; + +// Signed saturate. def HexagonSSAT: SDNode<"HexagonISD::SSAT", SDTSaturate>; + +// Unsigned saturate. def HexagonUSAT: SDNode<"HexagonISD::USAT", SDTSaturate>; def ptrue: PatFrag<(ops), (HexagonPTRUE)>; @@ -408,9 +439,15 @@ def Imm64Hi: SDNodeXForm, SDTCisVT<1, i32>, SDTCisPtrTy<0>]>; +// Jump table. def HexagonJT: SDNode<"HexagonISD::JT", SDTIntUnaryOp>; + +// Constant pool. def HexagonCP: SDNode<"HexagonISD::CP", SDTIntUnaryOp>; + def HexagonCONST32: SDNode<"HexagonISD::CONST32", SDTHexagonCONST32>; + +// For marking data present in GP. def HexagonCONST32_GP: SDNode<"HexagonISD::CONST32_GP", SDTHexagonCONST32>; def TruncI64ToI32: SDNodeXForm, SDTCisVec<0>, SDTCisVT<2, i32>]>; +// Vector shifts by a scalar value def HexagonVASL: SDNode<"HexagonISD::VASL", SDTHexagonVShift>; def HexagonVASR: SDNode<"HexagonISD::VASR", SDTHexagonVShift>; def HexagonVLSR: SDNode<"HexagonISD::VLSR", SDTHexagonVShift>; @@ -3291,8 +3329,12 @@ def SDT_SPCall: SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; def HexagonTCRet: SDNode<"HexagonISD::TC_RETURN", SDT_SPCall, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + +// Function call. def callv3: SDNode<"HexagonISD::CALL", SDT_SPCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; + +// Function call that does not return. def callv3nr: SDNode<"HexagonISD::CALLnr", SDT_SPCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; @@ -3314,8 +3356,10 @@ def: Pat<(callv3nr I32:$dst), (PS_callr_nr I32:$dst)>; def: Pat<(callv3nr tglobaladdr:$dst), (PS_call_nr tglobaladdr:$dst)>; def: Pat<(callv3nr texternalsym:$dst), (PS_call_nr texternalsym:$dst)>; +// Return with a glue operand. def retglue : SDNode<"HexagonISD::RET_GLUE", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + def eh_return: SDNode<"HexagonISD::EH_RETURN", SDTNone, [SDNPHasChain]>; def: Pat<(retglue), (PS_jmpret (i32 R31))>; @@ -3395,7 +3439,9 @@ def HexagonALLOCA def: Pat<(HexagonALLOCA I32:$Rs, (i32 imm:$A)), (PS_alloca IntRegs:$Rs, imm:$A)>; +// Memory barrier. def HexagonBARRIER: SDNode<"HexagonISD::BARRIER", SDTNone, [SDNPHasChain]>; + def: Pat<(HexagonBARRIER), (Y2_barrier)>; def: Pat<(trap), (PS_crash)>; diff --git a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp index 33aa6e4a26145..4b9d2b92f451a 100644 --- a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp +++ b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.cpp @@ -10,12 +10,58 @@ // //===----------------------------------------------------------------------===// +#include "HexagonSelectionDAGInfo.h" #include "HexagonTargetMachine.h" #include "llvm/CodeGen/SelectionDAG.h" + +#define GET_SDNODE_DESC +#include "HexagonGenSDNodeInfo.inc" + using namespace llvm; #define DEBUG_TYPE "hexagon-selectiondag-info" +HexagonSelectionDAGInfo::HexagonSelectionDAGInfo() + : SelectionDAGGenTargetInfo(HexagonGenSDNodeInfo) {} + +const char *HexagonSelectionDAGInfo::getTargetNodeName(unsigned Opcode) const { +#define CASE(NAME) \ + case HexagonISD::NAME: \ + return "HexagonISD::" #NAME + + // These nodes don't have corresponding entries in *.td files yet. + switch (static_cast(Opcode)) { + CASE(CALLR); + CASE(VROR); + CASE(D2P); + CASE(P2D); + CASE(V2Q); + CASE(Q2V); + CASE(TL_EXTEND); + CASE(TL_TRUNCATE); + CASE(TYPECAST); + CASE(ISEL); + } +#undef CASE + + return SelectionDAGGenTargetInfo::getTargetNodeName(Opcode); +} + +void HexagonSelectionDAGInfo::verifyTargetNode(const SelectionDAG &DAG, + const SDNode *N) const { + switch (N->getOpcode()) { + default: + break; + case HexagonISD::VALIGNADDR: + // invalid number of operands; expected 1, got 2 + case HexagonISD::VINSERTW0: + // operand #1 must have type i32, but has type v4i8/v2i16 + return; + } + + SelectionDAGGenTargetInfo::verifyTargetNode(DAG, N); +} + SDValue HexagonSelectionDAGInfo::EmitTargetCodeForMemcpy( SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, Align Alignment, bool isVolatile, bool AlwaysInline, diff --git a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.h b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.h index 0d3b1725d1bc4..d1d5b0c7ac0ee 100644 --- a/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.h +++ b/llvm/lib/Target/Hexagon/HexagonSelectionDAGInfo.h @@ -15,11 +15,58 @@ #include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#define GET_SDNODE_ENUM +#include "HexagonGenSDNodeInfo.inc" + namespace llvm { +namespace HexagonISD { + +enum NodeType : unsigned { + CALLR = GENERATED_OPCODE_END, + + VROR, + D2P, // Convert 8-byte value to 8-bit predicate register. [*] + P2D, // Convert 8-bit predicate register to 8-byte value. [*] + V2Q, // Convert HVX vector to a vector predicate reg. [*] + Q2V, // Convert vector predicate to an HVX vector. [*] + // [*] The equivalence is defined as "Q <=> (V != 0)", + // where the != operation compares bytes. + // Note: V != 0 is implemented as V >u 0. -class HexagonSelectionDAGInfo : public SelectionDAGTargetInfo { + TL_EXTEND, // Wrappers for ISD::*_EXTEND and ISD::TRUNCATE to prevent DAG + TL_TRUNCATE, // from auto-folding operations, e.g. + // (i32 ext (i16 ext i8)) would be folded to (i32 ext i8). + // To simplify the type legalization, we want to keep these + // single steps separate during type legalization. + // TL_[EXTEND|TRUNCATE] Inp, i128 _, i32 Opc + // * Inp is the original input to extend/truncate, + // * _ is a dummy operand with an illegal type (can be undef), + // * Opc is the original opcode. + // The legalization process (in Hexagon lowering code) will + // first deal with the "real" types (i.e. Inp and the result), + // and once all of them are processed, the wrapper node will + // be replaced with the original ISD node. The dummy illegal + // operand is there to make sure that the legalization hooks + // are called again after everything else is legal, giving + // us the opportunity to undo the wrapping. + + TYPECAST, // No-op that's used to convert between different legal + // types in a register. + ISEL, // Marker for nodes that were created during ISel, and + // which need explicit selection (would have been left + // unselected otherwise). +}; + +} // namespace HexagonISD + +class HexagonSelectionDAGInfo : public SelectionDAGGenTargetInfo { public: - explicit HexagonSelectionDAGInfo() = default; + HexagonSelectionDAGInfo(); + + const char *getTargetNodeName(unsigned Opcode) const override; + + void verifyTargetNode(const SelectionDAG &DAG, + const SDNode *N) const override; SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, const SDLoc &dl, SDValue Chain, SDValue Dst, SDValue Src, @@ -29,6 +76,6 @@ class HexagonSelectionDAGInfo : public SelectionDAGTargetInfo { MachinePointerInfo SrcPtrInfo) const override; }; -} +} // namespace llvm #endif