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 
20 // RISCV-specific code to select RISCV machine instructions for
21 // SelectionDAG operations.
22 namespace llvm {
23 class RISCVDAGToDAGISel : public SelectionDAGISel {
24   const RISCVSubtarget *Subtarget = nullptr;
25 
26 public:
27   explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine,
28                              CodeGenOpt::Level OptLevel)
29       : SelectionDAGISel(TargetMachine, OptLevel) {}
30 
31   StringRef getPassName() const override {
32     return "RISCV DAG->DAG Pattern Instruction Selection";
33   }
34 
35   bool runOnMachineFunction(MachineFunction &MF) override {
36     Subtarget = &MF.getSubtarget<RISCVSubtarget>();
37     return SelectionDAGISel::runOnMachineFunction(MF);
38   }
39 
40   void PreprocessISelDAG() override;
41   void PostprocessISelDAG() override;
42 
43   void Select(SDNode *Node) override;
44 
45   bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
46                                     std::vector<SDValue> &OutOps) override;
47 
48   bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset);
49   bool SelectFrameAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
50   bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
51 
52   bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
53   bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
54     return selectShiftMask(N, Subtarget->getXLen(), ShAmt);
55   }
56   bool selectShiftMask32(SDValue N, SDValue &ShAmt) {
57     return selectShiftMask(N, 32, ShAmt);
58   }
59 
60   bool selectSExti32(SDValue N, SDValue &Val);
61   bool selectZExti32(SDValue N, SDValue &Val);
62 
63   bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val);
64   bool selectSH1ADDOp(SDValue N, SDValue &Val) {
65     return selectSHXADDOp(N, 1, Val);
66   }
67   bool selectSH2ADDOp(SDValue N, SDValue &Val) {
68     return selectSHXADDOp(N, 2, Val);
69   }
70   bool selectSH3ADDOp(SDValue N, SDValue &Val) {
71     return selectSHXADDOp(N, 3, Val);
72   }
73 
74   bool hasAllNBitUsers(SDNode *Node, unsigned Bits) const;
75   bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); }
76   bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); }
77 
78   bool selectVLOp(SDValue N, SDValue &VL);
79 
80   bool selectVSplat(SDValue N, SDValue &SplatVal);
81   bool selectVSplatSimm5(SDValue N, SDValue &SplatVal);
82   bool selectVSplatUimm5(SDValue N, SDValue &SplatVal);
83   bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal);
84   bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal);
85 
86   bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm);
87   template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) {
88     return selectRVVSimm5(N, Width, Imm);
89   }
90 
91   void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm,
92                                   const SDLoc &DL, unsigned CurOp,
93                                   bool IsMasked, bool IsStridedOrIndexed,
94                                   SmallVectorImpl<SDValue> &Operands,
95                                   bool IsLoad = false, MVT *IndexVT = nullptr);
96 
97   void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided);
98   void selectVLSEGFF(SDNode *Node, bool IsMasked);
99   void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
100   void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided);
101   void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
102 
103   void selectVSETVLI(SDNode *Node);
104 
105   // Return the RISC-V condition code that matches the given DAG integer
106   // condition code. The CondCode must be one of those supported by the RISC-V
107   // ISA (see translateSetCCForBranch).
108   static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
109     switch (CC) {
110     default:
111       llvm_unreachable("Unsupported CondCode");
112     case ISD::SETEQ:
113       return RISCVCC::COND_EQ;
114     case ISD::SETNE:
115       return RISCVCC::COND_NE;
116     case ISD::SETLT:
117       return RISCVCC::COND_LT;
118     case ISD::SETGE:
119       return RISCVCC::COND_GE;
120     case ISD::SETULT:
121       return RISCVCC::COND_LTU;
122     case ISD::SETUGE:
123       return RISCVCC::COND_GEU;
124     }
125   }
126 
127 // Include the pieces autogenerated from the target description.
128 #include "RISCVGenDAGISel.inc"
129 
130 private:
131   bool doPeepholeSExtW(SDNode *Node);
132   bool doPeepholeMaskedRVV(SDNode *Node);
133 };
134 
135 namespace RISCV {
136 struct VLSEGPseudo {
137   uint16_t NF : 4;
138   uint16_t Masked : 1;
139   uint16_t IsTU : 1;
140   uint16_t Strided : 1;
141   uint16_t FF : 1;
142   uint16_t Log2SEW : 3;
143   uint16_t LMUL : 3;
144   uint16_t Pseudo;
145 };
146 
147 struct VLXSEGPseudo {
148   uint16_t NF : 4;
149   uint16_t Masked : 1;
150   uint16_t IsTU : 1;
151   uint16_t Ordered : 1;
152   uint16_t Log2SEW : 3;
153   uint16_t LMUL : 3;
154   uint16_t IndexLMUL : 3;
155   uint16_t Pseudo;
156 };
157 
158 struct VSSEGPseudo {
159   uint16_t NF : 4;
160   uint16_t Masked : 1;
161   uint16_t Strided : 1;
162   uint16_t Log2SEW : 3;
163   uint16_t LMUL : 3;
164   uint16_t Pseudo;
165 };
166 
167 struct VSXSEGPseudo {
168   uint16_t NF : 4;
169   uint16_t Masked : 1;
170   uint16_t Ordered : 1;
171   uint16_t Log2SEW : 3;
172   uint16_t LMUL : 3;
173   uint16_t IndexLMUL : 3;
174   uint16_t Pseudo;
175 };
176 
177 struct VLEPseudo {
178   uint16_t Masked : 1;
179   uint16_t IsTU : 1;
180   uint16_t Strided : 1;
181   uint16_t FF : 1;
182   uint16_t Log2SEW : 3;
183   uint16_t LMUL : 3;
184   uint16_t Pseudo;
185 };
186 
187 struct VSEPseudo {
188   uint16_t Masked :1;
189   uint16_t Strided : 1;
190   uint16_t Log2SEW : 3;
191   uint16_t LMUL : 3;
192   uint16_t Pseudo;
193 };
194 
195 struct VLX_VSXPseudo {
196   uint16_t Masked : 1;
197   uint16_t IsTU : 1;
198   uint16_t Ordered : 1;
199   uint16_t Log2SEW : 3;
200   uint16_t LMUL : 3;
201   uint16_t IndexLMUL : 3;
202   uint16_t Pseudo;
203 };
204 
205 struct RISCVMaskedPseudoInfo {
206   uint16_t MaskedPseudo;
207   uint16_t UnmaskedPseudo;
208   uint16_t UnmaskedTUPseudo;
209   uint8_t MaskOpIdx;
210 };
211 
212 #define GET_RISCVVSSEGTable_DECL
213 #define GET_RISCVVLSEGTable_DECL
214 #define GET_RISCVVLXSEGTable_DECL
215 #define GET_RISCVVSXSEGTable_DECL
216 #define GET_RISCVVLETable_DECL
217 #define GET_RISCVVSETable_DECL
218 #define GET_RISCVVLXTable_DECL
219 #define GET_RISCVVSXTable_DECL
220 #define GET_RISCVMaskedPseudosTable_DECL
221 #include "RISCVGenSearchableTables.inc"
222 } // namespace RISCV
223 
224 } // namespace llvm
225 
226 #endif
227