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.
23namespace llvm {
24class RISCVDAGToDAGISel : public SelectionDAGISel {
25 const RISCVSubtarget *Subtarget = nullptr;
26
27public:
28 static char ID;
29
30 RISCVDAGToDAGISel() = delete;
31
32 explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine,
33 CodeGenOptLevel 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,
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);
54 bool SelectAddrRegImmINX(SDValue Addr, SDValue &Base, SDValue &Offset) {
55 return SelectAddrRegImm(Addr, Base, Offset, IsINX: 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>
63 bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
64 SDValue &Scale) {
65 return SelectAddrRegRegScale(Addr, MaxShiftAmount: MaxShift, Base, Index, Scale);
66 }
67
68 template <unsigned MaxShift, unsigned Bits>
69 bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
70 SDValue &Scale) {
71 if (SelectAddrRegRegScale(Addr, MaxShiftAmount: MaxShift, Base, Index, Scale)) {
72 if (Index.getOpcode() == ISD::AND) {
73 auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(i: 1));
74 if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
75 Index = Index.getOperand(i: 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);
88 bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
89 return selectShiftMask(N, ShiftWidth: Subtarget->getXLen(), ShAmt);
90 }
91 bool selectShiftMask32(SDValue N, SDValue &ShAmt) {
92 return selectShiftMask(N, ShiftWidth: 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, ExpectedCCVal: ISD::SETNE, Val);
98 }
99 bool selectSETEQ(SDValue N, SDValue &Val) {
100 return selectSETCC(N, ExpectedCCVal: 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 hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, Bits: 16); }
125 bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, Bits: 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);
134 template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) {
135 return selectVSplatUimm(N, Bits, SplatVal&: 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);
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 void selectSF_VC_X_SE(SDNode *Node);
164
165 // Return the RISC-V condition code that matches the given DAG integer
166 // condition code. The CondCode must be one of those supported by the RISC-V
167 // ISA (see translateSetCCForBranch).
168 static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
169 switch (CC) {
170 default:
171 llvm_unreachable("Unsupported CondCode");
172 case ISD::SETEQ:
173 return RISCVCC::COND_EQ;
174 case ISD::SETNE:
175 return RISCVCC::COND_NE;
176 case ISD::SETLT:
177 return RISCVCC::COND_LT;
178 case ISD::SETGE:
179 return RISCVCC::COND_GE;
180 case ISD::SETULT:
181 return RISCVCC::COND_LTU;
182 case ISD::SETUGE:
183 return RISCVCC::COND_GEU;
184 }
185 }
186
187// Include the pieces autogenerated from the target description.
188#include "RISCVGenDAGISel.inc"
189
190private:
191 bool doPeepholeSExtW(SDNode *Node);
192 bool doPeepholeMaskedRVV(MachineSDNode *Node);
193 bool doPeepholeMergeVVMFold();
194 bool doPeepholeNoRegPassThru();
195 bool performCombineVMergeAndVOps(SDNode *N);
196};
197
198namespace RISCV {
199struct VLSEGPseudo {
200 uint16_t NF : 4;
201 uint16_t Masked : 1;
202 uint16_t Strided : 1;
203 uint16_t FF : 1;
204 uint16_t Log2SEW : 3;
205 uint16_t LMUL : 3;
206 uint16_t Pseudo;
207};
208
209struct VLXSEGPseudo {
210 uint16_t NF : 4;
211 uint16_t Masked : 1;
212 uint16_t Ordered : 1;
213 uint16_t Log2SEW : 3;
214 uint16_t LMUL : 3;
215 uint16_t IndexLMUL : 3;
216 uint16_t Pseudo;
217};
218
219struct VSSEGPseudo {
220 uint16_t NF : 4;
221 uint16_t Masked : 1;
222 uint16_t Strided : 1;
223 uint16_t Log2SEW : 3;
224 uint16_t LMUL : 3;
225 uint16_t Pseudo;
226};
227
228struct VSXSEGPseudo {
229 uint16_t NF : 4;
230 uint16_t Masked : 1;
231 uint16_t Ordered : 1;
232 uint16_t Log2SEW : 3;
233 uint16_t LMUL : 3;
234 uint16_t IndexLMUL : 3;
235 uint16_t Pseudo;
236};
237
238struct VLEPseudo {
239 uint16_t Masked : 1;
240 uint16_t Strided : 1;
241 uint16_t FF : 1;
242 uint16_t Log2SEW : 3;
243 uint16_t LMUL : 3;
244 uint16_t Pseudo;
245};
246
247struct VSEPseudo {
248 uint16_t Masked :1;
249 uint16_t Strided : 1;
250 uint16_t Log2SEW : 3;
251 uint16_t LMUL : 3;
252 uint16_t Pseudo;
253};
254
255struct VLX_VSXPseudo {
256 uint16_t Masked : 1;
257 uint16_t Ordered : 1;
258 uint16_t Log2SEW : 3;
259 uint16_t LMUL : 3;
260 uint16_t IndexLMUL : 3;
261 uint16_t Pseudo;
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} // namespace RISCV
273
274} // namespace llvm
275
276#endif
277

source code of llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h