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 "RISCV.h"
17#include "RISCVRegisterInfo.h"
18#include "llvm/CodeGen/TargetInstrInfo.h"
19#include "llvm/IR/DiagnosticInfo.h"
20
21#define GET_INSTRINFO_HEADER
22#define GET_INSTRINFO_OPERAND_ENUM
23#include "RISCVGenInstrInfo.inc"
24#include "RISCVGenRegisterInfo.inc"
25
26namespace llvm {
27
28class RISCVSubtarget;
29
30static const MachineMemOperand::Flags MONontemporalBit0 =
31 MachineMemOperand::MOTargetFlag1;
32static const MachineMemOperand::Flags MONontemporalBit1 =
33 MachineMemOperand::MOTargetFlag2;
34
35namespace RISCVCC {
36
37enum CondCode {
38 COND_EQ,
39 COND_NE,
40 COND_LT,
41 COND_GE,
42 COND_LTU,
43 COND_GEU,
44 COND_INVALID
45};
46
47CondCode getOppositeBranchCondition(CondCode);
48unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0);
49
50} // end of namespace RISCVCC
51
52// RISCV MachineCombiner patterns
53enum RISCVMachineCombinerPattern : unsigned {
54 FMADD_AX = MachineCombinerPattern::TARGET_PATTERN_START,
55 FMADD_XA,
56 FMSUB,
57 FNMSUB,
58 SHXADD_ADD_SLLI_OP1,
59 SHXADD_ADD_SLLI_OP2,
60};
61
62class RISCVInstrInfo : public RISCVGenInstrInfo {
63
64public:
65 explicit RISCVInstrInfo(RISCVSubtarget &STI);
66
67 MCInst getNop() const override;
68
69 Register isLoadFromStackSlot(const MachineInstr &MI,
70 int &FrameIndex) const override;
71 Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex,
72 TypeSize &MemBytes) const override;
73 Register isStoreToStackSlot(const MachineInstr &MI,
74 int &FrameIndex) const override;
75 Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex,
76 TypeSize &MemBytes) const override;
77
78 bool isReallyTriviallyReMaterializable(const MachineInstr &MI) const override;
79
80 bool shouldBreakCriticalEdgeToSink(MachineInstr &MI) const override {
81 return MI.getOpcode() == RISCV::ADDI && MI.getOperand(i: 1).isReg() &&
82 MI.getOperand(i: 1).getReg() == RISCV::X0;
83 }
84
85 void copyPhysRegVector(MachineBasicBlock &MBB,
86 MachineBasicBlock::iterator MBBI, const DebugLoc &DL,
87 MCRegister DstReg, MCRegister SrcReg, bool KillSrc,
88 const TargetRegisterClass *RegClass) const;
89 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
90 const DebugLoc &DL, Register DstReg, Register SrcReg,
91 bool KillSrc, bool RenamableDest = false,
92 bool RenamableSrc = false) const override;
93
94 void storeRegToStackSlot(
95 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg,
96 bool IsKill, int FrameIndex, const TargetRegisterClass *RC,
97 const TargetRegisterInfo *TRI, Register VReg,
98 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
99
100 void loadRegFromStackSlot(
101 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg,
102 int FrameIndex, const TargetRegisterClass *RC,
103 const TargetRegisterInfo *TRI, Register VReg,
104 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;
105
106 using TargetInstrInfo::foldMemoryOperandImpl;
107 MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,
108 ArrayRef<unsigned> Ops,
109 MachineBasicBlock::iterator InsertPt,
110 int FrameIndex,
111 LiveIntervals *LIS = nullptr,
112 VirtRegMap *VRM = nullptr) const override;
113
114 // Materializes the given integer Val into DstReg.
115 void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
116 const DebugLoc &DL, Register DstReg, uint64_t Val,
117 MachineInstr::MIFlag Flag = MachineInstr::NoFlags,
118 bool DstRenamable = false, bool DstIsDead = false) const;
119
120 unsigned getInstSizeInBytes(const MachineInstr &MI) const override;
121
122 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
123 MachineBasicBlock *&FBB,
124 SmallVectorImpl<MachineOperand> &Cond,
125 bool AllowModify) const override;
126
127 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
128 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
129 const DebugLoc &dl,
130 int *BytesAdded = nullptr) const override;
131
132 void insertIndirectBranch(MachineBasicBlock &MBB,
133 MachineBasicBlock &NewDestBB,
134 MachineBasicBlock &RestoreBB, const DebugLoc &DL,
135 int64_t BrOffset, RegScavenger *RS) const override;
136
137 unsigned removeBranch(MachineBasicBlock &MBB,
138 int *BytesRemoved = nullptr) const override;
139
140 bool
141 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
142
143 bool optimizeCondBranch(MachineInstr &MI) const override;
144
145 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;
146
147 bool isBranchOffsetInRange(unsigned BranchOpc,
148 int64_t BrOffset) const override;
149
150 bool analyzeSelect(const MachineInstr &MI,
151 SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,
152 unsigned &FalseOp, bool &Optimizable) const override;
153
154 MachineInstr *optimizeSelect(MachineInstr &MI,
155 SmallPtrSetImpl<MachineInstr *> &SeenMIs,
156 bool) const override;
157
158 bool isAsCheapAsAMove(const MachineInstr &MI) const override;
159
160 std::optional<DestSourcePair>
161 isCopyInstrImpl(const MachineInstr &MI) const override;
162
163 bool verifyInstruction(const MachineInstr &MI,
164 StringRef &ErrInfo) const override;
165
166 bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,
167 const MachineInstr &AddrI,
168 ExtAddrMode &AM) const override;
169
170 MachineInstr *emitLdStWithAddr(MachineInstr &MemI,
171 const ExtAddrMode &AM) const override;
172
173 bool getMemOperandsWithOffsetWidth(
174 const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps,
175 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
176 const TargetRegisterInfo *TRI) const override;
177
178 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
179 int64_t Offset1, bool OffsetIsScalable1,
180 ArrayRef<const MachineOperand *> BaseOps2,
181 int64_t Offset2, bool OffsetIsScalable2,
182 unsigned ClusterSize,
183 unsigned NumBytes) const override;
184
185 bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
186 const MachineOperand *&BaseOp,
187 int64_t &Offset, LocationSize &Width,
188 const TargetRegisterInfo *TRI) const;
189
190 bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
191 const MachineInstr &MIb) const override;
192
193
194 std::pair<unsigned, unsigned>
195 decomposeMachineOperandsTargetFlags(unsigned TF) const override;
196
197 ArrayRef<std::pair<unsigned, const char *>>
198 getSerializableDirectMachineOperandTargetFlags() const override;
199
200 // Return true if the function can safely be outlined from.
201 bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
202 bool OutlineFromLinkOnceODRs) const override;
203
204 // Return true if MBB is safe to outline from, and return any target-specific
205 // information in Flags.
206 bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
207 unsigned &Flags) const override;
208
209 bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;
210
211 // Calculate target-specific information for a set of outlining candidates.
212 std::optional<std::unique_ptr<outliner::OutlinedFunction>>
213 getOutliningCandidateInfo(
214 const MachineModuleInfo &MMI,
215 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
216 unsigned MinRepeats) const override;
217
218 // Return if/how a given MachineInstr should be outlined.
219 outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,
220 MachineBasicBlock::iterator &MBBI,
221 unsigned Flags) const override;
222
223 // Insert a custom frame for outlined functions.
224 void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
225 const outliner::OutlinedFunction &OF) const override;
226
227 // Insert a call to an outlined function into a given basic block.
228 MachineBasicBlock::iterator
229 insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
230 MachineBasicBlock::iterator &It, MachineFunction &MF,
231 outliner::Candidate &C) const override;
232
233 std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
234 Register Reg) const override;
235
236 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
237 unsigned &SrcOpIdx2) const override;
238 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
239 unsigned OpIdx1,
240 unsigned OpIdx2) const override;
241
242 bool simplifyInstruction(MachineInstr &MI) const override;
243
244 MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
245 LiveIntervals *LIS) const override;
246
247 // MIR printer helper function to annotate Operands with a comment.
248 std::string
249 createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op,
250 unsigned OpIdx,
251 const TargetRegisterInfo *TRI) const override;
252
253 /// Generate code to multiply the value in DestReg by Amt - handles all
254 /// the common optimizations for this idiom, and supports fallback for
255 /// subtargets which don't support multiply instructions.
256 void mulImm(MachineFunction &MF, MachineBasicBlock &MBB,
257 MachineBasicBlock::iterator II, const DebugLoc &DL,
258 Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const;
259
260 bool useMachineCombiner() const override { return true; }
261
262 MachineTraceStrategy getMachineCombinerTraceStrategy() const override;
263
264 CombinerObjective getCombinerObjective(unsigned Pattern) const override;
265
266 bool getMachineCombinerPatterns(MachineInstr &Root,
267 SmallVectorImpl<unsigned> &Patterns,
268 bool DoRegPressureReduce) const override;
269
270 void
271 finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern,
272 SmallVectorImpl<MachineInstr *> &InsInstrs) const override;
273
274 void genAlternativeCodeSequence(
275 MachineInstr &Root, unsigned Pattern,
276 SmallVectorImpl<MachineInstr *> &InsInstrs,
277 SmallVectorImpl<MachineInstr *> &DelInstrs,
278 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const override;
279
280 bool hasReassociableOperands(const MachineInstr &Inst,
281 const MachineBasicBlock *MBB) const override;
282
283 bool hasReassociableSibling(const MachineInstr &Inst,
284 bool &Commuted) const override;
285
286 bool isAssociativeAndCommutative(const MachineInstr &Inst,
287 bool Invert) const override;
288
289 std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;
290
291 void getReassociateOperandIndices(
292 const MachineInstr &Root, unsigned Pattern,
293 std::array<unsigned, 5> &OperandIndices) const override;
294
295 ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
296 getSerializableMachineMemOperandTargetFlags() const override;
297
298 unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override;
299
300 std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
301 analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
302
303 bool isHighLatencyDef(int Opc) const override;
304
305 /// Return true if pairing the given load or store may be paired with another.
306 static bool isPairableLdStInstOpc(unsigned Opc);
307
308 static bool isLdStSafeToPair(const MachineInstr &LdSt,
309 const TargetRegisterInfo *TRI);
310#define GET_INSTRINFO_HELPER_DECLS
311#include "RISCVGenInstrInfo.inc"
312
313 static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc);
314
315 /// Return the result of the evaluation of C0 CC C1, where CC is a
316 /// RISCVCC::CondCode.
317 static bool evaluateCondBranch(RISCVCC::CondCode CC, int64_t C0, int64_t C1);
318
319 /// Return true if the operand is a load immediate instruction and
320 /// sets Imm to the immediate value.
321 static bool isFromLoadImm(const MachineRegisterInfo &MRI,
322 const MachineOperand &Op, int64_t &Imm);
323
324protected:
325 const RISCVSubtarget &STI;
326
327private:
328 unsigned getInstBundleLength(const MachineInstr &MI) const;
329
330 bool isVectorAssociativeAndCommutative(const MachineInstr &MI,
331 bool Invert = false) const;
332 bool areRVVInstsReassociable(const MachineInstr &MI1,
333 const MachineInstr &MI2) const;
334 bool hasReassociableVectorSibling(const MachineInstr &Inst,
335 bool &Commuted) const;
336};
337
338namespace RISCV {
339
340// Returns true if the given MI is an RVV instruction opcode for which we may
341// expect to see a FrameIndex operand.
342bool isRVVSpill(const MachineInstr &MI);
343
344std::optional<std::pair<unsigned, unsigned>>
345isRVVSpillForZvlsseg(unsigned Opcode);
346
347// Return true if both input instructions have equal rounding mode. If at least
348// one of the instructions does not have rounding mode, false will be returned.
349bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2);
350
351// If \p Opcode is a .vx vector instruction, returns the lower number of bits
352// that are used from the scalar .x operand for a given \p Log2SEW. Otherwise
353// returns null.
354std::optional<unsigned> getVectorLowDemandedScalarBits(unsigned Opcode,
355 unsigned Log2SEW);
356
357// Returns the MC opcode of RVV pseudo instruction.
358unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode);
359
360// For a (non-pseudo) RVV instruction \p Desc and the given \p Log2SEW, returns
361// the log2 EEW of the destination operand.
362unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW);
363
364// Special immediate for AVL operand of V pseudo instructions to indicate VLMax.
365static constexpr int64_t VLMaxSentinel = -1LL;
366
367/// Given two VL operands, do we know that LHS <= RHS?
368bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS);
369
370// Mask assignments for floating-point
371static constexpr unsigned FPMASK_Negative_Infinity = 0x001;
372static constexpr unsigned FPMASK_Negative_Normal = 0x002;
373static constexpr unsigned FPMASK_Negative_Subnormal = 0x004;
374static constexpr unsigned FPMASK_Negative_Zero = 0x008;
375static constexpr unsigned FPMASK_Positive_Zero = 0x010;
376static constexpr unsigned FPMASK_Positive_Subnormal = 0x020;
377static constexpr unsigned FPMASK_Positive_Normal = 0x040;
378static constexpr unsigned FPMASK_Positive_Infinity = 0x080;
379static constexpr unsigned FPMASK_Signaling_NaN = 0x100;
380static constexpr unsigned FPMASK_Quiet_NaN = 0x200;
381} // namespace RISCV
382
383namespace RISCVVPseudosTable {
384
385struct PseudoInfo {
386 uint16_t Pseudo;
387 uint16_t BaseInstr;
388};
389
390#define GET_RISCVVPseudosTable_DECL
391#include "RISCVGenSearchableTables.inc"
392
393} // end namespace RISCVVPseudosTable
394
395namespace RISCV {
396
397struct RISCVMaskedPseudoInfo {
398 uint16_t MaskedPseudo;
399 uint16_t UnmaskedPseudo;
400 uint8_t MaskOpIdx;
401};
402#define GET_RISCVMaskedPseudosTable_DECL
403#include "RISCVGenSearchableTables.inc"
404} // end namespace RISCV
405
406} // end namespace llvm
407#endif
408