xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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   RISCVDAGToDAGISel() = delete;
29 
30   explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine,
31                              CodeGenOptLevel OptLevel)
32       : SelectionDAGISel(TargetMachine, OptLevel) {}
33 
34   bool runOnMachineFunction(MachineFunction &MF) override {
35     Subtarget = &MF.getSubtarget<RISCVSubtarget>();
36     return SelectionDAGISel::runOnMachineFunction(MF);
37   }
38 
39   void PreprocessISelDAG() override;
40   void PostprocessISelDAG() override;
41 
42   void Select(SDNode *Node) override;
43 
44   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
45                                     InlineAsm::ConstraintCode 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                         bool IsINX = false);
52   bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) {
53     return SelectAddrRegImm(Addr, Base, Offset, true);
54   }
55   bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset);
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 SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset);
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 hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); }
125   bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); }
126   bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 32); }
127 
128   bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2);
129 
130   bool selectVLOp(SDValue N, SDValue &VL);
131 
132   bool selectVSplat(SDValue N, SDValue &SplatVal);
133   bool selectVSplatSimm5(SDValue N, SDValue &SplatVal);
134   bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal);
135   template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) {
136     return selectVSplatUimm(N, Bits, Val);
137   }
138   bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal);
139   bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal);
140   // Matches the splat of a value which can be extended or truncated, such that
141   // only the bottom 8 bits are preserved.
142   bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal);
143   bool selectFPImm(SDValue N, SDValue &Imm);
144 
145   bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm);
146   template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) {
147     return selectRVVSimm5(N, Width, Imm);
148   }
149 
150   void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm,
151                                   const SDLoc &DL, unsigned CurOp,
152                                   bool IsMasked, bool IsStridedOrIndexed,
153                                   SmallVectorImpl<SDValue> &Operands,
154                                   bool IsLoad = false, MVT *IndexVT = nullptr);
155 
156   void selectVLSEG(SDNode *Node, bool IsMasked, bool IsStrided);
157   void selectVLSEGFF(SDNode *Node, bool IsMasked);
158   void selectVLXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
159   void selectVSSEG(SDNode *Node, bool IsMasked, bool IsStrided);
160   void selectVSXSEG(SDNode *Node, bool IsMasked, bool IsOrdered);
161 
162   void selectVSETVLI(SDNode *Node);
163 
164   void selectSF_VC_X_SE(SDNode *Node);
165 
166   // Return the RISC-V condition code that matches the given DAG integer
167   // condition code. The CondCode must be one of those supported by the RISC-V
168   // ISA (see translateSetCCForBranch).
169   static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
170     switch (CC) {
171     default:
172       llvm_unreachable("Unsupported CondCode");
173     case ISD::SETEQ:
174       return RISCVCC::COND_EQ;
175     case ISD::SETNE:
176       return RISCVCC::COND_NE;
177     case ISD::SETLT:
178       return RISCVCC::COND_LT;
179     case ISD::SETGE:
180       return RISCVCC::COND_GE;
181     case ISD::SETULT:
182       return RISCVCC::COND_LTU;
183     case ISD::SETUGE:
184       return RISCVCC::COND_GEU;
185     }
186   }
187 
188 // Include the pieces autogenerated from the target description.
189 #include "RISCVGenDAGISel.inc"
190 
191 private:
192   bool doPeepholeSExtW(SDNode *Node);
193   bool doPeepholeMaskedRVV(MachineSDNode *Node);
194   bool doPeepholeMergeVVMFold();
195   bool doPeepholeNoRegPassThru();
196   bool performCombineVMergeAndVOps(SDNode *N);
197 };
198 
199 class RISCVDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
200 public:
201   static char ID;
202   explicit RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TargetMachine,
203                                    CodeGenOptLevel OptLevel);
204 };
205 
206 namespace RISCV {
207 struct VLSEGPseudo {
208   uint16_t NF : 4;
209   uint16_t Masked : 1;
210   uint16_t Strided : 1;
211   uint16_t FF : 1;
212   uint16_t Log2SEW : 3;
213   uint16_t LMUL : 3;
214   uint16_t Pseudo;
215 };
216 
217 struct VLXSEGPseudo {
218   uint16_t NF : 4;
219   uint16_t Masked : 1;
220   uint16_t Ordered : 1;
221   uint16_t Log2SEW : 3;
222   uint16_t LMUL : 3;
223   uint16_t IndexLMUL : 3;
224   uint16_t Pseudo;
225 };
226 
227 struct VSSEGPseudo {
228   uint16_t NF : 4;
229   uint16_t Masked : 1;
230   uint16_t Strided : 1;
231   uint16_t Log2SEW : 3;
232   uint16_t LMUL : 3;
233   uint16_t Pseudo;
234 };
235 
236 struct VSXSEGPseudo {
237   uint16_t NF : 4;
238   uint16_t Masked : 1;
239   uint16_t Ordered : 1;
240   uint16_t Log2SEW : 3;
241   uint16_t LMUL : 3;
242   uint16_t IndexLMUL : 3;
243   uint16_t Pseudo;
244 };
245 
246 struct VLEPseudo {
247   uint16_t Masked : 1;
248   uint16_t Strided : 1;
249   uint16_t FF : 1;
250   uint16_t Log2SEW : 3;
251   uint16_t LMUL : 3;
252   uint16_t Pseudo;
253 };
254 
255 struct VSEPseudo {
256   uint16_t Masked :1;
257   uint16_t Strided : 1;
258   uint16_t Log2SEW : 3;
259   uint16_t LMUL : 3;
260   uint16_t Pseudo;
261 };
262 
263 struct VLX_VSXPseudo {
264   uint16_t Masked : 1;
265   uint16_t Ordered : 1;
266   uint16_t Log2SEW : 3;
267   uint16_t LMUL : 3;
268   uint16_t IndexLMUL : 3;
269   uint16_t Pseudo;
270 };
271 
272 #define GET_RISCVVSSEGTable_DECL
273 #define GET_RISCVVLSEGTable_DECL
274 #define GET_RISCVVLXSEGTable_DECL
275 #define GET_RISCVVSXSEGTable_DECL
276 #define GET_RISCVVLETable_DECL
277 #define GET_RISCVVSETable_DECL
278 #define GET_RISCVVLXTable_DECL
279 #define GET_RISCVVSXTable_DECL
280 } // namespace RISCV
281 
282 } // namespace llvm
283 
284 #endif
285