1*06c3fb27SDimitry Andric //===---- RISCVISelDAGToDAG.h - A dag to dag inst selector for RISC-V -----===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 9*06c3fb27SDimitry Andric // This file defines an instruction selector for the RISC-V target. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 125ffd83dbSDimitry Andric 135ffd83dbSDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_RISCVISELDAGTODAG_H 145ffd83dbSDimitry Andric #define LLVM_LIB_TARGET_RISCV_RISCVISELDAGTODAG_H 155ffd83dbSDimitry Andric 165ffd83dbSDimitry Andric #include "RISCV.h" 175ffd83dbSDimitry Andric #include "RISCVTargetMachine.h" 185ffd83dbSDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h" 19bdd1243dSDimitry Andric #include "llvm/Support/KnownBits.h" 205ffd83dbSDimitry Andric 21*06c3fb27SDimitry Andric // RISC-V specific code to select RISC-V machine instructions for 225ffd83dbSDimitry Andric // SelectionDAG operations. 235ffd83dbSDimitry Andric namespace llvm { 245ffd83dbSDimitry Andric class RISCVDAGToDAGISel : public SelectionDAGISel { 255ffd83dbSDimitry Andric const RISCVSubtarget *Subtarget = nullptr; 265ffd83dbSDimitry Andric 275ffd83dbSDimitry Andric public: 28bdd1243dSDimitry Andric static char ID; 29bdd1243dSDimitry Andric 30bdd1243dSDimitry Andric RISCVDAGToDAGISel() = delete; 31bdd1243dSDimitry Andric 3281ad6265SDimitry Andric explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine, 3381ad6265SDimitry Andric CodeGenOpt::Level OptLevel) 34bdd1243dSDimitry Andric : SelectionDAGISel(ID, TargetMachine, OptLevel) {} 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 375ffd83dbSDimitry Andric Subtarget = &MF.getSubtarget<RISCVSubtarget>(); 385ffd83dbSDimitry Andric return SelectionDAGISel::runOnMachineFunction(MF); 395ffd83dbSDimitry Andric } 405ffd83dbSDimitry Andric 41fe6060f1SDimitry Andric void PreprocessISelDAG() override; 425ffd83dbSDimitry Andric void PostprocessISelDAG() override; 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric void Select(SDNode *Node) override; 455ffd83dbSDimitry Andric 465ffd83dbSDimitry Andric bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 475ffd83dbSDimitry Andric std::vector<SDValue> &OutOps) override; 485ffd83dbSDimitry Andric 4981ad6265SDimitry Andric bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset); 5081ad6265SDimitry Andric bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); 51*06c3fb27SDimitry Andric bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset, 52*06c3fb27SDimitry Andric bool IsINX = false); 53*06c3fb27SDimitry Andric bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) { 54*06c3fb27SDimitry Andric return SelectAddrRegImm(Addr, Base, Offset, true); 55*06c3fb27SDimitry Andric } 56*06c3fb27SDimitry Andric 57*06c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount, 58*06c3fb27SDimitry Andric SDValue &Base, SDValue &Index, SDValue &Scale); 59*06c3fb27SDimitry Andric 60*06c3fb27SDimitry Andric template <unsigned MaxShift> 61*06c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 62*06c3fb27SDimitry Andric SDValue &Scale) { 63*06c3fb27SDimitry Andric return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale); 64*06c3fb27SDimitry Andric } 65*06c3fb27SDimitry Andric 66*06c3fb27SDimitry Andric template <unsigned MaxShift, unsigned Bits> 67*06c3fb27SDimitry Andric bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 68*06c3fb27SDimitry Andric SDValue &Scale) { 69*06c3fb27SDimitry Andric if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) { 70*06c3fb27SDimitry Andric if (Index.getOpcode() == ISD::AND) { 71*06c3fb27SDimitry Andric auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1)); 72*06c3fb27SDimitry Andric if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) { 73*06c3fb27SDimitry Andric Index = Index.getOperand(0); 74*06c3fb27SDimitry Andric return true; 75*06c3fb27SDimitry Andric } 76*06c3fb27SDimitry Andric } 77*06c3fb27SDimitry Andric } 78*06c3fb27SDimitry Andric return false; 79*06c3fb27SDimitry Andric } 805ffd83dbSDimitry Andric 81bdd1243dSDimitry Andric bool tryShrinkShlLogicImm(SDNode *Node); 82*06c3fb27SDimitry Andric bool trySignedBitfieldExtract(SDNode *Node); 83*06c3fb27SDimitry Andric bool tryIndexedLoad(SDNode *Node); 84bdd1243dSDimitry Andric 85fe6060f1SDimitry Andric bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); 86fe6060f1SDimitry Andric bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) { 87fe6060f1SDimitry Andric return selectShiftMask(N, Subtarget->getXLen(), ShAmt); 88fe6060f1SDimitry Andric } 89fe6060f1SDimitry Andric bool selectShiftMask32(SDValue N, SDValue &ShAmt) { 90fe6060f1SDimitry Andric return selectShiftMask(N, 32, ShAmt); 91fe6060f1SDimitry Andric } 92fe6060f1SDimitry Andric 93*06c3fb27SDimitry Andric bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val); 94*06c3fb27SDimitry Andric bool selectSETNE(SDValue N, SDValue &Val) { 95*06c3fb27SDimitry Andric return selectSETCC(N, ISD::SETNE, Val); 96*06c3fb27SDimitry Andric } 97*06c3fb27SDimitry Andric bool selectSETEQ(SDValue N, SDValue &Val) { 98*06c3fb27SDimitry Andric return selectSETCC(N, ISD::SETEQ, Val); 99*06c3fb27SDimitry Andric } 100*06c3fb27SDimitry Andric 101*06c3fb27SDimitry Andric bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val); 102*06c3fb27SDimitry Andric template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) { 103*06c3fb27SDimitry Andric return selectSExtBits(N, Bits, Val); 104*06c3fb27SDimitry Andric } 105bdd1243dSDimitry Andric bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val); 106bdd1243dSDimitry Andric template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) { 107bdd1243dSDimitry Andric return selectZExtBits(N, Bits, Val); 108bdd1243dSDimitry Andric } 109e8d8bef9SDimitry Andric 110753f127fSDimitry Andric bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val); 111bdd1243dSDimitry Andric template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) { 112bdd1243dSDimitry Andric return selectSHXADDOp(N, ShAmt, Val); 113753f127fSDimitry Andric } 114753f127fSDimitry Andric 115bdd1243dSDimitry Andric bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val); 116bdd1243dSDimitry Andric template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) { 117bdd1243dSDimitry Andric return selectSHXADD_UWOp(N, ShAmt, Val); 118bdd1243dSDimitry Andric } 119bdd1243dSDimitry Andric 120bdd1243dSDimitry Andric bool hasAllNBitUsers(SDNode *Node, unsigned Bits, 121bdd1243dSDimitry Andric const unsigned Depth = 0) const; 122349cc55cSDimitry Andric bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } 123349cc55cSDimitry Andric bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } 124349cc55cSDimitry Andric 125*06c3fb27SDimitry Andric bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2); 126*06c3fb27SDimitry Andric 127d409305fSDimitry Andric bool selectVLOp(SDValue N, SDValue &VL); 128d409305fSDimitry Andric 129e8d8bef9SDimitry Andric bool selectVSplat(SDValue N, SDValue &SplatVal); 130e8d8bef9SDimitry Andric bool selectVSplatSimm5(SDValue N, SDValue &SplatVal); 131*06c3fb27SDimitry Andric bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal); 132*06c3fb27SDimitry Andric template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) { 133*06c3fb27SDimitry Andric return selectVSplatUimm(N, Bits, Val); 134*06c3fb27SDimitry Andric } 135fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal); 136fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal); 137*06c3fb27SDimitry Andric bool selectExtOneUseVSplat(SDValue N, SDValue &SplatVal); 138*06c3fb27SDimitry Andric bool selectFPImm(SDValue N, SDValue &Imm); 139e8d8bef9SDimitry Andric 140fe6060f1SDimitry Andric bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm); 141fe6060f1SDimitry Andric template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) { 142fe6060f1SDimitry Andric return selectRVVSimm5(N, Width, Imm); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric 145fe6060f1SDimitry Andric void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, 146fe6060f1SDimitry Andric const SDLoc &DL, unsigned CurOp, 147fe6060f1SDimitry Andric bool IsMasked, bool IsStridedOrIndexed, 148fe6060f1SDimitry Andric SmallVectorImpl<SDValue> &Operands, 149349cc55cSDimitry Andric bool IsLoad = false, MVT *IndexVT = nullptr); 150fe6060f1SDimitry Andric 151fe6060f1SDimitry Andric void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided); 152fe6060f1SDimitry Andric void selectVLSEGFF(SDNode *Node, bool IsMasked); 153fe6060f1SDimitry Andric void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 154fe6060f1SDimitry Andric void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided); 155fe6060f1SDimitry Andric void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 156979e22ffSDimitry Andric 15704eeddc0SDimitry Andric void selectVSETVLI(SDNode *Node); 15804eeddc0SDimitry Andric 159349cc55cSDimitry Andric // Return the RISC-V condition code that matches the given DAG integer 160349cc55cSDimitry Andric // condition code. The CondCode must be one of those supported by the RISC-V 161349cc55cSDimitry Andric // ISA (see translateSetCCForBranch). 162349cc55cSDimitry Andric static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) { 163349cc55cSDimitry Andric switch (CC) { 164349cc55cSDimitry Andric default: 165349cc55cSDimitry Andric llvm_unreachable("Unsupported CondCode"); 166349cc55cSDimitry Andric case ISD::SETEQ: 167349cc55cSDimitry Andric return RISCVCC::COND_EQ; 168349cc55cSDimitry Andric case ISD::SETNE: 169349cc55cSDimitry Andric return RISCVCC::COND_NE; 170349cc55cSDimitry Andric case ISD::SETLT: 171349cc55cSDimitry Andric return RISCVCC::COND_LT; 172349cc55cSDimitry Andric case ISD::SETGE: 173349cc55cSDimitry Andric return RISCVCC::COND_GE; 174349cc55cSDimitry Andric case ISD::SETULT: 175349cc55cSDimitry Andric return RISCVCC::COND_LTU; 176349cc55cSDimitry Andric case ISD::SETUGE: 177349cc55cSDimitry Andric return RISCVCC::COND_GEU; 178349cc55cSDimitry Andric } 179349cc55cSDimitry Andric } 180349cc55cSDimitry Andric 1815ffd83dbSDimitry Andric // Include the pieces autogenerated from the target description. 1825ffd83dbSDimitry Andric #include "RISCVGenDAGISel.inc" 1835ffd83dbSDimitry Andric 1845ffd83dbSDimitry Andric private: 185349cc55cSDimitry Andric bool doPeepholeSExtW(SDNode *Node); 18681ad6265SDimitry Andric bool doPeepholeMaskedRVV(SDNode *Node); 187bdd1243dSDimitry Andric bool doPeepholeMergeVVMFold(); 188*06c3fb27SDimitry Andric bool performVMergeToVMv(SDNode *N); 189*06c3fb27SDimitry Andric bool performCombineVMergeAndVOps(SDNode *N); 1905ffd83dbSDimitry Andric }; 191fe6060f1SDimitry Andric 192fe6060f1SDimitry Andric namespace RISCV { 193fe6060f1SDimitry Andric struct VLSEGPseudo { 194fe6060f1SDimitry Andric uint16_t NF : 4; 195fe6060f1SDimitry Andric uint16_t Masked : 1; 196fe6060f1SDimitry Andric uint16_t Strided : 1; 197fe6060f1SDimitry Andric uint16_t FF : 1; 198fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 199fe6060f1SDimitry Andric uint16_t LMUL : 3; 200fe6060f1SDimitry Andric uint16_t Pseudo; 201fe6060f1SDimitry Andric }; 202fe6060f1SDimitry Andric 203fe6060f1SDimitry Andric struct VLXSEGPseudo { 204fe6060f1SDimitry Andric uint16_t NF : 4; 205fe6060f1SDimitry Andric uint16_t Masked : 1; 206fe6060f1SDimitry Andric uint16_t Ordered : 1; 207fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 208fe6060f1SDimitry Andric uint16_t LMUL : 3; 209fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 210fe6060f1SDimitry Andric uint16_t Pseudo; 211fe6060f1SDimitry Andric }; 212fe6060f1SDimitry Andric 213fe6060f1SDimitry Andric struct VSSEGPseudo { 214fe6060f1SDimitry Andric uint16_t NF : 4; 215fe6060f1SDimitry Andric uint16_t Masked : 1; 216fe6060f1SDimitry Andric uint16_t Strided : 1; 217fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 218fe6060f1SDimitry Andric uint16_t LMUL : 3; 219fe6060f1SDimitry Andric uint16_t Pseudo; 220fe6060f1SDimitry Andric }; 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric struct VSXSEGPseudo { 223fe6060f1SDimitry Andric uint16_t NF : 4; 224fe6060f1SDimitry Andric uint16_t Masked : 1; 225fe6060f1SDimitry Andric uint16_t Ordered : 1; 226fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 227fe6060f1SDimitry Andric uint16_t LMUL : 3; 228fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 229fe6060f1SDimitry Andric uint16_t Pseudo; 230fe6060f1SDimitry Andric }; 231fe6060f1SDimitry Andric 232fe6060f1SDimitry Andric struct VLEPseudo { 233fe6060f1SDimitry Andric uint16_t Masked : 1; 234fe6060f1SDimitry Andric uint16_t Strided : 1; 235fe6060f1SDimitry Andric uint16_t FF : 1; 236fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 237fe6060f1SDimitry Andric uint16_t LMUL : 3; 238fe6060f1SDimitry Andric uint16_t Pseudo; 239fe6060f1SDimitry Andric }; 240fe6060f1SDimitry Andric 241fe6060f1SDimitry Andric struct VSEPseudo { 242fe6060f1SDimitry Andric uint16_t Masked :1; 243fe6060f1SDimitry Andric uint16_t Strided : 1; 244fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 245fe6060f1SDimitry Andric uint16_t LMUL : 3; 246fe6060f1SDimitry Andric uint16_t Pseudo; 247fe6060f1SDimitry Andric }; 248fe6060f1SDimitry Andric 249fe6060f1SDimitry Andric struct VLX_VSXPseudo { 250fe6060f1SDimitry Andric uint16_t Masked : 1; 251fe6060f1SDimitry Andric uint16_t Ordered : 1; 252fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 253fe6060f1SDimitry Andric uint16_t LMUL : 3; 254fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 255fe6060f1SDimitry Andric uint16_t Pseudo; 256fe6060f1SDimitry Andric }; 257fe6060f1SDimitry Andric 25881ad6265SDimitry Andric struct RISCVMaskedPseudoInfo { 25981ad6265SDimitry Andric uint16_t MaskedPseudo; 26081ad6265SDimitry Andric uint16_t UnmaskedPseudo; 26181ad6265SDimitry Andric uint8_t MaskOpIdx; 26281ad6265SDimitry Andric }; 26381ad6265SDimitry Andric 264fe6060f1SDimitry Andric #define GET_RISCVVSSEGTable_DECL 265fe6060f1SDimitry Andric #define GET_RISCVVLSEGTable_DECL 266fe6060f1SDimitry Andric #define GET_RISCVVLXSEGTable_DECL 267fe6060f1SDimitry Andric #define GET_RISCVVSXSEGTable_DECL 268fe6060f1SDimitry Andric #define GET_RISCVVLETable_DECL 269fe6060f1SDimitry Andric #define GET_RISCVVSETable_DECL 270fe6060f1SDimitry Andric #define GET_RISCVVLXTable_DECL 271fe6060f1SDimitry Andric #define GET_RISCVVSXTable_DECL 27281ad6265SDimitry Andric #define GET_RISCVMaskedPseudosTable_DECL 273fe6060f1SDimitry Andric #include "RISCVGenSearchableTables.inc" 274fe6060f1SDimitry Andric } // namespace RISCV 275fe6060f1SDimitry Andric 276fe6060f1SDimitry Andric } // namespace llvm 2775ffd83dbSDimitry Andric 2785ffd83dbSDimitry Andric #endif 279