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 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&: 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 areOffsetsWithinAlignment(SDValue Addr, Align Alignment);
49
50 bool SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset);
51 bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
52 bool SelectBrindRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
53 bool SelectAddrRegImm26(SDValue Addr, SDValue &Base, SDValue &Offset);
54 bool SelectAddrRegImm9(SDValue Addr, SDValue &Base, SDValue &Offset);
55 bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset);
56
57 bool SelectAddrRegRegScale(SDValue Addr, ArrayRef<unsigned> Amounts,
58 SDValue &Base, SDValue &Index, SDValue &Scale);
59
60 template <unsigned ShiftAmount>
61 bool SelectAddrRegRegFixedScale(SDValue Addr, SDValue &Base, SDValue &Index) {
62 SDValue Scale;
63 if (!SelectAddrRegRegScale(Addr, Amounts: ShiftAmount, Base, Index, Scale))
64 return false;
65 assert(Scale->getAsZExtVal() == ShiftAmount &&
66 "ShiftAmount doesn't match!");
67 return true;
68 }
69
70 template <unsigned MaxShift>
71 bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
72 SDValue &Scale) {
73 std::array<unsigned, MaxShift + 1> Amounts;
74 std::iota(Amounts.begin(), Amounts.end(), 0);
75 return SelectAddrRegRegScale(Addr, Amounts, Base, Index, Scale);
76 }
77
78 bool SelectAddrRegZextRegScale(SDValue Addr, ArrayRef<unsigned> Amounts,
79 unsigned Bits, SDValue &Base, SDValue &Index,
80 SDValue &Scale);
81
82 template <unsigned ShiftAmount, unsigned Bits>
83 bool SelectAddrRegZextRegFixedScale(SDValue Addr, SDValue &Base,
84 SDValue &Index) {
85 SDValue Scale;
86 if (!SelectAddrRegZextRegScale(Addr, Amounts: ShiftAmount, Bits, Base, Index, Scale))
87 return false;
88 assert(Scale->getAsZExtVal() == ShiftAmount &&
89 "ShiftAmount doesn't match!");
90 return true;
91 }
92
93 template <unsigned MaxShift, unsigned Bits>
94 bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
95 SDValue &Scale) {
96 std::array<unsigned, MaxShift + 1> Amounts;
97 std::iota(Amounts.begin(), Amounts.end(), 0);
98 return SelectAddrRegZextRegScale(Addr, Amounts, Bits, Base, Index, Scale);
99 }
100
101 bool SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset);
102
103 bool tryShrinkShlLogicImm(SDNode *Node);
104 bool trySignedBitfieldExtract(SDNode *Node);
105 bool trySignedBitfieldInsertInSign(SDNode *Node);
106 bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT,
107 SDValue X, unsigned Msb, unsigned Lsb);
108 bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT,
109 SDValue X, unsigned Msb, unsigned Lsb);
110 bool tryIndexedLoad(SDNode *Node);
111 bool tryWideningMulAcc(SDNode *Node, const SDLoc &DL);
112
113 bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
114 bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
115 return selectShiftMask(N, ShiftWidth: Subtarget->getXLen(), ShAmt);
116 }
117 template <unsigned Size> bool selectShiftMask(SDValue N, SDValue &ShAmt) {
118 return selectShiftMask(N, ShiftWidth: Size, ShAmt);
119 }
120
121 bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val,
122 bool OneUse);
123 template <bool OneUse = false> bool selectSETNE(SDValue N, SDValue &Val) {
124 return selectSETCC(N, ExpectedCCVal: ISD::SETNE, Val, OneUse);
125 }
126 template <bool OneUse = false> bool selectSETEQ(SDValue N, SDValue &Val) {
127 return selectSETCC(N, ExpectedCCVal: ISD::SETEQ, Val, OneUse);
128 }
129
130 bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val);
131 template <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) {
132 return selectSExtBits(N, Bits, Val);
133 }
134 bool selectZExtBits(SDValue N, unsigned Bits, SDValue &Val);
135 template <unsigned Bits> bool selectZExtBits(SDValue N, SDValue &Val) {
136 return selectZExtBits(N, Bits, Val);
137 }
138
139 bool selectSHXADDOp(SDValue N, unsigned ShAmt, SDValue &Val);
140 template <unsigned ShAmt> bool selectSHXADDOp(SDValue N, SDValue &Val) {
141 return selectSHXADDOp(N, ShAmt, Val);
142 }
143
144 bool selectSHXADD_UWOp(SDValue N, unsigned ShAmt, SDValue &Val);
145 template <unsigned ShAmt> bool selectSHXADD_UWOp(SDValue N, SDValue &Val) {
146 return selectSHXADD_UWOp(N, ShAmt, Val);
147 }
148
149 bool selectZExtImm32(SDValue N, SDValue &Val);
150 bool selectNegImm(SDValue N, SDValue &Val);
151 bool selectInvLogicImm(SDValue N, SDValue &Val);
152
153 bool orDisjoint(const SDNode *Node) const;
154 bool hasAllNBitUsers(SDNode *Node, unsigned Bits,
155 const unsigned Depth = 0) const;
156 bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, Bits: 8); }
157 bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, Bits: 16); }
158 bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, Bits: 32); }
159
160 bool selectSimm5Shl2(SDValue N, SDValue &Simm5, SDValue &Shl2);
161
162 bool selectVLOp(SDValue N, SDValue &VL);
163
164 bool selectVSplat(SDValue N, SDValue &SplatVal);
165 bool selectVSplatSimm5(SDValue N, SDValue &SplatVal);
166 bool selectVSplatUimm(SDValue N, unsigned Bits, SDValue &SplatVal);
167 template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) {
168 return selectVSplatUimm(N, Bits, SplatVal&: Val);
169 }
170 bool selectVSplatSimm5Plus1(SDValue N, SDValue &SplatVal);
171 bool selectVSplatSimm5Plus1NoDec(SDValue N, SDValue &SplatVal);
172 bool selectVSplatSimm5Plus1NonZero(SDValue N, SDValue &SplatVal);
173 bool selectVSplatImm64Neg(SDValue N, SDValue &SplatVal);
174 // Matches the splat of a value which can be extended or truncated, such that
175 // only the bottom 8 bits are preserved.
176 bool selectLow8BitsVSplat(SDValue N, SDValue &SplatVal);
177 bool selectScalarFPAsInt(SDValue N, SDValue &Imm);
178
179 bool selectRVVSimm5(SDValue N, unsigned Width, SDValue &Imm);
180 template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) {
181 return selectRVVSimm5(N, Width, Imm);
182 }
183
184 bool selectVMNOTOp(SDValue N, SDValue &Res);
185 bool selectVMNOT_VLOp(SDNode *Parent, SDValue N, SDValue &Res);
186
187 void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm,
188 const SDLoc &DL, unsigned CurOp,
189 bool IsMasked, bool IsStridedOrIndexed,
190 SmallVectorImpl<SDValue> &Operands,
191 bool IsLoad = false, MVT *IndexVT = nullptr);
192
193 void selectVLSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided);
194 void selectVLSEGFF(SDNode *Node, unsigned NF, bool IsMasked);
195 void selectVLXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered);
196 void selectVSSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided);
197 void selectVSXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered);
198
199 void selectVSETVLI(SDNode *Node);
200 void selectXSfmmVSET(SDNode *Node);
201
202 void selectSF_VC_X_SE(SDNode *Node);
203
204 // Return the RISC-V condition code that matches the given DAG integer
205 // condition code. The CondCode must be one of those supported by the RISC-V
206 // ISA (see translateSetCCForBranch).
207 static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
208 switch (CC) {
209 default:
210 llvm_unreachable("Unsupported CondCode");
211 case ISD::SETEQ:
212 return RISCVCC::COND_EQ;
213 case ISD::SETNE:
214 return RISCVCC::COND_NE;
215 case ISD::SETLT:
216 return RISCVCC::COND_LT;
217 case ISD::SETGE:
218 return RISCVCC::COND_GE;
219 case ISD::SETULT:
220 return RISCVCC::COND_LTU;
221 case ISD::SETUGE:
222 return RISCVCC::COND_GEU;
223 }
224 }
225
226// Include the pieces autogenerated from the target description.
227#define GET_DAGISEL_DECL
228#include "RISCVGenDAGISel.inc"
229
230private:
231 bool doPeepholeSExtW(SDNode *Node);
232 bool doPeepholeMaskedRVV(MachineSDNode *Node);
233 bool doPeepholeNoRegPassThru();
234 bool selectImm64IfCheaper(int64_t Imm, int64_t OrigImm, SDValue N,
235 SDValue &Val);
236};
237
238class RISCVDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
239public:
240 static char ID;
241 explicit RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TargetMachine,
242 CodeGenOptLevel OptLevel);
243};
244
245} // namespace llvm
246
247#endif
248