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, bool Imm = false); 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 const MCInstrDesc &getBrCond(RISCVCC::CondCode CC, bool Imm = false) const; 69 70 Register isLoadFromStackSlot(const MachineInstr &MI, 71 int &FrameIndex) const override; 72 Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex, 73 unsigned &MemBytes) const override; 74 Register isStoreToStackSlot(const MachineInstr &MI, 75 int &FrameIndex) const override; 76 Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex, 77 unsigned &MemBytes) const override; 78 79 bool isReallyTriviallyReMaterializable(const MachineInstr &MI) const override; 80 81 bool shouldBreakCriticalEdgeToSink(MachineInstr &MI) const override { 82 return MI.getOpcode() == RISCV::ADDI && MI.getOperand(1).isReg() && 83 MI.getOperand(1).getReg() == RISCV::X0; 84 } 85 86 void copyPhysRegVector(MachineBasicBlock &MBB, 87 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 88 MCRegister DstReg, MCRegister SrcReg, bool KillSrc, 89 const TargetRegisterClass *RegClass) const; 90 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 91 const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, 92 bool KillSrc, bool RenamableDest = false, 93 bool RenamableSrc = false) const override; 94 95 void storeRegToStackSlot( 96 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, 97 bool IsKill, int FrameIndex, const TargetRegisterClass *RC, 98 const TargetRegisterInfo *TRI, Register VReg, 99 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override; 100 101 void loadRegFromStackSlot( 102 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, 103 int FrameIndex, const TargetRegisterClass *RC, 104 const TargetRegisterInfo *TRI, Register VReg, 105 MachineInstr::MIFlag Flags = MachineInstr::NoFlags) const override; 106 107 using TargetInstrInfo::foldMemoryOperandImpl; 108 MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 109 ArrayRef<unsigned> Ops, 110 MachineBasicBlock::iterator InsertPt, 111 int FrameIndex, 112 LiveIntervals *LIS = nullptr, 113 VirtRegMap *VRM = nullptr) const override; 114 115 // Materializes the given integer Val into DstReg. 116 void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 117 const DebugLoc &DL, Register DstReg, uint64_t Val, 118 MachineInstr::MIFlag Flag = MachineInstr::NoFlags, 119 bool DstRenamable = false, bool DstIsDead = false) const; 120 121 unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 122 123 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 124 MachineBasicBlock *&FBB, 125 SmallVectorImpl<MachineOperand> &Cond, 126 bool AllowModify) const override; 127 128 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 129 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 130 const DebugLoc &dl, 131 int *BytesAdded = nullptr) const override; 132 133 void insertIndirectBranch(MachineBasicBlock &MBB, 134 MachineBasicBlock &NewDestBB, 135 MachineBasicBlock &RestoreBB, const DebugLoc &DL, 136 int64_t BrOffset, RegScavenger *RS) const override; 137 138 unsigned removeBranch(MachineBasicBlock &MBB, 139 int *BytesRemoved = nullptr) const override; 140 141 bool 142 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; 143 144 bool optimizeCondBranch(MachineInstr &MI) const override; 145 146 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; 147 148 bool isBranchOffsetInRange(unsigned BranchOpc, 149 int64_t BrOffset) const override; 150 151 bool analyzeSelect(const MachineInstr &MI, 152 SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp, 153 unsigned &FalseOp, bool &Optimizable) const override; 154 155 MachineInstr *optimizeSelect(MachineInstr &MI, 156 SmallPtrSetImpl<MachineInstr *> &SeenMIs, 157 bool) const override; 158 159 bool isAsCheapAsAMove(const MachineInstr &MI) const override; 160 161 std::optional<DestSourcePair> 162 isCopyInstrImpl(const MachineInstr &MI) const override; 163 164 bool verifyInstruction(const MachineInstr &MI, 165 StringRef &ErrInfo) const override; 166 167 bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, 168 const MachineInstr &AddrI, 169 ExtAddrMode &AM) const override; 170 171 MachineInstr *emitLdStWithAddr(MachineInstr &MemI, 172 const ExtAddrMode &AM) const override; 173 174 bool getMemOperandsWithOffsetWidth( 175 const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps, 176 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, 177 const TargetRegisterInfo *TRI) const override; 178 179 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1, 180 int64_t Offset1, bool OffsetIsScalable1, 181 ArrayRef<const MachineOperand *> BaseOps2, 182 int64_t Offset2, bool OffsetIsScalable2, 183 unsigned ClusterSize, 184 unsigned NumBytes) const override; 185 186 bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, 187 const MachineOperand *&BaseOp, 188 int64_t &Offset, LocationSize &Width, 189 const TargetRegisterInfo *TRI) const; 190 191 bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 192 const MachineInstr &MIb) const override; 193 194 195 std::pair<unsigned, unsigned> 196 decomposeMachineOperandsTargetFlags(unsigned TF) const override; 197 198 ArrayRef<std::pair<unsigned, const char *>> 199 getSerializableDirectMachineOperandTargetFlags() const override; 200 201 // Return true if the function can safely be outlined from. 202 bool isFunctionSafeToOutlineFrom(MachineFunction &MF, 203 bool OutlineFromLinkOnceODRs) const override; 204 205 // Return true if MBB is safe to outline from, and return any target-specific 206 // information in Flags. 207 bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, 208 unsigned &Flags) const override; 209 210 bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override; 211 212 // Calculate target-specific information for a set of outlining candidates. 213 std::optional<std::unique_ptr<outliner::OutlinedFunction>> 214 getOutliningCandidateInfo( 215 const MachineModuleInfo &MMI, 216 std::vector<outliner::Candidate> &RepeatedSequenceLocs, 217 unsigned MinRepeats) const override; 218 219 // Return if/how a given MachineInstr should be outlined. 220 virtual outliner::InstrType 221 getOutliningTypeImpl(const MachineModuleInfo &MMI, 222 MachineBasicBlock::iterator &MBBI, 223 unsigned Flags) const override; 224 225 // Insert a custom frame for outlined functions. 226 void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, 227 const outliner::OutlinedFunction &OF) const override; 228 229 // Insert a call to an outlined function into a given basic block. 230 MachineBasicBlock::iterator 231 insertOutlinedCall(Module &M, MachineBasicBlock &MBB, 232 MachineBasicBlock::iterator &It, MachineFunction &MF, 233 outliner::Candidate &C) const override; 234 235 std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI, 236 Register Reg) const override; 237 238 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 239 unsigned &SrcOpIdx2) const override; 240 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 241 unsigned OpIdx1, 242 unsigned OpIdx2) 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<unsigned, 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 protected: 304 const RISCVSubtarget &STI; 305 306 private: 307 unsigned getInstBundleLength(const MachineInstr &MI) const; 308 309 bool isVectorAssociativeAndCommutative(const MachineInstr &MI, 310 bool Invert = false) const; 311 bool areRVVInstsReassociable(const MachineInstr &MI1, 312 const MachineInstr &MI2) const; 313 bool hasReassociableVectorSibling(const MachineInstr &Inst, 314 bool &Commuted) const; 315 }; 316 317 namespace RISCV { 318 319 // Returns true if this is the sext.w pattern, addiw rd, rs1, 0. 320 bool isSEXT_W(const MachineInstr &MI); 321 bool isZEXT_W(const MachineInstr &MI); 322 bool isZEXT_B(const MachineInstr &MI); 323 324 // Returns true if the given MI is an RVV instruction opcode for which we may 325 // expect to see a FrameIndex operand. 326 bool isRVVSpill(const MachineInstr &MI); 327 328 std::optional<std::pair<unsigned, unsigned>> 329 isRVVSpillForZvlsseg(unsigned Opcode); 330 331 bool isFaultFirstLoad(const MachineInstr &MI); 332 333 // Implemented in RISCVGenInstrInfo.inc 334 int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); 335 336 // Return true if both input instructions have equal rounding mode. If at least 337 // one of the instructions does not have rounding mode, false will be returned. 338 bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2); 339 340 // If \p Opcode is a .vx vector instruction, returns the lower number of bits 341 // that are used from the scalar .x operand for a given \p Log2SEW. Otherwise 342 // returns null. 343 std::optional<unsigned> getVectorLowDemandedScalarBits(uint16_t Opcode, 344 unsigned Log2SEW); 345 346 // Returns the MC opcode of RVV pseudo instruction. 347 unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode); 348 349 // For a (non-pseudo) RVV instruction \p Desc and the given \p Log2SEW, returns 350 // the log2 EEW of the destination operand. 351 unsigned getDestLog2EEW(const MCInstrDesc &Desc, unsigned Log2SEW); 352 353 // Special immediate for AVL operand of V pseudo instructions to indicate VLMax. 354 static constexpr int64_t VLMaxSentinel = -1LL; 355 356 /// Given two VL operands, do we know that LHS <= RHS? 357 bool isVLKnownLE(const MachineOperand &LHS, const MachineOperand &RHS); 358 359 // Mask assignments for floating-point 360 static constexpr unsigned FPMASK_Negative_Infinity = 0x001; 361 static constexpr unsigned FPMASK_Negative_Normal = 0x002; 362 static constexpr unsigned FPMASK_Negative_Subnormal = 0x004; 363 static constexpr unsigned FPMASK_Negative_Zero = 0x008; 364 static constexpr unsigned FPMASK_Positive_Zero = 0x010; 365 static constexpr unsigned FPMASK_Positive_Subnormal = 0x020; 366 static constexpr unsigned FPMASK_Positive_Normal = 0x040; 367 static constexpr unsigned FPMASK_Positive_Infinity = 0x080; 368 static constexpr unsigned FPMASK_Signaling_NaN = 0x100; 369 static constexpr unsigned FPMASK_Quiet_NaN = 0x200; 370 } // namespace RISCV 371 372 namespace RISCVVPseudosTable { 373 374 struct PseudoInfo { 375 uint16_t Pseudo; 376 uint16_t BaseInstr; 377 }; 378 379 #define GET_RISCVVPseudosTable_DECL 380 #include "RISCVGenSearchableTables.inc" 381 382 } // end namespace RISCVVPseudosTable 383 384 namespace RISCV { 385 386 struct RISCVMaskedPseudoInfo { 387 uint16_t MaskedPseudo; 388 uint16_t UnmaskedPseudo; 389 uint8_t MaskOpIdx; 390 }; 391 #define GET_RISCVMaskedPseudosTable_DECL 392 #include "RISCVGenSearchableTables.inc" 393 } // end namespace RISCV 394 395 } // end namespace llvm 396 #endif 397