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 
RISCVDAGToDAGISel(RISCVTargetMachine & TargetMachine,CodeGenOptLevel OptLevel)32   explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine,
33                              CodeGenOptLevel OptLevel)
34       : SelectionDAGISel(ID, TargetMachine, OptLevel) {}
35 
runOnMachineFunction(MachineFunction & MF)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);
SelectAddrRegImmINX(SDValue Addr,SDValue & Base,SDValue & Offset)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>
SelectAddrRegRegScale(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Scale)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>
SelectAddrRegZextRegScale(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Scale)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);
selectShiftMaskXLen(SDValue N,SDValue & ShAmt)88   bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
89     return selectShiftMask(N, Subtarget->getXLen(), ShAmt);
90   }
selectShiftMask32(SDValue N,SDValue & ShAmt)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);
selectSETNE(SDValue N,SDValue & Val)96   bool selectSETNE(SDValue N, SDValue &Val) {
97     return selectSETCC(N, ISD::SETNE, Val);
98   }
selectSETEQ(SDValue N,SDValue & Val)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);
selectSExtBits(SDValue N,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);
selectZExtBits(SDValue N,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);
selectSHXADDOp(SDValue N,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);
selectSHXADD_UWOp(SDValue N,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;
hasAllHUsers(SDNode * Node)124   bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); }
hasAllWUsers(SDNode * Node)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);
selectVSplatUimmBits(SDValue N,SDValue & Val)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);
selectRVVSimm5(SDValue N,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).
getRISCVCCForIntCC(ISD::CondCode CC)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