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 static char ID; 29bdd1243dSDimitry Andric 30bdd1243dSDimitry Andric RISCVDAGToDAGISel() = delete; 31bdd1243dSDimitry Andric 3281ad6265SDimitry Andric explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine, 33*5f757f3fSDimitry Andric CodeGenOptLevel 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 46*5f757f3fSDimitry Andric bool SelectInlineAsmMemoryOperand(const SDValue &Op, 47*5f757f3fSDimitry Andric InlineAsm::ConstraintCode ConstraintID, 485ffd83dbSDimitry Andric std::vector<SDValue> &OutOps) override; 495ffd83dbSDimitry Andric 5081ad6265SDimitry Andric bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset); 5181ad6265SDimitry Andric bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); 5206c3fb27SDimitry Andric bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset, 5306c3fb27SDimitry Andric bool IsINX = false); 5406c3fb27SDimitry Andric bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) { 5506c3fb27SDimitry Andric return SelectAddrRegImm(Addr, Base, Offset, true); 5606c3fb27SDimitry Andric } 57*5f757f3fSDimitry Andric bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset); 5806c3fb27SDimitry Andric 5906c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount, 6006c3fb27SDimitry Andric SDValue &Base, SDValue &Index, SDValue &Scale); 6106c3fb27SDimitry Andric 6206c3fb27SDimitry Andric template <unsigned MaxShift> 6306c3fb27SDimitry Andric bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 6406c3fb27SDimitry Andric SDValue &Scale) { 6506c3fb27SDimitry Andric return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale); 6606c3fb27SDimitry Andric } 6706c3fb27SDimitry Andric 6806c3fb27SDimitry Andric template <unsigned MaxShift, unsigned Bits> 6906c3fb27SDimitry Andric bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 7006c3fb27SDimitry Andric SDValue &Scale) { 7106c3fb27SDimitry Andric if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) { 7206c3fb27SDimitry Andric if (Index.getOpcode() == ISD::AND) { 7306c3fb27SDimitry Andric auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1)); 7406c3fb27SDimitry Andric if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) { 7506c3fb27SDimitry Andric Index = Index.getOperand(0); 7606c3fb27SDimitry Andric return true; 7706c3fb27SDimitry Andric } 7806c3fb27SDimitry Andric } 7906c3fb27SDimitry Andric } 8006c3fb27SDimitry Andric return false; 8106c3fb27SDimitry Andric } 825ffd83dbSDimitry 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; 124349cc55cSDimitry Andric bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } 125349cc55cSDimitry Andric bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } 126349cc55cSDimitry Andric 12706c3fb27SDimitry Andric bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2); 12806c3fb27SDimitry Andric 129d409305fSDimitry Andric bool selectVLOp(SDValue N, SDValue &VL); 130d409305fSDimitry Andric 131e8d8bef9SDimitry Andric bool selectVSplat(SDValue N, SDValue &SplatVal); 132e8d8bef9SDimitry Andric bool selectVSplatSimm5(SDValue N, SDValue &SplatVal); 13306c3fb27SDimitry Andric bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal); 13406c3fb27SDimitry Andric template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) { 13506c3fb27SDimitry Andric return selectVSplatUimm(N, Bits, Val); 13606c3fb27SDimitry Andric } 137fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal); 138fe6060f1SDimitry Andric bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal); 139*5f757f3fSDimitry Andric // Matches the splat of a value which can be extended or truncated, such that 140*5f757f3fSDimitry Andric // only the bottom 8 bits are preserved. 141*5f757f3fSDimitry Andric bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal); 14206c3fb27SDimitry Andric bool selectFPImm(SDValue N, SDValue &Imm); 143e8d8bef9SDimitry Andric 144fe6060f1SDimitry Andric bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm); 145fe6060f1SDimitry Andric template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) { 146fe6060f1SDimitry Andric return selectRVVSimm5(N, Width, Imm); 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, 150fe6060f1SDimitry Andric const SDLoc &DL, unsigned CurOp, 151fe6060f1SDimitry Andric bool IsMasked, bool IsStridedOrIndexed, 152fe6060f1SDimitry Andric SmallVectorImpl<SDValue> &Operands, 153349cc55cSDimitry Andric bool IsLoad = false, MVT *IndexVT = nullptr); 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided); 156fe6060f1SDimitry Andric void selectVLSEGFF(SDNode *Node, bool IsMasked); 157fe6060f1SDimitry Andric void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 158fe6060f1SDimitry Andric void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided); 159fe6060f1SDimitry Andric void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 160979e22ffSDimitry Andric 16104eeddc0SDimitry Andric void selectVSETVLI(SDNode *Node); 16204eeddc0SDimitry Andric 163349cc55cSDimitry Andric // Return the RISC-V condition code that matches the given DAG integer 164349cc55cSDimitry Andric // condition code. The CondCode must be one of those supported by the RISC-V 165349cc55cSDimitry Andric // ISA (see translateSetCCForBranch). 166349cc55cSDimitry Andric static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) { 167349cc55cSDimitry Andric switch (CC) { 168349cc55cSDimitry Andric default: 169349cc55cSDimitry Andric llvm_unreachable("Unsupported CondCode"); 170349cc55cSDimitry Andric case ISD::SETEQ: 171349cc55cSDimitry Andric return RISCVCC::COND_EQ; 172349cc55cSDimitry Andric case ISD::SETNE: 173349cc55cSDimitry Andric return RISCVCC::COND_NE; 174349cc55cSDimitry Andric case ISD::SETLT: 175349cc55cSDimitry Andric return RISCVCC::COND_LT; 176349cc55cSDimitry Andric case ISD::SETGE: 177349cc55cSDimitry Andric return RISCVCC::COND_GE; 178349cc55cSDimitry Andric case ISD::SETULT: 179349cc55cSDimitry Andric return RISCVCC::COND_LTU; 180349cc55cSDimitry Andric case ISD::SETUGE: 181349cc55cSDimitry Andric return RISCVCC::COND_GEU; 182349cc55cSDimitry Andric } 183349cc55cSDimitry Andric } 184349cc55cSDimitry Andric 1855ffd83dbSDimitry Andric // Include the pieces autogenerated from the target description. 1865ffd83dbSDimitry Andric #include "RISCVGenDAGISel.inc" 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric private: 189349cc55cSDimitry Andric bool doPeepholeSExtW(SDNode *Node); 190*5f757f3fSDimitry Andric bool doPeepholeMaskedRVV(MachineSDNode *Node); 191bdd1243dSDimitry Andric bool doPeepholeMergeVVMFold(); 192*5f757f3fSDimitry Andric bool doPeepholeNoRegPassThru(); 19306c3fb27SDimitry Andric bool performCombineVMergeAndVOps(SDNode *N); 1945ffd83dbSDimitry Andric }; 195fe6060f1SDimitry Andric 196fe6060f1SDimitry Andric namespace RISCV { 197fe6060f1SDimitry Andric struct VLSEGPseudo { 198fe6060f1SDimitry Andric uint16_t NF : 4; 199fe6060f1SDimitry Andric uint16_t Masked : 1; 200fe6060f1SDimitry Andric uint16_t Strided : 1; 201fe6060f1SDimitry Andric uint16_t FF : 1; 202fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 203fe6060f1SDimitry Andric uint16_t LMUL : 3; 204fe6060f1SDimitry Andric uint16_t Pseudo; 205fe6060f1SDimitry Andric }; 206fe6060f1SDimitry Andric 207fe6060f1SDimitry Andric struct VLXSEGPseudo { 208fe6060f1SDimitry Andric uint16_t NF : 4; 209fe6060f1SDimitry Andric uint16_t Masked : 1; 210fe6060f1SDimitry Andric uint16_t Ordered : 1; 211fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 212fe6060f1SDimitry Andric uint16_t LMUL : 3; 213fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 214fe6060f1SDimitry Andric uint16_t Pseudo; 215fe6060f1SDimitry Andric }; 216fe6060f1SDimitry Andric 217fe6060f1SDimitry Andric struct VSSEGPseudo { 218fe6060f1SDimitry Andric uint16_t NF : 4; 219fe6060f1SDimitry Andric uint16_t Masked : 1; 220fe6060f1SDimitry Andric uint16_t Strided : 1; 221fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 222fe6060f1SDimitry Andric uint16_t LMUL : 3; 223fe6060f1SDimitry Andric uint16_t Pseudo; 224fe6060f1SDimitry Andric }; 225fe6060f1SDimitry Andric 226fe6060f1SDimitry Andric struct VSXSEGPseudo { 227fe6060f1SDimitry Andric uint16_t NF : 4; 228fe6060f1SDimitry Andric uint16_t Masked : 1; 229fe6060f1SDimitry Andric uint16_t Ordered : 1; 230fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 231fe6060f1SDimitry Andric uint16_t LMUL : 3; 232fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 233fe6060f1SDimitry Andric uint16_t Pseudo; 234fe6060f1SDimitry Andric }; 235fe6060f1SDimitry Andric 236fe6060f1SDimitry Andric struct VLEPseudo { 237fe6060f1SDimitry Andric uint16_t Masked : 1; 238fe6060f1SDimitry Andric uint16_t Strided : 1; 239fe6060f1SDimitry Andric uint16_t FF : 1; 240fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 241fe6060f1SDimitry Andric uint16_t LMUL : 3; 242fe6060f1SDimitry Andric uint16_t Pseudo; 243fe6060f1SDimitry Andric }; 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric struct VSEPseudo { 246fe6060f1SDimitry Andric uint16_t Masked :1; 247fe6060f1SDimitry Andric uint16_t Strided : 1; 248fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 249fe6060f1SDimitry Andric uint16_t LMUL : 3; 250fe6060f1SDimitry Andric uint16_t Pseudo; 251fe6060f1SDimitry Andric }; 252fe6060f1SDimitry Andric 253fe6060f1SDimitry Andric struct VLX_VSXPseudo { 254fe6060f1SDimitry Andric uint16_t Masked : 1; 255fe6060f1SDimitry Andric uint16_t Ordered : 1; 256fe6060f1SDimitry Andric uint16_t Log2SEW : 3; 257fe6060f1SDimitry Andric uint16_t LMUL : 3; 258fe6060f1SDimitry Andric uint16_t IndexLMUL : 3; 259fe6060f1SDimitry Andric uint16_t Pseudo; 260fe6060f1SDimitry Andric }; 261fe6060f1SDimitry Andric 26281ad6265SDimitry Andric struct RISCVMaskedPseudoInfo { 26381ad6265SDimitry Andric uint16_t MaskedPseudo; 26481ad6265SDimitry Andric uint16_t UnmaskedPseudo; 26581ad6265SDimitry Andric uint8_t MaskOpIdx; 266*5f757f3fSDimitry Andric uint8_t MaskAffectsResult : 1; 26781ad6265SDimitry Andric }; 26881ad6265SDimitry Andric 269fe6060f1SDimitry Andric #define GET_RISCVVSSEGTable_DECL 270fe6060f1SDimitry Andric #define GET_RISCVVLSEGTable_DECL 271fe6060f1SDimitry Andric #define GET_RISCVVLXSEGTable_DECL 272fe6060f1SDimitry Andric #define GET_RISCVVSXSEGTable_DECL 273fe6060f1SDimitry Andric #define GET_RISCVVLETable_DECL 274fe6060f1SDimitry Andric #define GET_RISCVVSETable_DECL 275fe6060f1SDimitry Andric #define GET_RISCVVLXTable_DECL 276fe6060f1SDimitry Andric #define GET_RISCVVSXTable_DECL 27781ad6265SDimitry Andric #define GET_RISCVMaskedPseudosTable_DECL 278fe6060f1SDimitry Andric #include "RISCVGenSearchableTables.inc" 279fe6060f1SDimitry Andric } // namespace RISCV 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric } // namespace llvm 2825ffd83dbSDimitry Andric 2835ffd83dbSDimitry Andric #endif 284