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