106c3fb27SDimitry 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 // 906c3fb27SDimitry 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 2106c3fb27SDimitry 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 RISCVDAGToDAGISel() = delete; 29bdd1243dSDimitry Andric 3081ad6265SDimitry Andric explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine, 315f757f3fSDimitry Andric CodeGenOptLevel OptLevel) 32*0fca6ea1SDimitry Andric : SelectionDAGISel(TargetMachine, OptLevel) {} 335ffd83dbSDimitry Andric 345ffd83dbSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 355ffd83dbSDimitry Andric Subtarget = &MF.getSubtarget<RISCVSubtarget>(); 365ffd83dbSDimitry Andric return SelectionDAGISel::runOnMachineFunction(MF); 375ffd83dbSDimitry Andric } 385ffd83dbSDimitry Andric 39fe6060f1SDimitry Andric void PreprocessISelDAG() override; 405ffd83dbSDimitry Andric void PostprocessISelDAG() override; 415ffd83dbSDimitry Andric 425ffd83dbSDimitry Andric void Select(SDNode *Node) override; 435ffd83dbSDimitry Andric 445f757f3fSDimitry Andric bool SelectInlineAsmMemoryOperand(const SDValue &Op, 455f757f3fSDimitry Andric InlineAsm::ConstraintCode ConstraintID, 465ffd83dbSDimitry Andric std::vector<SDValue> &OutOps) override; 475ffd83dbSDimitry Andric 4881ad6265SDimitry Andric bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset); 4981ad6265SDimitry Andric bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); 5006c3fb27SDimitry Andric bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset, 5106c3fb27SDimitry Andric bool IsINX = false); 5206c3fb27SDimitry Andric bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) { 5306c3fb27SDimitry Andric return SelectAddrRegImm(Addr, Base, Offset, true); 5406c3fb27SDimitry Andric } 555f757f3fSDimitry Andric bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset); 5606c3fb27SDimitry Andric 5706c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount, 5806c3fb27SDimitry Andric SDValue &Base, SDValue &Index, SDValue &Scale); 5906c3fb27SDimitry Andric 6006c3fb27SDimitry Andric template <unsigned MaxShift> 6106c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 6206c3fb27SDimitry Andric SDValue &Scale) { 6306c3fb27SDimitry Andric return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale); 6406c3fb27SDimitry Andric } 6506c3fb27SDimitry Andric 6606c3fb27SDimitry Andric template <unsigned MaxShift, unsigned Bits> 6706c3fb27SDimitry Andric bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 6806c3fb27SDimitry Andric SDValue &Scale) { 6906c3fb27SDimitry Andric if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) { 7006c3fb27SDimitry Andric if (Index.getOpcode() == ISD::AND) { 7106c3fb27SDimitry Andric auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1)); 7206c3fb27SDimitry Andric if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) { 7306c3fb27SDimitry Andric Index = Index.getOperand(0); 7406c3fb27SDimitry Andric return true; 7506c3fb27SDimitry Andric } 7606c3fb27SDimitry Andric } 7706c3fb27SDimitry Andric } 7806c3fb27SDimitry Andric return false; 7906c3fb27SDimitry Andric } 805ffd83dbSDimitry Andric 81*0fca6ea1SDimitry Andric bool SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset); 82*0fca6ea1SDimitry Andric 83bdd1243dSDimitry Andric bool tryShrinkShlLogicImm(SDNode *Node); 8406c3fb27SDimitry Andric bool trySignedBitfieldExtract(SDNode *Node); 8506c3fb27SDimitry Andric bool tryIndexedLoad(SDNode *Node); 86bdd1243dSDimitry Andric 87fe6060f1SDimitry Andric bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); 88fe6060f1SDimitry Andric bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) { 89fe6060f1SDimitry Andric return selectShiftMask(N, Subtarget->getXLen(), ShAmt); 90fe6060f1SDimitry Andric } 91fe6060f1SDimitry Andric bool selectShiftMask32(SDValue N, SDValue &ShAmt) { 92fe6060f1SDimitry Andric return selectShiftMask(N, 32, ShAmt); 93fe6060f1SDimitry Andric } 94fe6060f1SDimitry Andric 9506c3fb27SDimitry Andric bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val); 9606c3fb27SDimitry Andric bool selectSETNE(SDValue N, SDValue &Val) { 9706c3fb27SDimitry Andric return selectSETCC(N, ISD::SETNE, Val); 9806c3fb27SDimitry Andric } 9906c3fb27SDimitry Andric bool selectSETEQ(SDValue N, SDValue &Val) { 10006c3fb27SDimitry Andric return selectSETCC(N, ISD::SETEQ, Val); 10106c3fb27SDimitry Andric } 10206c3fb27SDimitry Andric 10306c3fb27SDimitry Andric bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val); 10406c3fb27SDimitry Andric template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) { 10506c3fb27SDimitry Andric return selectSExtBits(N, Bits, Val); 10606c3fb27SDimitry Andric } 107bdd1243dSDimitry Andric bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val); 108bdd1243dSDimitry Andric template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) { 109bdd1243dSDimitry Andric return selectZExtBits(N, Bits, Val); 110bdd1243dSDimitry Andric } 111e8d8bef9SDimitry Andric 112753f127fSDimitry Andric bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val); 113bdd1243dSDimitry Andric template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) { 114bdd1243dSDimitry Andric return selectSHXADDOp(N, ShAmt, Val); 115753f127fSDimitry Andric } 116753f127fSDimitry Andric 117bdd1243dSDimitry Andric bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val); 118bdd1243dSDimitry Andric template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) { 119bdd1243dSDimitry Andric return selectSHXADD_UWOp(N, ShAmt, Val); 120bdd1243dSDimitry Andric } 121bdd1243dSDimitry Andric 122bdd1243dSDimitry Andric bool hasAllNBitUsers(SDNode *Node, unsigned Bits, 123bdd1243dSDimitry Andric const unsigned Depth = 0) const; 124*0fca6ea1SDimitry Andric bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); } 125349cc55cSDimitry Andric bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } 126349cc55cSDimitry Andric bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } 127349cc55cSDimitry Andric 12806c3fb27SDimitry Andric bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2); 12906c3fb27SDimitry Andric 130d409305fSDimitry Andric bool selectVLOp(SDValue N, SDValue &VL); 131d409305fSDimitry Andric 132e8d8bef9SDimitry Andric bool selectVSplat(SDValue N, SDValue &SplatVal); 133e8d8bef9SDimitry Andric bool selectVSplatSimm5(SDValue N, SDValue &SplatVal); 13406c3fb27SDimitry Andric bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal); 13506c3fb27SDimitry Andric template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) { 13606c3fb27SDimitry Andric return selectVSplatUimm(N, Bits, Val); 13706c3fb27SDimitry Andric } 138fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal); 139fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal); 1405f757f3fSDimitry Andric // Matches the splat of a value which can be extended or truncated, such that 1415f757f3fSDimitry Andric // only the bottom 8 bits are preserved. 1425f757f3fSDimitry Andric bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal); 14306c3fb27SDimitry Andric bool selectFPImm(SDValue N, SDValue &Imm); 144e8d8bef9SDimitry Andric 145fe6060f1SDimitry Andric bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm); 146fe6060f1SDimitry Andric template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) { 147fe6060f1SDimitry Andric return selectRVVSimm5(N, Width, Imm); 148fe6060f1SDimitry Andric } 149fe6060f1SDimitry Andric 150fe6060f1SDimitry Andric void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, 151fe6060f1SDimitry Andric const SDLoc &DL, unsigned CurOp, 152fe6060f1SDimitry Andric bool IsMasked, bool IsStridedOrIndexed, 153fe6060f1SDimitry Andric SmallVectorImpl<SDValue> &Operands, 154349cc55cSDimitry Andric bool IsLoad = false, MVT *IndexVT = nullptr); 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided); 157fe6060f1SDimitry Andric void selectVLSEGFF(SDNode *Node, bool IsMasked); 158fe6060f1SDimitry Andric void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 159fe6060f1SDimitry Andric void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided); 160fe6060f1SDimitry Andric void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 161979e22ffSDimitry Andric 16204eeddc0SDimitry Andric void selectVSETVLI(SDNode *Node); 16304eeddc0SDimitry Andric 164*0fca6ea1SDimitry Andric void selectSF_VC_X_SE(SDNode *Node); 165*0fca6ea1SDimitry Andric 166349cc55cSDimitry Andric // Return the RISC-V condition code that matches the given DAG integer 167349cc55cSDimitry Andric // condition code. The CondCode must be one of those supported by the RISC-V 168349cc55cSDimitry Andric // ISA (see translateSetCCForBranch). 169349cc55cSDimitry Andric static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) { 170349cc55cSDimitry Andric switch (CC) { 171349cc55cSDimitry Andric default: 172349cc55cSDimitry Andric llvm_unreachable("Unsupported CondCode"); 173349cc55cSDimitry Andric case ISD::SETEQ: 174349cc55cSDimitry Andric return RISCVCC::COND_EQ; 175349cc55cSDimitry Andric case ISD::SETNE: 176349cc55cSDimitry Andric return RISCVCC::COND_NE; 177349cc55cSDimitry Andric case ISD::SETLT: 178349cc55cSDimitry Andric return RISCVCC::COND_LT; 179349cc55cSDimitry Andric case ISD::SETGE: 180349cc55cSDimitry Andric return RISCVCC::COND_GE; 181349cc55cSDimitry Andric case ISD::SETULT: 182349cc55cSDimitry Andric return RISCVCC::COND_LTU; 183349cc55cSDimitry Andric case ISD::SETUGE: 184349cc55cSDimitry Andric return RISCVCC::COND_GEU; 185349cc55cSDimitry Andric } 186349cc55cSDimitry Andric } 187349cc55cSDimitry Andric 1885ffd83dbSDimitry Andric // Include the pieces autogenerated from the target description. 1895ffd83dbSDimitry Andric #include "RISCVGenDAGISel.inc" 1905ffd83dbSDimitry Andric 1915ffd83dbSDimitry Andric private: 192349cc55cSDimitry Andric bool doPeepholeSExtW(SDNode *Node); 1935f757f3fSDimitry Andric bool doPeepholeMaskedRVV(MachineSDNode *Node); 194bdd1243dSDimitry Andric bool doPeepholeMergeVVMFold(); 1955f757f3fSDimitry Andric bool doPeepholeNoRegPassThru(); 19606c3fb27SDimitry Andric bool performCombineVMergeAndVOps(SDNode *N); 1975ffd83dbSDimitry Andric }; 198fe6060f1SDimitry Andric 199*0fca6ea1SDimitry Andric class RISCVDAGToDAGISelLegacy : public SelectionDAGISelLegacy { 200*0fca6ea1SDimitry Andric public: 201*0fca6ea1SDimitry Andric static char ID; 202*0fca6ea1SDimitry Andric explicit RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TargetMachine, 203*0fca6ea1SDimitry Andric CodeGenOptLevel OptLevel); 204*0fca6ea1SDimitry Andric }; 205*0fca6ea1SDimitry Andric 206fe6060f1SDimitry Andric namespace RISCV { 207fe6060f1SDimitry Andric struct VLSEGPseudo { 208fe6060f1SDimitry Andric uint16_t NF : 4; 209fe6060f1SDimitry Andric uint16_t Masked : 1; 210fe6060f1SDimitry Andric uint16_t Strided : 1; 211fe6060f1SDimitry Andric uint16_t FF : 1; 212fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 213fe6060f1SDimitry Andric uint16_t LMUL : 3; 214fe6060f1SDimitry Andric uint16_t Pseudo; 215fe6060f1SDimitry Andric }; 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric struct VLXSEGPseudo { 218fe6060f1SDimitry Andric uint16_t NF : 4; 219fe6060f1SDimitry Andric uint16_t Masked : 1; 220fe6060f1SDimitry Andric uint16_t Ordered : 1; 221fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 222fe6060f1SDimitry Andric uint16_t LMUL : 3; 223fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 224fe6060f1SDimitry Andric uint16_t Pseudo; 225fe6060f1SDimitry Andric }; 226fe6060f1SDimitry Andric 227fe6060f1SDimitry Andric struct VSSEGPseudo { 228fe6060f1SDimitry Andric uint16_t NF : 4; 229fe6060f1SDimitry Andric uint16_t Masked : 1; 230fe6060f1SDimitry Andric uint16_t Strided : 1; 231fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 232fe6060f1SDimitry Andric uint16_t LMUL : 3; 233fe6060f1SDimitry Andric uint16_t Pseudo; 234fe6060f1SDimitry Andric }; 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric struct VSXSEGPseudo { 237fe6060f1SDimitry Andric uint16_t NF : 4; 238fe6060f1SDimitry Andric uint16_t Masked : 1; 239fe6060f1SDimitry Andric uint16_t Ordered : 1; 240fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 241fe6060f1SDimitry Andric uint16_t LMUL : 3; 242fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 243fe6060f1SDimitry Andric uint16_t Pseudo; 244fe6060f1SDimitry Andric }; 245fe6060f1SDimitry Andric 246fe6060f1SDimitry Andric struct VLEPseudo { 247fe6060f1SDimitry Andric uint16_t Masked : 1; 248fe6060f1SDimitry Andric uint16_t Strided : 1; 249fe6060f1SDimitry Andric uint16_t FF : 1; 250fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 251fe6060f1SDimitry Andric uint16_t LMUL : 3; 252fe6060f1SDimitry Andric uint16_t Pseudo; 253fe6060f1SDimitry Andric }; 254fe6060f1SDimitry Andric 255fe6060f1SDimitry Andric struct VSEPseudo { 256fe6060f1SDimitry Andric uint16_t Masked :1; 257fe6060f1SDimitry Andric uint16_t Strided : 1; 258fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 259fe6060f1SDimitry Andric uint16_t LMUL : 3; 260fe6060f1SDimitry Andric uint16_t Pseudo; 261fe6060f1SDimitry Andric }; 262fe6060f1SDimitry Andric 263fe6060f1SDimitry Andric struct VLX_VSXPseudo { 264fe6060f1SDimitry Andric uint16_t Masked : 1; 265fe6060f1SDimitry Andric uint16_t Ordered : 1; 266fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 267fe6060f1SDimitry Andric uint16_t LMUL : 3; 268fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 269fe6060f1SDimitry Andric uint16_t Pseudo; 270fe6060f1SDimitry Andric }; 271fe6060f1SDimitry Andric 272fe6060f1SDimitry Andric #define GET_RISCVVSSEGTable_DECL 273fe6060f1SDimitry Andric #define GET_RISCVVLSEGTable_DECL 274fe6060f1SDimitry Andric #define GET_RISCVVLXSEGTable_DECL 275fe6060f1SDimitry Andric #define GET_RISCVVSXSEGTable_DECL 276fe6060f1SDimitry Andric #define GET_RISCVVLETable_DECL 277fe6060f1SDimitry Andric #define GET_RISCVVSETable_DECL 278fe6060f1SDimitry Andric #define GET_RISCVVLXTable_DECL 279fe6060f1SDimitry Andric #define GET_RISCVVSXTable_DECL 280fe6060f1SDimitry Andric } // namespace RISCV 281fe6060f1SDimitry Andric 282fe6060f1SDimitry Andric } // namespace llvm 2835ffd83dbSDimitry Andric 2845ffd83dbSDimitry Andric #endif 285