430 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the RISC-V implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#ifndef LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H14#define LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H15 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_HEADER22#define GET_INSTRINFO_OPERAND_ENUM23#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_INVALID64};65 66CondCode getInverseBranchCondition(CondCode);67unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0);68 69} // end of namespace RISCVCC70 71// RISCV MachineCombiner patterns72enum 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(1).isReg() &&104 MI.getOperand(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 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override;127 128 using TargetInstrInfo::foldMemoryOperandImpl;129 MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI,130 ArrayRef<unsigned> Ops,131 MachineBasicBlock::iterator InsertPt,132 int FrameIndex,133 LiveIntervals *LIS = nullptr,134 VirtRegMap *VRM = nullptr) const override;135 136 // Materializes the given integer Val into DstReg.137 void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,138 const DebugLoc &DL, Register DstReg, uint64_t Val,139 MachineInstr::MIFlag Flag = MachineInstr::NoFlags,140 bool DstRenamable = false, bool DstIsDead = false) const;141 142 unsigned getInstSizeInBytes(const MachineInstr &MI) const override;143 144 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,145 MachineBasicBlock *&FBB,146 SmallVectorImpl<MachineOperand> &Cond,147 bool AllowModify) const override;148 149 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,150 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,151 const DebugLoc &dl,152 int *BytesAdded = nullptr) const override;153 154 void insertIndirectBranch(MachineBasicBlock &MBB,155 MachineBasicBlock &NewDestBB,156 MachineBasicBlock &RestoreBB, const DebugLoc &DL,157 int64_t BrOffset, RegScavenger *RS) const override;158 159 unsigned removeBranch(MachineBasicBlock &MBB,160 int *BytesRemoved = nullptr) const override;161 162 bool163 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;164 165 bool optimizeCondBranch(MachineInstr &MI) const override;166 167 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override;168 169 bool isBranchOffsetInRange(unsigned BranchOpc,170 int64_t BrOffset) const override;171 172 bool analyzeSelect(const MachineInstr &MI,173 SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp,174 unsigned &FalseOp, bool &Optimizable) const override;175 176 MachineInstr *optimizeSelect(MachineInstr &MI,177 SmallPtrSetImpl<MachineInstr *> &SeenMIs,178 bool) const override;179 180 bool isAsCheapAsAMove(const MachineInstr &MI) const override;181 182 std::optional<DestSourcePair>183 isCopyInstrImpl(const MachineInstr &MI) const override;184 185 bool verifyInstruction(const MachineInstr &MI,186 StringRef &ErrInfo) const override;187 188 bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg,189 const MachineInstr &AddrI,190 ExtAddrMode &AM) const override;191 192 MachineInstr *emitLdStWithAddr(MachineInstr &MemI,193 const ExtAddrMode &AM) const override;194 195 bool getMemOperandsWithOffsetWidth(196 const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps,197 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,198 const TargetRegisterInfo *TRI) const override;199 200 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1,201 int64_t Offset1, bool OffsetIsScalable1,202 ArrayRef<const MachineOperand *> BaseOps2,203 int64_t Offset2, bool OffsetIsScalable2,204 unsigned ClusterSize,205 unsigned NumBytes) const override;206 207 bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt,208 const MachineOperand *&BaseOp,209 int64_t &Offset, LocationSize &Width,210 const TargetRegisterInfo *TRI) const;211 212 bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa,213 const MachineInstr &MIb) const override;214 215 216 std::pair<unsigned, unsigned>217 decomposeMachineOperandsTargetFlags(unsigned TF) const override;218 219 ArrayRef<std::pair<unsigned, const char *>>220 getSerializableDirectMachineOperandTargetFlags() const override;221 222 // Return true if the function can safely be outlined from.223 bool isFunctionSafeToOutlineFrom(MachineFunction &MF,224 bool OutlineFromLinkOnceODRs) const override;225 226 // Return true if MBB is safe to outline from, and return any target-specific227 // information in Flags.228 bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,229 unsigned &Flags) const override;230 231 bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override;232 233 // Calculate target-specific information for a set of outlining candidates.234 std::optional<std::unique_ptr<outliner::OutlinedFunction>>235 getOutliningCandidateInfo(236 const MachineModuleInfo &MMI,237 std::vector<outliner::Candidate> &RepeatedSequenceLocs,238 unsigned MinRepeats) const override;239 240 // Return if/how a given MachineInstr should be outlined.241 outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,242 MachineBasicBlock::iterator &MBBI,243 unsigned Flags) const override;244 245 // Insert a custom frame for outlined functions.246 void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,247 const outliner::OutlinedFunction &OF) const override;248 249 // Insert a call to an outlined function into a given basic block.250 MachineBasicBlock::iterator251 insertOutlinedCall(Module &M, MachineBasicBlock &MBB,252 MachineBasicBlock::iterator &It, MachineFunction &MF,253 outliner::Candidate &C) const override;254 255 std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI,256 Register Reg) const override;257 258 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,259 unsigned &SrcOpIdx2) const override;260 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI,261 unsigned OpIdx1,262 unsigned OpIdx2) const override;263 264 bool simplifyInstruction(MachineInstr &MI) const override;265 266 MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV,267 LiveIntervals *LIS) const override;268 269 // MIR printer helper function to annotate Operands with a comment.270 std::string271 createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op,272 unsigned OpIdx,273 const TargetRegisterInfo *TRI) const override;274 275 /// Generate code to multiply the value in DestReg by Amt - handles all276 /// the common optimizations for this idiom, and supports fallback for277 /// subtargets which don't support multiply instructions.278 void mulImm(MachineFunction &MF, MachineBasicBlock &MBB,279 MachineBasicBlock::iterator II, const DebugLoc &DL,280 Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const;281 282 bool useMachineCombiner() const override { return true; }283 284 MachineTraceStrategy getMachineCombinerTraceStrategy() const override;285 286 CombinerObjective getCombinerObjective(unsigned Pattern) const override;287 288 bool getMachineCombinerPatterns(MachineInstr &Root,289 SmallVectorImpl<unsigned> &Patterns,290 bool DoRegPressureReduce) const override;291 292 void293 finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern,294 SmallVectorImpl<MachineInstr *> &InsInstrs) const override;295 296 void genAlternativeCodeSequence(297 MachineInstr &Root, unsigned Pattern,298 SmallVectorImpl<MachineInstr *> &InsInstrs,299 SmallVectorImpl<MachineInstr *> &DelInstrs,300 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const override;301 302 bool hasReassociableOperands(const MachineInstr &Inst,303 const MachineBasicBlock *MBB) const override;304 305 bool hasReassociableSibling(const MachineInstr &Inst,306 bool &Commuted) const override;307 308 bool isAssociativeAndCommutative(const MachineInstr &Inst,309 bool Invert) const override;310 311 std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override;312 313 void getReassociateOperandIndices(314 const MachineInstr &Root, unsigned Pattern,315 std::array<unsigned, 5> &OperandIndices) const override;316 317 ArrayRef<std::pair<MachineMemOperand::Flags, const char *>>318 getSerializableMachineMemOperandTargetFlags() const override;319 320 unsigned getTailDuplicateSize(CodeGenOptLevel OptLevel) const override;321 322 std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>323 analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override;324 325 bool isHighLatencyDef(int Opc) const override;326 327 /// Return true if pairing the given load or store may be paired with another.328 static bool isPairableLdStInstOpc(unsigned Opc);329 330 static bool isLdStSafeToPair(const MachineInstr &LdSt,331 const TargetRegisterInfo *TRI);332#define GET_INSTRINFO_HELPER_DECLS333#include "RISCVGenInstrInfo.inc"334 335 static RISCVCC::CondCode getCondFromBranchOpc(unsigned Opc);336 337 /// Return the result of the evaluation of C0 CC C1, where CC is a338 /// RISCVCC::CondCode.339 static bool evaluateCondBranch(RISCVCC::CondCode CC, int64_t C0, int64_t C1);340 341 /// Return true if the operand is a load immediate instruction and342 /// sets Imm to the immediate value.343 static bool isFromLoadImm(const MachineRegisterInfo &MRI,344 const MachineOperand &Op, int64_t &Imm);345 346protected:347 const RISCVSubtarget &STI;348 349private:350 unsigned getInstBundleLength(const MachineInstr &MI) const;351 352 bool isVectorAssociativeAndCommutative(const MachineInstr &MI,353 bool Invert = false) const;354 bool areRVVInstsReassociable(const MachineInstr &MI1,355 const MachineInstr &MI2) const;356 bool hasReassociableVectorSibling(const MachineInstr &Inst,357 bool &Commuted) const;358};359 360namespace RISCV {361 362// Returns true if the given MI is an RVV instruction opcode for which we may363// expect to see a FrameIndex operand.364bool isRVVSpill(const MachineInstr &MI);365 366std::optional<std::pair<unsigned, unsigned>>367isRVVSpillForZvlsseg(unsigned Opcode);368 369// Return true if both input instructions have equal rounding mode. If at least370// one of the instructions does not have rounding mode, false will be returned.371bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2);372 373// If \p Opcode is a .vx vector instruction, returns the lower number of bits374// that are used from the scalar .x operand for a given \p Log2SEW. Otherwise375// returns null.376std::optional<unsigned> getVectorLowDemandedScalarBits(unsigned Opcode,377 unsigned Log2SEW);378 379// Returns the MC opcode of RVV pseudo instruction.380unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode);381 382// For a (non-pseudo) RVV instruction \p Desc and the given \p Log2SEW, returns383// the log2 EEW of the destination operand.384unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW);385 386// Special immediate for AVL operand of V pseudo instructions to indicate VLMax.387static constexpr int64_t VLMaxSentinel = -1LL;388 389/// Given two VL operands, do we know that LHS <= RHS?390bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS);391 392// Mask assignments for floating-point393static constexpr unsigned FPMASK_Negative_Infinity = 0x001;394static constexpr unsigned FPMASK_Negative_Normal = 0x002;395static constexpr unsigned FPMASK_Negative_Subnormal = 0x004;396static constexpr unsigned FPMASK_Negative_Zero = 0x008;397static constexpr unsigned FPMASK_Positive_Zero = 0x010;398static constexpr unsigned FPMASK_Positive_Subnormal = 0x020;399static constexpr unsigned FPMASK_Positive_Normal = 0x040;400static constexpr unsigned FPMASK_Positive_Infinity = 0x080;401static constexpr unsigned FPMASK_Signaling_NaN = 0x100;402static constexpr unsigned FPMASK_Quiet_NaN = 0x200;403} // namespace RISCV404 405namespace RISCVVPseudosTable {406 407struct PseudoInfo {408 uint16_t Pseudo;409 uint16_t BaseInstr;410};411 412#define GET_RISCVVPseudosTable_DECL413#include "RISCVGenSearchableTables.inc"414 415} // end namespace RISCVVPseudosTable416 417namespace RISCV {418 419struct RISCVMaskedPseudoInfo {420 uint16_t MaskedPseudo;421 uint16_t UnmaskedPseudo;422 uint8_t MaskOpIdx;423};424#define GET_RISCVMaskedPseudosTable_DECL425#include "RISCVGenSearchableTables.inc"426} // end namespace RISCV427 428} // end namespace llvm429#endif430