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