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 CodeGenOptLevel 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, 47 InlineAsm::ConstraintCode ConstraintID, 48 std::vector<SDValue> &OutOps) override; 49 50 bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset); 51 bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset); 52 bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset, 53 bool IsINX = false); 54 bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) { 55 return SelectAddrRegImm(Addr, Base, Offset, true); 56 } 57 bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset); 58 59 bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount, 60 SDValue &Base, SDValue &Index, SDValue &Scale); 61 62 template <unsigned MaxShift> 63 bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 64 SDValue &Scale) { 65 return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale); 66 } 67 68 template <unsigned MaxShift, unsigned Bits> 69 bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index, 70 SDValue &Scale) { 71 if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) { 72 if (Index.getOpcode() == ISD::AND) { 73 auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1)); 74 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) { 75 Index = Index.getOperand(0); 76 return true; 77 } 78 } 79 } 80 return false; 81 } 82 83 bool tryShrinkShlLogicImm(SDNode *Node); 84 bool trySignedBitfieldExtract(SDNode *Node); 85 bool tryIndexedLoad(SDNode *Node); 86 87 bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt); 88 bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) { 89 return selectShiftMask(N, Subtarget->getXLen(), ShAmt); 90 } 91 bool selectShiftMask32(SDValue N, SDValue &ShAmt) { 92 return selectShiftMask(N, 32, ShAmt); 93 } 94 95 bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val); 96 bool selectSETNE(SDValue N, SDValue &Val) { 97 return selectSETCC(N, ISD::SETNE, Val); 98 } 99 bool selectSETEQ(SDValue N, SDValue &Val) { 100 return selectSETCC(N, ISD::SETEQ, Val); 101 } 102 103 bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val); 104 template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) { 105 return selectSExtBits(N, Bits, Val); 106 } 107 bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val); 108 template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) { 109 return selectZExtBits(N, Bits, Val); 110 } 111 112 bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val); 113 template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) { 114 return selectSHXADDOp(N, ShAmt, Val); 115 } 116 117 bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val); 118 template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) { 119 return selectSHXADD_UWOp(N, ShAmt, Val); 120 } 121 122 bool hasAllNBitUsers(SDNode *Node, unsigned Bits, 123 const unsigned Depth = 0) const; 124 bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); } 125 bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); } 126 127 bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2); 128 129 bool selectVLOp(SDValue N, SDValue &VL); 130 131 bool selectVSplat(SDValue N, SDValue &SplatVal); 132 bool selectVSplatSimm5(SDValue N, SDValue &SplatVal); 133 bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal); 134 template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) { 135 return selectVSplatUimm(N, Bits, Val); 136 } 137 bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal); 138 bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal); 139 // Matches the splat of a value which can be extended or truncated, such that 140 // only the bottom 8 bits are preserved. 141 bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal); 142 bool selectFPImm(SDValue N, SDValue &Imm); 143 144 bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm); 145 template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) { 146 return selectRVVSimm5(N, Width, Imm); 147 } 148 149 void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm, 150 const SDLoc &DL, unsigned CurOp, 151 bool IsMasked, bool IsStridedOrIndexed, 152 SmallVectorImpl<SDValue> &Operands, 153 bool IsLoad = false, MVT *IndexVT = nullptr); 154 155 void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided); 156 void selectVLSEGFF(SDNode *Node, bool IsMasked); 157 void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 158 void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided); 159 void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered); 160 161 void selectVSETVLI(SDNode *Node); 162 163 // Return the RISC-V condition code that matches the given DAG integer 164 // condition code. The CondCode must be one of those supported by the RISC-V 165 // ISA (see translateSetCCForBranch). 166 static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) { 167 switch (CC) { 168 default: 169 llvm_unreachable("Unsupported CondCode"); 170 case ISD::SETEQ: 171 return RISCVCC::COND_EQ; 172 case ISD::SETNE: 173 return RISCVCC::COND_NE; 174 case ISD::SETLT: 175 return RISCVCC::COND_LT; 176 case ISD::SETGE: 177 return RISCVCC::COND_GE; 178 case ISD::SETULT: 179 return RISCVCC::COND_LTU; 180 case ISD::SETUGE: 181 return RISCVCC::COND_GEU; 182 } 183 } 184 185 // Include the pieces autogenerated from the target description. 186 #include "RISCVGenDAGISel.inc" 187 188 private: 189 bool doPeepholeSExtW(SDNode *Node); 190 bool doPeepholeMaskedRVV(MachineSDNode *Node); 191 bool doPeepholeMergeVVMFold(); 192 bool doPeepholeNoRegPassThru(); 193 bool performCombineVMergeAndVOps(SDNode *N); 194 }; 195 196 namespace RISCV { 197 struct VLSEGPseudo { 198 uint16_t NF : 4; 199 uint16_t Masked : 1; 200 uint16_t Strided : 1; 201 uint16_t FF : 1; 202 uint16_t Log2SEW : 3; 203 uint16_t LMUL : 3; 204 uint16_t Pseudo; 205 }; 206 207 struct VLXSEGPseudo { 208 uint16_t NF : 4; 209 uint16_t Masked : 1; 210 uint16_t Ordered : 1; 211 uint16_t Log2SEW : 3; 212 uint16_t LMUL : 3; 213 uint16_t IndexLMUL : 3; 214 uint16_t Pseudo; 215 }; 216 217 struct VSSEGPseudo { 218 uint16_t NF : 4; 219 uint16_t Masked : 1; 220 uint16_t Strided : 1; 221 uint16_t Log2SEW : 3; 222 uint16_t LMUL : 3; 223 uint16_t Pseudo; 224 }; 225 226 struct VSXSEGPseudo { 227 uint16_t NF : 4; 228 uint16_t Masked : 1; 229 uint16_t Ordered : 1; 230 uint16_t Log2SEW : 3; 231 uint16_t LMUL : 3; 232 uint16_t IndexLMUL : 3; 233 uint16_t Pseudo; 234 }; 235 236 struct VLEPseudo { 237 uint16_t Masked : 1; 238 uint16_t Strided : 1; 239 uint16_t FF : 1; 240 uint16_t Log2SEW : 3; 241 uint16_t LMUL : 3; 242 uint16_t Pseudo; 243 }; 244 245 struct VSEPseudo { 246 uint16_t Masked :1; 247 uint16_t Strided : 1; 248 uint16_t Log2SEW : 3; 249 uint16_t LMUL : 3; 250 uint16_t Pseudo; 251 }; 252 253 struct VLX_VSXPseudo { 254 uint16_t Masked : 1; 255 uint16_t Ordered : 1; 256 uint16_t Log2SEW : 3; 257 uint16_t LMUL : 3; 258 uint16_t IndexLMUL : 3; 259 uint16_t Pseudo; 260 }; 261 262 struct RISCVMaskedPseudoInfo { 263 uint16_t MaskedPseudo; 264 uint16_t UnmaskedPseudo; 265 uint8_t MaskOpIdx; 266 uint8_t MaskAffectsResult : 1; 267 }; 268 269 #define GET_RISCVVSSEGTable_DECL 270 #define GET_RISCVVLSEGTable_DECL 271 #define GET_RISCVVLXSEGTable_DECL 272 #define GET_RISCVVSXSEGTable_DECL 273 #define GET_RISCVVLETable_DECL 274 #define GET_RISCVVSETable_DECL 275 #define GET_RISCVVLXTable_DECL 276 #define GET_RISCVVSXTable_DECL 277 #define GET_RISCVMaskedPseudosTable_DECL 278 #include "RISCVGenSearchableTables.inc" 279 } // namespace RISCV 280 281 } // namespace llvm 282 283 #endif 284