1 //===---- RISCVISelDAGToDAG.h - A dag to dag inst selector for RISCV ------===//
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 RISCV 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 // RISCV-specific code to select RISCV 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 
53   bool tryShrinkShlLogicImm(SDNode *Node);
54 
55   bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
56   bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
57     return selectShiftMask(N, Subtarget->getXLen(), ShAmt);
58   }
59   bool selectShiftMask32(SDValue N, SDValue &ShAmt) {
60     return selectShiftMask(N, 32, ShAmt);
61   }
62 
63   bool selectSExti32(SDValue N, SDValue &Val);
64   bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val);
65   template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) {
66     return selectZExtBits(N, Bits, Val);
67   }
68 
69   bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val);
70   template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) {
71     return selectSHXADDOp(N, ShAmt, Val);
72   }
73 
74   bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val);
75   template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) {
76     return selectSHXADD_UWOp(N, ShAmt, Val);
77   }
78 
79   bool hasAllNBitUsers(SDNode *Node, unsigned Bits,
80                        const unsigned Depth = 0) const;
81   bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); }
82   bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); }
83 
84   bool selectVLOp(SDValue N, SDValue &VL);
85 
86   bool selectVSplat(SDValue N, SDValue &SplatVal);
87   bool selectVSplatSimm5(SDValue N, SDValue &SplatVal);
88   bool selectVSplatUimm5(SDValue N, SDValue &SplatVal);
89   bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal);
90   bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal);
91 
92   bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm);
93   template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) {
94     return selectRVVSimm5(N, Width, Imm);
95   }
96 
97   void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm,
98                                   const SDLoc &DL, unsigned CurOp,
99                                   bool IsMasked, bool IsStridedOrIndexed,
100                                   SmallVectorImpl<SDValue> &Operands,
101                                   bool IsLoad = false, MVT *IndexVT = nullptr);
102 
103   void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided);
104   void selectVLSEGFF(SDNode *Node, bool IsMasked);
105   void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
106   void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided);
107   void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
108 
109   void selectVSETVLI(SDNode *Node);
110 
111   // Return the RISC-V condition code that matches the given DAG integer
112   // condition code. The CondCode must be one of those supported by the RISC-V
113   // ISA (see translateSetCCForBranch).
114   static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
115     switch (CC) {
116     default:
117       llvm_unreachable("Unsupported CondCode");
118     case ISD::SETEQ:
119       return RISCVCC::COND_EQ;
120     case ISD::SETNE:
121       return RISCVCC::COND_NE;
122     case ISD::SETLT:
123       return RISCVCC::COND_LT;
124     case ISD::SETGE:
125       return RISCVCC::COND_GE;
126     case ISD::SETULT:
127       return RISCVCC::COND_LTU;
128     case ISD::SETUGE:
129       return RISCVCC::COND_GEU;
130     }
131   }
132 
133 // Include the pieces autogenerated from the target description.
134 #include "RISCVGenDAGISel.inc"
135 
136 private:
137   bool doPeepholeSExtW(SDNode *Node);
138   bool doPeepholeMaskedRVV(SDNode *Node);
139   bool doPeepholeMergeVVMFold();
140   bool performVMergeToVAdd(SDNode *N);
141   bool performCombineVMergeAndVOps(SDNode *N, bool IsTA);
142 };
143 
144 namespace RISCV {
145 struct VLSEGPseudo {
146   uint16_t NF : 4;
147   uint16_t Masked : 1;
148   uint16_t IsTU : 1;
149   uint16_t Strided : 1;
150   uint16_t FF : 1;
151   uint16_t Log2SEW : 3;
152   uint16_t LMUL : 3;
153   uint16_t Pseudo;
154 };
155 
156 struct VLXSEGPseudo {
157   uint16_t NF : 4;
158   uint16_t Masked : 1;
159   uint16_t IsTU : 1;
160   uint16_t Ordered : 1;
161   uint16_t Log2SEW : 3;
162   uint16_t LMUL : 3;
163   uint16_t IndexLMUL : 3;
164   uint16_t Pseudo;
165 };
166 
167 struct VSSEGPseudo {
168   uint16_t NF : 4;
169   uint16_t Masked : 1;
170   uint16_t Strided : 1;
171   uint16_t Log2SEW : 3;
172   uint16_t LMUL : 3;
173   uint16_t Pseudo;
174 };
175 
176 struct VSXSEGPseudo {
177   uint16_t NF : 4;
178   uint16_t Masked : 1;
179   uint16_t Ordered : 1;
180   uint16_t Log2SEW : 3;
181   uint16_t LMUL : 3;
182   uint16_t IndexLMUL : 3;
183   uint16_t Pseudo;
184 };
185 
186 struct VLEPseudo {
187   uint16_t Masked : 1;
188   uint16_t IsTU : 1;
189   uint16_t Strided : 1;
190   uint16_t FF : 1;
191   uint16_t Log2SEW : 3;
192   uint16_t LMUL : 3;
193   uint16_t Pseudo;
194 };
195 
196 struct VSEPseudo {
197   uint16_t Masked :1;
198   uint16_t Strided : 1;
199   uint16_t Log2SEW : 3;
200   uint16_t LMUL : 3;
201   uint16_t Pseudo;
202 };
203 
204 struct VLX_VSXPseudo {
205   uint16_t Masked : 1;
206   uint16_t IsTU : 1;
207   uint16_t Ordered : 1;
208   uint16_t Log2SEW : 3;
209   uint16_t LMUL : 3;
210   uint16_t IndexLMUL : 3;
211   uint16_t Pseudo;
212 };
213 
214 struct RISCVMaskedPseudoInfo {
215   uint16_t MaskedPseudo;
216   uint16_t UnmaskedPseudo;
217   uint16_t UnmaskedTUPseudo;
218   uint8_t MaskOpIdx;
219 };
220 
221 #define GET_RISCVVSSEGTable_DECL
222 #define GET_RISCVVLSEGTable_DECL
223 #define GET_RISCVVLXSEGTable_DECL
224 #define GET_RISCVVSXSEGTable_DECL
225 #define GET_RISCVVLETable_DECL
226 #define GET_RISCVVSETable_DECL
227 #define GET_RISCVVLXTable_DECL
228 #define GET_RISCVVSXTable_DECL
229 #define GET_RISCVMaskedPseudosTable_DECL
230 #include "RISCVGenSearchableTables.inc"
231 } // namespace RISCV
232 
233 } // namespace llvm
234 
235 #endif
236