1 //===-- RISCVInstrInfo.h - RISC-V Instruction Information -------*- C++ -*-===//
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 contains the RISC-V implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
14 #define LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H
15 
16 #include "RISCVRegisterInfo.h"
17 #include "llvm/CodeGen/TargetInstrInfo.h"
18 #include "llvm/IR/DiagnosticInfo.h"
19 
20 #define GET_INSTRINFO_HEADER
21 #define GET_INSTRINFO_OPERAND_ENUM
22 #include "RISCVGenInstrInfo.inc"
23 
24 namespace llvm {
25 
26 class RISCVSubtarget;
27 
28 static const MachineMemOperand::Flags MONontemporalBit0 =
29     MachineMemOperand::MOTargetFlag1;
30 static const MachineMemOperand::Flags MONontemporalBit1 =
31     MachineMemOperand::MOTargetFlag2;
32 
33 namespace RISCVCC {
34 
35 enum CondCode {
36   COND_EQ,
37   COND_NE,
38   COND_LT,
39   COND_GE,
40   COND_LTU,
41   COND_GEU,
42   COND_INVALID
43 };
44 
45 CondCode getOppositeBranchCondition(CondCode);
46 
47 } // end of namespace RISCVCC
48 
49 class RISCVInstrInfo : public RISCVGenInstrInfo {
50 
51 public:
52   explicit RISCVInstrInfo(RISCVSubtarget &STI);
53 
54   MCInst getNop() const override;
55   const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const;
56 
57   unsigned isLoadFromStackSlot(const MachineInstr &MI,
58                                int &FrameIndex) const override;
59   unsigned isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex,
60                                unsigned &MemBytes) const override;
61   unsigned isStoreToStackSlot(const MachineInstr &MI,
62                               int &FrameIndex) const override;
63   unsigned isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex,
64                               unsigned &MemBytes) const override;
65 
66   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
67                    const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
68                    bool KillSrc) const override;
69 
70   void storeRegToStackSlot(MachineBasicBlock &MBB,
71                            MachineBasicBlock::iterator MBBI, Register SrcReg,
72                            bool IsKill, int FrameIndex,
73                            const TargetRegisterClass *RC,
74                            const TargetRegisterInfo *TRI,
75                            Register VReg) const override;
76 
77   void loadRegFromStackSlot(MachineBasicBlock &MBB,
78                             MachineBasicBlock::iterator MBBI, Register DstReg,
79                             int FrameIndex, const TargetRegisterClass *RC,
80                             const TargetRegisterInfo *TRI,
81                             Register VReg) const override;
82 
83   using TargetInstrInfo::foldMemoryOperandImpl;
84   MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
85                                       ArrayRef<unsigned> Ops,
86                                       MachineBasicBlock::iterator InsertPt,
87                                       int FrameIndex,
88                                       LiveIntervals *LIS = nullptr,
89                                       VirtRegMap *VRM = nullptr) const override;
90 
91   // Materializes the given integer Val into DstReg.
92   void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
93               const DebugLoc &DL, Register DstReg, uint64_t Val,
94               MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
95 
96   unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
97 
98   bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
99                      MachineBasicBlock *&FBB,
100                      SmallVectorImpl<MachineOperand> &Cond,
101                      bool AllowModify) const override;
102 
103   unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
104                         MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
105                         const DebugLoc &dl,
106                         int *BytesAdded = nullptr) const override;
107 
108   void insertIndirectBranch(MachineBasicBlock &MBB,
109                             MachineBasicBlock &NewDestBB,
110                             MachineBasicBlock &RestoreBB, const DebugLoc &DL,
111                             int64_t BrOffset, RegScavenger *RS) const override;
112 
113   unsigned removeBranch(MachineBasicBlock &MBB,
114                         int *BytesRemoved = nullptr) const override;
115 
116   bool
117   reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
118 
119   MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
120 
121   bool isBranchOffsetInRange(unsigned BranchOpc,
122                              int64_t BrOffset) const override;
123 
124   bool analyzeSelect(const MachineInstr &MI,
125                      SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,
126                      unsigned &FalseOp, bool &Optimizable) const override;
127 
128   MachineInstr *optimizeSelect(MachineInstr &MI,
129                                SmallPtrSetImpl<MachineInstr *> &SeenMIs,
130                                bool) const override;
131 
132   bool isAsCheapAsAMove(const MachineInstr &MI) const override;
133 
134   std::optional<DestSourcePair>
135   isCopyInstrImpl(const MachineInstr &MI) const override;
136 
137   bool verifyInstruction(const MachineInstr &MI,
138                          StringRef &ErrInfo) const override;
139 
140   bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
141                                     const MachineOperand *&BaseOp,
142                                     int64_t &Offset, unsigned &Width,
143                                     const TargetRegisterInfo *TRI) const;
144 
145   bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
146                                        const MachineInstr &MIb) const override;
147 
148 
149   std::pair<unsigned, unsigned>
150   decomposeMachineOperandsTargetFlags(unsigned TF) const override;
151 
152   ArrayRef<std::pair<unsigned, const char *>>
153   getSerializableDirectMachineOperandTargetFlags() const override;
154 
155   // Return true if the function can safely be outlined from.
156   bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
157                                    bool OutlineFromLinkOnceODRs) const override;
158 
159   // Return true if MBB is safe to outline from, and return any target-specific
160   // information in Flags.
161   bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
162                               unsigned &Flags) const override;
163 
164   bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;
165 
166   // Calculate target-specific information for a set of outlining candidates.
167   std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo(
168       std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
169 
170   // Return if/how a given MachineInstr should be outlined.
171   virtual outliner::InstrType
172   getOutliningTypeImpl(MachineBasicBlock::iterator &MBBI,
173                        unsigned Flags) const override;
174 
175   // Insert a custom frame for outlined functions.
176   void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
177                           const outliner::OutlinedFunction &OF) const override;
178 
179   // Insert a call to an outlined function into a given basic block.
180   MachineBasicBlock::iterator
181   insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
182                      MachineBasicBlock::iterator &It, MachineFunction &MF,
183                      outliner::Candidate &C) const override;
184 
185   bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
186                              unsigned &SrcOpIdx2) const override;
187   MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
188                                        unsigned OpIdx1,
189                                        unsigned OpIdx2) const override;
190 
191   MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
192                                       LiveIntervals *LIS) const override;
193 
194   // MIR printer helper function to annotate Operands with a comment.
195   std::string
196   createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op,
197                           unsigned OpIdx,
198                           const TargetRegisterInfo *TRI) const override;
199 
200   void getVLENFactoredAmount(
201       MachineFunction &MF, MachineBasicBlock &MBB,
202       MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg,
203       int64_t Amount, MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const;
204 
205   bool useMachineCombiner() const override { return true; }
206 
207   MachineTraceStrategy getMachineCombinerTraceStrategy() const override;
208 
209   void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2,
210                              MachineInstr &NewMI1,
211                              MachineInstr &NewMI2) const override;
212   bool
213   getMachineCombinerPatterns(MachineInstr &Root,
214                              SmallVectorImpl<MachineCombinerPattern> &Patterns,
215                              bool DoRegPressureReduce) const override;
216 
217   void
218   finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P,
219                     SmallVectorImpl<MachineInstr *> &InsInstrs) const override;
220 
221   void genAlternativeCodeSequence(
222       MachineInstr &Root, MachineCombinerPattern Pattern,
223       SmallVectorImpl<MachineInstr *> &InsInstrs,
224       SmallVectorImpl<MachineInstr *> &DelInstrs,
225       DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override;
226 
227   bool hasReassociableSibling(const MachineInstr &Inst,
228                               bool &Commuted) const override;
229 
230   bool isAssociativeAndCommutative(const MachineInstr &Inst,
231                                    bool Invert) const override;
232 
233   std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;
234 
235   ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
236   getSerializableMachineMemOperandTargetFlags() const override;
237 
238 protected:
239   const RISCVSubtarget &STI;
240 
241 private:
242   unsigned getInstBundleLength(const MachineInstr &MI) const;
243 };
244 
245 namespace RISCV {
246 
247 // Returns true if this is the sext.w pattern, addiw rd, rs1, 0.
248 bool isSEXT_W(const MachineInstr &MI);
249 bool isZEXT_W(const MachineInstr &MI);
250 bool isZEXT_B(const MachineInstr &MI);
251 
252 // Returns true if the given MI is an RVV instruction opcode for which we may
253 // expect to see a FrameIndex operand.
254 bool isRVVSpill(const MachineInstr &MI);
255 
256 std::optional<std::pair<unsigned, unsigned>>
257 isRVVSpillForZvlsseg(unsigned Opcode);
258 
259 bool isFaultFirstLoad(const MachineInstr &MI);
260 
261 // Implemented in RISCVGenInstrInfo.inc
262 int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex);
263 
264 // Return true if both input instructions have equal rounding mode. If at least
265 // one of the instructions does not have rounding mode, false will be returned.
266 bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2);
267 
268 // Special immediate for AVL operand of V pseudo instructions to indicate VLMax.
269 static constexpr int64_t VLMaxSentinel = -1LL;
270 
271 // Mask assignments for floating-point
272 static constexpr unsigned FPMASK_Negative_Infinity = 0x001;
273 static constexpr unsigned FPMASK_Negative_Normal = 0x002;
274 static constexpr unsigned FPMASK_Negative_Subnormal = 0x004;
275 static constexpr unsigned FPMASK_Negative_Zero = 0x008;
276 static constexpr unsigned FPMASK_Positive_Zero = 0x010;
277 static constexpr unsigned FPMASK_Positive_Subnormal = 0x020;
278 static constexpr unsigned FPMASK_Positive_Normal = 0x040;
279 static constexpr unsigned FPMASK_Positive_Infinity = 0x080;
280 static constexpr unsigned FPMASK_Signaling_NaN = 0x100;
281 static constexpr unsigned FPMASK_Quiet_NaN = 0x200;
282 } // namespace RISCV
283 
284 namespace RISCVVPseudosTable {
285 
286 struct PseudoInfo {
287   uint16_t Pseudo;
288   uint16_t BaseInstr;
289 };
290 
291 #define GET_RISCVVPseudosTable_DECL
292 #include "RISCVGenSearchableTables.inc"
293 
294 } // end namespace RISCVVPseudosTable
295 
296 } // end namespace llvm
297 #endif
298