1 //===---- RISCVISelDAGToDAG.h - A dag to dag inst selector for RISC-V -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines an instruction selector for the RISC-V target. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_TARGET_RISCV_RISCVISELDAGTODAG_H 14 #define LLVM_LIB_TARGET_RISCV_RISCVISELDAGTODAG_H 15 16 #include "RISCV.h" 17 #include "RISCVTargetMachine.h" 18 #include "llvm/CodeGen/SelectionDAGISel.h" 19 #include "llvm/Support/KnownBits.h" 20 21 // RISC-V specific code to select RISC-V machine instructions for 22 // SelectionDAG operations. 23 namespace llvm { 24 class RISCVDAGToDAGISel : public SelectionDAGISel { 25 const RISCVSubtarget *Subtarget = nullptr; 26 27 public: 28 static char ID; 29 30 RISCVDAGToDAGISel() = delete; 31 32 explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine, 33 CodeGenOpt::Level OptLevel) 34 : SelectionDAGISel(ID, TargetMachine, OptLevel) {} 35 36 bool runOnMachineFunction(MachineFunction &MF) override { 37 Subtarget = &MF.getSubtarget<RISCVSubtarget>(); 38 return SelectionDAGISel::runOnMachineFunction(MF); 39 } 40 41 void PreprocessISelDAG() override; 42 void PostprocessISelDAG() override; 43 44 void Select(SDNode *Node) override; 45 46 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, 47 std::vector<SDValue> &OutOps) override; 48 49 bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset); 50 bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); 51 bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset, 52 bool IsINX = false); 53 bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) { 54 return SelectAddrRegImm(Addr, Base, Offset, true); 55 } 56 57 bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount, 58 SDValue &Base, SDValue &Index, SDValue &Scale); 59 60 template <unsigned MaxShift> 61 bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 62 SDValue &Scale) { 63 return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale); 64 } 65 66 template <unsigned MaxShift, unsigned Bits> 67 bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 68 SDValue &Scale) { 69 if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) { 70 if (Index.getOpcode() == ISD::AND) { 71 auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1)); 72 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) { 73 Index = Index.getOperand(0); 74 return true; 75 } 76 } 77 } 78 return false; 79 } 80 81 bool tryShrinkShlLogicImm(SDNode *Node); 82 bool trySignedBitfieldExtract(SDNode *Node); 83 bool tryIndexedLoad(SDNode *Node); 84 85 bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); 86 bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) { 87 return selectShiftMask(N, Subtarget->getXLen(), ShAmt); 88 } 89 bool selectShiftMask32(SDValue N, SDValue &ShAmt) { 90 return selectShiftMask(N, 32, ShAmt); 91 } 92 93 bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val); 94 bool selectSETNE(SDValue N, SDValue &Val) { 95 return selectSETCC(N, ISD::SETNE, Val); 96 } 97 bool selectSETEQ(SDValue N, SDValue &Val) { 98 return selectSETCC(N, ISD::SETEQ, Val); 99 } 100 101 bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val); 102 template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) { 103 return selectSExtBits(N, Bits, Val); 104 } 105 bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val); 106 template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) { 107 return selectZExtBits(N, Bits, Val); 108 } 109 110 bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val); 111 template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) { 112 return selectSHXADDOp(N, ShAmt, Val); 113 } 114 115 bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val); 116 template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) { 117 return selectSHXADD_UWOp(N, ShAmt, Val); 118 } 119 120 bool hasAllNBitUsers(SDNode *Node, unsigned Bits, 121 const unsigned Depth = 0) const; 122 bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } 123 bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } 124 125 bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2); 126 127 bool selectVLOp(SDValue N, SDValue &VL); 128 129 bool selectVSplat(SDValue N, SDValue &SplatVal); 130 bool selectVSplatSimm5(SDValue N, SDValue &SplatVal); 131 bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal); 132 template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) { 133 return selectVSplatUimm(N, Bits, Val); 134 } 135 bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal); 136 bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal); 137 bool selectExtOneUseVSplat(SDValue N, SDValue &SplatVal); 138 bool selectFPImm(SDValue N, SDValue &Imm); 139 140 bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm); 141 template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) { 142 return selectRVVSimm5(N, Width, Imm); 143 } 144 145 void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, 146 const SDLoc &DL, unsigned CurOp, 147 bool IsMasked, bool IsStridedOrIndexed, 148 SmallVectorImpl<SDValue> &Operands, 149 bool IsLoad = false, MVT *IndexVT = nullptr); 150 151 void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided); 152 void selectVLSEGFF(SDNode *Node, bool IsMasked); 153 void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 154 void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided); 155 void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 156 157 void selectVSETVLI(SDNode *Node); 158 159 // Return the RISC-V condition code that matches the given DAG integer 160 // condition code. The CondCode must be one of those supported by the RISC-V 161 // ISA (see translateSetCCForBranch). 162 static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) { 163 switch (CC) { 164 default: 165 llvm_unreachable("Unsupported CondCode"); 166 case ISD::SETEQ: 167 return RISCVCC::COND_EQ; 168 case ISD::SETNE: 169 return RISCVCC::COND_NE; 170 case ISD::SETLT: 171 return RISCVCC::COND_LT; 172 case ISD::SETGE: 173 return RISCVCC::COND_GE; 174 case ISD::SETULT: 175 return RISCVCC::COND_LTU; 176 case ISD::SETUGE: 177 return RISCVCC::COND_GEU; 178 } 179 } 180 181 // Include the pieces autogenerated from the target description. 182 #include "RISCVGenDAGISel.inc" 183 184 private: 185 bool doPeepholeSExtW(SDNode *Node); 186 bool doPeepholeMaskedRVV(SDNode *Node); 187 bool doPeepholeMergeVVMFold(); 188 bool performVMergeToVMv(SDNode *N); 189 bool performCombineVMergeAndVOps(SDNode *N); 190 }; 191 192 namespace RISCV { 193 struct VLSEGPseudo { 194 uint16_t NF : 4; 195 uint16_t Masked : 1; 196 uint16_t Strided : 1; 197 uint16_t FF : 1; 198 uint16_t Log2SEW : 3; 199 uint16_t LMUL : 3; 200 uint16_t Pseudo; 201 }; 202 203 struct VLXSEGPseudo { 204 uint16_t NF : 4; 205 uint16_t Masked : 1; 206 uint16_t Ordered : 1; 207 uint16_t Log2SEW : 3; 208 uint16_t LMUL : 3; 209 uint16_t IndexLMUL : 3; 210 uint16_t Pseudo; 211 }; 212 213 struct VSSEGPseudo { 214 uint16_t NF : 4; 215 uint16_t Masked : 1; 216 uint16_t Strided : 1; 217 uint16_t Log2SEW : 3; 218 uint16_t LMUL : 3; 219 uint16_t Pseudo; 220 }; 221 222 struct VSXSEGPseudo { 223 uint16_t NF : 4; 224 uint16_t Masked : 1; 225 uint16_t Ordered : 1; 226 uint16_t Log2SEW : 3; 227 uint16_t LMUL : 3; 228 uint16_t IndexLMUL : 3; 229 uint16_t Pseudo; 230 }; 231 232 struct VLEPseudo { 233 uint16_t Masked : 1; 234 uint16_t Strided : 1; 235 uint16_t FF : 1; 236 uint16_t Log2SEW : 3; 237 uint16_t LMUL : 3; 238 uint16_t Pseudo; 239 }; 240 241 struct VSEPseudo { 242 uint16_t Masked :1; 243 uint16_t Strided : 1; 244 uint16_t Log2SEW : 3; 245 uint16_t LMUL : 3; 246 uint16_t Pseudo; 247 }; 248 249 struct VLX_VSXPseudo { 250 uint16_t Masked : 1; 251 uint16_t Ordered : 1; 252 uint16_t Log2SEW : 3; 253 uint16_t LMUL : 3; 254 uint16_t IndexLMUL : 3; 255 uint16_t Pseudo; 256 }; 257 258 struct RISCVMaskedPseudoInfo { 259 uint16_t MaskedPseudo; 260 uint16_t UnmaskedPseudo; 261 uint8_t MaskOpIdx; 262 }; 263 264 #define GET_RISCVVSSEGTable_DECL 265 #define GET_RISCVVLSEGTable_DECL 266 #define GET_RISCVVLXSEGTable_DECL 267 #define GET_RISCVVSXSEGTable_DECL 268 #define GET_RISCVVLETable_DECL 269 #define GET_RISCVVSETable_DECL 270 #define GET_RISCVVLXTable_DECL 271 #define GET_RISCVVSXTable_DECL 272 #define GET_RISCVMaskedPseudosTable_DECL 273 #include "RISCVGenSearchableTables.inc" 274 } // namespace RISCV 275 276 } // namespace llvm 277 278 #endif 279