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 26 namespace llvm { 27 28 class RISCVSubtarget; 29 30 static const MachineMemOperand::Flags MONontemporalBit0 = 31 MachineMemOperand::MOTargetFlag1; 32 static const MachineMemOperand::Flags MONontemporalBit1 = 33 MachineMemOperand::MOTargetFlag2; 34 35 namespace RISCVCC { 36 37 enum CondCode { 38 COND_EQ, 39 COND_NE, 40 COND_LT, 41 COND_GE, 42 COND_LTU, 43 COND_GEU, 44 COND_INVALID 45 }; 46 47 CondCode getOppositeBranchCondition(CondCode); 48 unsigned getBrCond(CondCode CC, unsigned SelectOpc = 0); 49 50 } // end of namespace RISCVCC 51 52 // RISCV MachineCombiner patterns 53 enum 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 62 class RISCVInstrInfo : public RISCVGenInstrInfo { 63 64 public: 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 shouldBreakCriticalEdgeToSink(MachineInstr & MI)80 bool shouldBreakCriticalEdgeToSink(MachineInstr &MI) const override { 81 return MI.getOpcode() == RISCV::ADDI && MI.getOperand(1).isReg() && 82 MI.getOperand(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 useMachineCombiner()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 324 protected: 325 const RISCVSubtarget &STI; 326 327 private: 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 338 namespace 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. 342 bool isRVVSpill(const MachineInstr &MI); 343 344 std::optional<std::pair<unsigned, unsigned>> 345 isRVVSpillForZvlsseg(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. 349 bool 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. 354 std::optional<unsigned> getVectorLowDemandedScalarBits(unsigned Opcode, 355 unsigned Log2SEW); 356 357 // Returns the MC opcode of RVV pseudo instruction. 358 unsigned 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. 362 unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW); 363 364 // Special immediate for AVL operand of V pseudo instructions to indicate VLMax. 365 static constexpr int64_t VLMaxSentinel = -1LL; 366 367 /// Given two VL operands, do we know that LHS <= RHS? 368 bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS); 369 370 // Mask assignments for floating-point 371 static constexpr unsigned FPMASK_Negative_Infinity = 0x001; 372 static constexpr unsigned FPMASK_Negative_Normal = 0x002; 373 static constexpr unsigned FPMASK_Negative_Subnormal = 0x004; 374 static constexpr unsigned FPMASK_Negative_Zero = 0x008; 375 static constexpr unsigned FPMASK_Positive_Zero = 0x010; 376 static constexpr unsigned FPMASK_Positive_Subnormal = 0x020; 377 static constexpr unsigned FPMASK_Positive_Normal = 0x040; 378 static constexpr unsigned FPMASK_Positive_Infinity = 0x080; 379 static constexpr unsigned FPMASK_Signaling_NaN = 0x100; 380 static constexpr unsigned FPMASK_Quiet_NaN = 0x200; 381 } // namespace RISCV 382 383 namespace RISCVVPseudosTable { 384 385 struct 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 395 namespace RISCV { 396 397 struct 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