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
28// If Value is of the form C1<<C2, where C1 = 3, 5 or 9,
29// returns log2(C1 - 1) and assigns Shift = C2.
30// Otherwise, returns 0.
31template <typename T> int isShifted359(T Value, int &Shift) {
32 if (Value == 0)
33 return 0;
34 Shift = llvm::countr_zero(Value);
35 switch (Value >> Shift) {
36 case 3:
37 return 1;
38 case 5:
39 return 2;
40 case 9:
41 return 3;
42 default:
43 return 0;
44 }
45}
46
47class RISCVSubtarget;
48
49static const MachineMemOperand::Flags MONontemporalBit0 =
50 MachineMemOperand::MOTargetFlag1;
51static const MachineMemOperand::Flags MONontemporalBit1 =
52 MachineMemOperand::MOTargetFlag2;
53
54namespace RISCVCC {
55
56enum CondCode {
57 COND_EQ,
58 COND_NE,
59 COND_LT,
60 COND_GE,
61 COND_LTU,
62 COND_GEU,
63 COND_INVALID
64};
65
66CondCode getInverseBranchCondition(CondCode);
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 bool analyzeSelect(const MachineInstr &MI,
179 SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,
180 unsigned &FalseOp, bool &Optimizable) const override;
181
182 MachineInstr *optimizeSelect(MachineInstr &MI,
183 SmallPtrSetImpl<MachineInstr *> &SeenMIs,
184 bool) const override;
185
186 bool isAsCheapAsAMove(const MachineInstr &MI) const override;
187
188 std::optional<DestSourcePair>
189 isCopyInstrImpl(const MachineInstr &MI) const override;
190
191 bool verifyInstruction(const MachineInstr &MI,
192 StringRef &ErrInfo) const override;
193
194 bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,
195 const MachineInstr &AddrI,
196 ExtAddrMode &AM) const override;
197
198 MachineInstr *emitLdStWithAddr(MachineInstr &MemI,
199 const ExtAddrMode &AM) const override;
200
201 bool getMemOperandsWithOffsetWidth(
202 const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps,
203 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
204 const TargetRegisterInfo *TRI) const override;
205
206 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,
207 int64_t Offset1, bool OffsetIsScalable1,
208 ArrayRef<const MachineOperand *> BaseOps2,
209 int64_t Offset2, bool OffsetIsScalable2,
210 unsigned ClusterSize,
211 unsigned NumBytes) const override;
212
213 bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,
214 const MachineOperand *&BaseOp,
215 int64_t &Offset, LocationSize &Width,
216 const TargetRegisterInfo *TRI) const;
217
218 bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,
219 const MachineInstr &MIb) const override;
220
221
222 std::pair<unsigned, unsigned>
223 decomposeMachineOperandsTargetFlags(unsigned TF) const override;
224
225 ArrayRef<std::pair<unsigned, const char *>>
226 getSerializableDirectMachineOperandTargetFlags() const override;
227
228 // Return true if the function can safely be outlined from.
229 bool isFunctionSafeToOutlineFrom(MachineFunction &MF,
230 bool OutlineFromLinkOnceODRs) const override;
231
232 // Return true if MBB is safe to outline from, and return any target-specific
233 // information in Flags.
234 bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
235 unsigned &Flags) const override;
236
237 bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;
238
239 bool analyzeCandidate(outliner::Candidate &C) const;
240 // Calculate target-specific information for a set of outlining candidates.
241 std::optional<std::unique_ptr<outliner::OutlinedFunction>>
242 getOutliningCandidateInfo(
243 const MachineModuleInfo &MMI,
244 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
245 unsigned MinRepeats) const override;
246
247 // Return if/how a given MachineInstr should be outlined.
248 outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,
249 MachineBasicBlock::iterator &MBBI,
250 unsigned Flags) const override;
251
252 // Insert a custom frame for outlined functions.
253 void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
254 const outliner::OutlinedFunction &OF) const override;
255
256 // Insert a call to an outlined function into a given basic block.
257 MachineBasicBlock::iterator
258 insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
259 MachineBasicBlock::iterator &It, MachineFunction &MF,
260 outliner::Candidate &C) const override;
261
262 std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,
263 Register Reg) const override;
264
265 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
266 unsigned &SrcOpIdx2) const override;
267 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,
268 unsigned OpIdx1,
269 unsigned OpIdx2) const override;
270
271 bool simplifyInstruction(MachineInstr &MI) const override;
272
273 MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,
274 LiveIntervals *LIS) const override;
275
276 // MIR printer helper function to annotate Operands with a comment.
277 std::string
278 createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op,
279 unsigned OpIdx,
280 const TargetRegisterInfo *TRI) const override;
281
282 /// Generate code to multiply the value in DestReg by Amt - handles all
283 /// the common optimizations for this idiom, and supports fallback for
284 /// subtargets which don't support multiply instructions.
285 void mulImm(MachineFunction &MF, MachineBasicBlock &MBB,
286 MachineBasicBlock::iterator II, const DebugLoc &DL,
287 Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const;
288
289 bool useMachineCombiner() const override { return true; }
290
291 MachineTraceStrategy getMachineCombinerTraceStrategy() const override;
292
293 CombinerObjective getCombinerObjective(unsigned Pattern) const override;
294
295 bool getMachineCombinerPatterns(MachineInstr &Root,
296 SmallVectorImpl<unsigned> &Patterns,
297 bool DoRegPressureReduce) const override;
298
299 void
300 finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern,
301 SmallVectorImpl<MachineInstr *> &InsInstrs) const override;
302
303 void genAlternativeCodeSequence(
304 MachineInstr &Root, unsigned Pattern,
305 SmallVectorImpl<MachineInstr *> &InsInstrs,
306 SmallVectorImpl<MachineInstr *> &DelInstrs,
307 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const override;
308
309 bool hasReassociableOperands(const MachineInstr &Inst,
310 const MachineBasicBlock *MBB) const override;
311
312 bool hasReassociableSibling(const MachineInstr &Inst,
313 bool &Commuted) const override;
314
315 bool isAssociativeAndCommutative(const MachineInstr &Inst,
316 bool Invert) const override;
317
318 std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;
319
320 void getReassociateOperandIndices(
321 const MachineInstr &Root, unsigned Pattern,
322 std::array<unsigned, 5> &OperandIndices) const override;
323
324 ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>
325 getSerializableMachineMemOperandTargetFlags() const override;
326
327 unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override;
328
329 std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
330 analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;
331
332 bool isHighLatencyDef(int Opc) const override;
333
334 /// Return true if \p MI is a COPY to a vector register of a specific \p LMul,
335 /// or any kind of vector registers when \p LMul is zero.
336 bool isVRegCopy(const MachineInstr *MI, unsigned LMul = 0) const;
337
338 /// Return true if pairing the given load or store may be paired with another.
339 static bool isPairableLdStInstOpc(unsigned Opc);
340
341 static bool isLdStSafeToPair(const MachineInstr &LdSt,
342 const TargetRegisterInfo *TRI);
343#define GET_INSTRINFO_HELPER_DECLS
344#include "RISCVGenInstrInfo.inc"
345
346 static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc);
347
348 /// Return the result of the evaluation of C0 CC C1, where CC is a
349 /// RISCVCC::CondCode.
350 static bool evaluateCondBranch(RISCVCC::CondCode CC, int64_t C0, int64_t C1);
351
352 /// Return true if the operand is a load immediate instruction and
353 /// sets Imm to the immediate value.
354 static bool isFromLoadImm(const MachineRegisterInfo &MRI,
355 const MachineOperand &Op, int64_t &Imm);
356
357protected:
358 const RISCVSubtarget &STI;
359
360private:
361 unsigned getInstBundleLength(const MachineInstr &MI) const;
362
363 bool isVectorAssociativeAndCommutative(const MachineInstr &MI,
364 bool Invert = false) const;
365 bool areRVVInstsReassociable(const MachineInstr &MI1,
366 const MachineInstr &MI2) const;
367 bool hasReassociableVectorSibling(const MachineInstr &Inst,
368 bool &Commuted) const;
369};
370
371namespace RISCV {
372
373// Returns true if the given MI is an RVV instruction opcode for which we may
374// expect to see a FrameIndex operand.
375bool isRVVSpill(const MachineInstr &MI);
376
377/// Return true if \p MI is a copy that will be lowered to one or more vmvNr.vs.
378bool isVectorCopy(const TargetRegisterInfo *TRI, const MachineInstr &MI);
379
380std::optional<std::pair<unsigned, unsigned>>
381isRVVSpillForZvlsseg(unsigned Opcode);
382
383// Return true if both input instructions have equal rounding mode. If at least
384// one of the instructions does not have rounding mode, false will be returned.
385bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2);
386
387// If \p Opcode is a .vx vector instruction, returns the lower number of bits
388// that are used from the scalar .x operand for a given \p Log2SEW. Otherwise
389// returns null.
390std::optional<unsigned> getVectorLowDemandedScalarBits(unsigned Opcode,
391 unsigned Log2SEW);
392
393// Returns the MC opcode of RVV pseudo instruction.
394unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode);
395
396// For a (non-pseudo) RVV instruction \p Desc and the given \p Log2SEW, returns
397// the log2 EEW of the destination operand.
398unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW);
399
400// Special immediate for AVL operand of V pseudo instructions to indicate VLMax.
401static constexpr int64_t VLMaxSentinel = -1LL;
402
403/// Given two VL operands, do we know that LHS <= RHS?
404bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS);
405
406// Mask assignments for floating-point
407static constexpr unsigned FPMASK_Negative_Infinity = 0x001;
408static constexpr unsigned FPMASK_Negative_Normal = 0x002;
409static constexpr unsigned FPMASK_Negative_Subnormal = 0x004;
410static constexpr unsigned FPMASK_Negative_Zero = 0x008;
411static constexpr unsigned FPMASK_Positive_Zero = 0x010;
412static constexpr unsigned FPMASK_Positive_Subnormal = 0x020;
413static constexpr unsigned FPMASK_Positive_Normal = 0x040;
414static constexpr unsigned FPMASK_Positive_Infinity = 0x080;
415static constexpr unsigned FPMASK_Signaling_NaN = 0x100;
416static constexpr unsigned FPMASK_Quiet_NaN = 0x200;
417} // namespace RISCV
418
419namespace RISCVVPseudosTable {
420
421struct PseudoInfo {
422 uint16_t Pseudo;
423 uint16_t BaseInstr;
424 uint16_t VLMul : 3;
425 uint16_t SEW : 8;
426 uint16_t IsAltFmt : 1;
427};
428
429#define GET_RISCVVPseudosTable_DECL
430#include "RISCVGenSearchableTables.inc"
431
432} // end namespace RISCVVPseudosTable
433
434namespace RISCV {
435
436struct RISCVMaskedPseudoInfo {
437 uint16_t MaskedPseudo;
438 uint16_t UnmaskedPseudo;
439 uint8_t MaskOpIdx;
440};
441#define GET_RISCVMaskedPseudosTable_DECL
442#include "RISCVGenSearchableTables.inc"
443} // end namespace RISCV
444
445} // end namespace llvm
446#endif
447