xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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   RISCVDAGToDAGISel() = delete;
29 
RISCVDAGToDAGISel(RISCVTargetMachine & TargetMachine,CodeGenOptLevel OptLevel)30   explicit RISCVDAGToDAGISel(RISCVTargetMachine &TargetMachine,
31                              CodeGenOptLevel OptLevel)
32       : SelectionDAGISel(TargetMachine, OptLevel) {}
33 
runOnMachineFunction(MachineFunction & MF)34   bool runOnMachineFunction(MachineFunction &MF) override {
35     Subtarget = &MF.getSubtarget<RISCVSubtarget>();
36     return SelectionDAGISel::runOnMachineFunction(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 SelectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset);
49   bool SelectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset);
50   bool SelectAddrRegImm9(SDValue Addr, SDValue &Base, SDValue &Offset);
51   bool SelectAddrRegImmLsb00000(SDValue Addr, SDValue &Base, SDValue &Offset);
52 
53   bool SelectAddrRegRegScale(SDValue Addr, unsigned MaxShiftAmount,
54                              SDValue &Base, SDValue &Index, SDValue &Scale);
55 
56   template <unsigned MaxShift>
SelectAddrRegRegScale(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Scale)57   bool SelectAddrRegRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
58                              SDValue &Scale) {
59     return SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale);
60   }
61 
62   template <unsigned MaxShift, unsigned Bits>
SelectAddrRegZextRegScale(SDValue Addr,SDValue & Base,SDValue & Index,SDValue & Scale)63   bool SelectAddrRegZextRegScale(SDValue Addr, SDValue &Base, SDValue &Index,
64                                  SDValue &Scale) {
65     if (SelectAddrRegRegScale(Addr, MaxShift, Base, Index, Scale)) {
66       if (Index.getOpcode() == ISD::AND) {
67         auto *C = dyn_cast<ConstantSDNode>(Index.getOperand(1));
68         if (C && C->getZExtValue() == maskTrailingOnes<uint64_t>(Bits)) {
69           Index = Index.getOperand(0);
70           return true;
71         }
72       }
73     }
74     return false;
75   }
76 
77   bool SelectAddrRegReg(SDValue Addr, SDValue &Base, SDValue &Offset);
78 
79   bool tryShrinkShlLogicImm(SDNode *Node);
80   bool trySignedBitfieldExtract(SDNode *Node);
81   bool trySignedBitfieldInsertInSign(SDNode *Node);
82   bool trySignedBitfieldInsertInMask(SDNode *Node);
83   bool tryUnsignedBitfieldExtract(SDNode *Node, const SDLoc &DL, MVT VT,
84                                   SDValue X, unsigned Msb, unsigned Lsb);
85   bool tryUnsignedBitfieldInsertInZero(SDNode *Node, const SDLoc &DL, MVT VT,
86                                        SDValue X, unsigned Msb, unsigned Lsb);
87   bool tryIndexedLoad(SDNode *Node);
88 
89   bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
selectShiftMaskXLen(SDValue N,SDValue & ShAmt)90   bool selectShiftMaskXLen(SDValue N, SDValue &ShAmt) {
91     return selectShiftMask(N, Subtarget->getXLen(), ShAmt);
92   }
selectShiftMask32(SDValue N,SDValue & ShAmt)93   bool selectShiftMask32(SDValue N, SDValue &ShAmt) {
94     return selectShiftMask(N, 32, ShAmt);
95   }
96 
97   bool selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val);
selectSETNE(SDValue N,SDValue & Val)98   bool selectSETNE(SDValue N, SDValue &Val) {
99     return selectSETCC(N, ISD::SETNE, Val);
100   }
selectSETEQ(SDValue N,SDValue & Val)101   bool selectSETEQ(SDValue N, SDValue &Val) {
102     return selectSETCC(N, ISD::SETEQ, Val);
103   }
104 
105   bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val);
selectSExtBits(SDValue N,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);
selectZExtBits(SDValue N,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);
selectSHXADDOp(SDValue N,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);
selectSHXADD_UWOp(SDValue N,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;
hasAllBUsers(SDNode * Node)131   bool hasAllBUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 8); }
hasAllHUsers(SDNode * Node)132   bool hasAllHUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 16); }
hasAllWUsers(SDNode * Node)133   bool hasAllWUsers(SDNode *Node) const { return hasAllNBitUsers(Node, 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);
selectVSplatUimmBits(SDValue N,SDValue & Val)142   template <unsigned Bits> bool selectVSplatUimmBits(SDValue N, SDValue &Val) {
143     return selectVSplatUimm(N, Bits, 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);
selectRVVSimm5(SDValue N,SDValue & Imm)155   template <unsigned Width> bool selectRVVSimm5(SDValue N, SDValue &Imm) {
156     return selectRVVSimm5(N, Width, Imm);
157   }
158 
159   void addVectorLoadStoreOperands(SDNode *Node, unsigned SEWImm,
160                                   const SDLoc &DL, unsigned CurOp,
161                                   bool IsMasked, bool IsStridedOrIndexed,
162                                   SmallVectorImpl<SDValue> &Operands,
163                                   bool IsLoad = false, MVT *IndexVT = nullptr);
164 
165   void selectVLSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided);
166   void selectVLSEGFF(SDNode *Node, unsigned NF, bool IsMasked);
167   void selectVLXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered);
168   void selectVSSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsStrided);
169   void selectVSXSEG(SDNode *Node, unsigned NF, bool IsMasked, bool IsOrdered);
170 
171   void selectVSETVLI(SDNode *Node);
172 
173   void selectSF_VC_X_SE(SDNode *Node);
174 
175   // Return the RISC-V condition code that matches the given DAG integer
176   // condition code. The CondCode must be one of those supported by the RISC-V
177   // ISA (see translateSetCCForBranch).
getRISCVCCForIntCC(ISD::CondCode CC)178   static RISCVCC::CondCode getRISCVCCForIntCC(ISD::CondCode CC) {
179     switch (CC) {
180     default:
181       llvm_unreachable("Unsupported CondCode");
182     case ISD::SETEQ:
183       return RISCVCC::COND_EQ;
184     case ISD::SETNE:
185       return RISCVCC::COND_NE;
186     case ISD::SETLT:
187       return RISCVCC::COND_LT;
188     case ISD::SETGE:
189       return RISCVCC::COND_GE;
190     case ISD::SETULT:
191       return RISCVCC::COND_LTU;
192     case ISD::SETUGE:
193       return RISCVCC::COND_GEU;
194     }
195   }
196 
197 // Include the pieces autogenerated from the target description.
198 #define GET_DAGISEL_DECL
199 #include "RISCVGenDAGISel.inc"
200 
201 private:
202   bool doPeepholeSExtW(SDNode *Node);
203   bool doPeepholeMaskedRVV(MachineSDNode *Node);
204   bool doPeepholeNoRegPassThru();
205   bool performCombineVMergeAndVOps(SDNode *N);
206   bool selectImm64IfCheaper(int64_t Imm, int64_t OrigImm, SDValue N,
207                             SDValue &Val);
208 };
209 
210 class RISCVDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
211 public:
212   static char ID;
213   explicit RISCVDAGToDAGISelLegacy(RISCVTargetMachine &TargetMachine,
214                                    CodeGenOptLevel OptLevel);
215 };
216 
217 } // namespace llvm
218 
219 #endif
220