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