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 | 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 (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 | |
190 | private: |
191 | bool doPeepholeSExtW(SDNode *Node); |
192 | bool doPeepholeMaskedRVV(MachineSDNode *Node); |
193 | bool doPeepholeMergeVVMFold(); |
194 | bool doPeepholeNoRegPassThru(); |
195 | bool performCombineVMergeAndVOps(SDNode *N); |
196 | }; |
197 | |
198 | namespace RISCV { |
199 | struct 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 | |
209 | struct 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 | |
219 | struct 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 | |
228 | struct 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 | |
238 | struct 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 | |
247 | struct 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 | |
255 | struct 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 | |