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 void copyPhysRegVector(MachineBasicBlock &MBB, 82 MachineBasicBlock::iterator MBBI, const DebugLoc &DL, 83 MCRegister DstReg, MCRegister SrcReg, bool KillSrc, 84 const TargetRegisterClass *RegClass) const; 85 void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 86 const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, 87 bool KillSrc) const override; 88 89 void storeRegToStackSlot(MachineBasicBlock &MBB, 90 MachineBasicBlock::iterator MBBI, Register SrcReg, 91 bool IsKill, int FrameIndex, 92 const TargetRegisterClass *RC, 93 const TargetRegisterInfo *TRI, 94 Register VReg) const override; 95 96 void loadRegFromStackSlot(MachineBasicBlock &MBB, 97 MachineBasicBlock::iterator MBBI, Register DstReg, 98 int FrameIndex, const TargetRegisterClass *RC, 99 const TargetRegisterInfo *TRI, 100 Register VReg) const override; 101 102 using TargetInstrInfo::foldMemoryOperandImpl; 103 MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 104 ArrayRef<unsigned> Ops, 105 MachineBasicBlock::iterator InsertPt, 106 int FrameIndex, 107 LiveIntervals *LIS = nullptr, 108 VirtRegMap *VRM = nullptr) const override; 109 110 // Materializes the given integer Val into DstReg. 111 void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 112 const DebugLoc &DL, Register DstReg, uint64_t Val, 113 MachineInstr::MIFlag Flag = MachineInstr::NoFlags, 114 bool DstRenamable = false, bool DstIsDead = false) const; 115 116 unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 117 118 bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 119 MachineBasicBlock *&FBB, 120 SmallVectorImpl<MachineOperand> &Cond, 121 bool AllowModify) const override; 122 123 unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 124 MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 125 const DebugLoc &dl, 126 int *BytesAdded = nullptr) const override; 127 128 void insertIndirectBranch(MachineBasicBlock &MBB, 129 MachineBasicBlock &NewDestBB, 130 MachineBasicBlock &RestoreBB, const DebugLoc &DL, 131 int64_t BrOffset, RegScavenger *RS) const override; 132 133 unsigned removeBranch(MachineBasicBlock &MBB, 134 int *BytesRemoved = nullptr) const override; 135 136 bool 137 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; 138 139 bool optimizeCondBranch(MachineInstr &MI) const override; 140 141 MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; 142 143 bool isBranchOffsetInRange(unsigned BranchOpc, 144 int64_t BrOffset) const override; 145 146 bool analyzeSelect(const MachineInstr &MI, 147 SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp, 148 unsigned &FalseOp, bool &Optimizable) const override; 149 150 MachineInstr *optimizeSelect(MachineInstr &MI, 151 SmallPtrSetImpl<MachineInstr *> &SeenMIs, 152 bool) const override; 153 154 bool isAsCheapAsAMove(const MachineInstr &MI) const override; 155 156 std::optional<DestSourcePair> 157 isCopyInstrImpl(const MachineInstr &MI) const override; 158 159 bool verifyInstruction(const MachineInstr &MI, 160 StringRef &ErrInfo) const override; 161 162 bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, 163 const MachineInstr &AddrI, 164 ExtAddrMode &AM) const override; 165 166 MachineInstr *emitLdStWithAddr(MachineInstr &MemI, 167 const ExtAddrMode &AM) const override; 168 169 bool getMemOperandsWithOffsetWidth( 170 const MachineInstr &MI, SmallVectorImpl<const MachineOperand *> &BaseOps, 171 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, 172 const TargetRegisterInfo *TRI) const override; 173 174 bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1, 175 int64_t Offset1, bool OffsetIsScalable1, 176 ArrayRef<const MachineOperand *> BaseOps2, 177 int64_t Offset2, bool OffsetIsScalable2, 178 unsigned ClusterSize, 179 unsigned NumBytes) const override; 180 181 bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, 182 const MachineOperand *&BaseOp, 183 int64_t &Offset, LocationSize &Width, 184 const TargetRegisterInfo *TRI) const; 185 186 bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 187 const MachineInstr &MIb) const override; 188 189 190 std::pair<unsigned, unsigned> 191 decomposeMachineOperandsTargetFlags(unsigned TF) const override; 192 193 ArrayRef<std::pair<unsigned, const char *>> 194 getSerializableDirectMachineOperandTargetFlags() const override; 195 196 // Return true if the function can safely be outlined from. 197 bool isFunctionSafeToOutlineFrom(MachineFunction &MF, 198 bool OutlineFromLinkOnceODRs) const override; 199 200 // Return true if MBB is safe to outline from, and return any target-specific 201 // information in Flags. 202 bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, 203 unsigned &Flags) const override; 204 205 bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override; 206 207 // Calculate target-specific information for a set of outlining candidates. 208 std::optional<outliner::OutlinedFunction> getOutliningCandidateInfo( 209 std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override; 210 211 // Return if/how a given MachineInstr should be outlined. 212 virtual outliner::InstrType 213 getOutliningTypeImpl(MachineBasicBlock::iterator &MBBI, 214 unsigned Flags) const override; 215 216 // Insert a custom frame for outlined functions. 217 void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, 218 const outliner::OutlinedFunction &OF) const override; 219 220 // Insert a call to an outlined function into a given basic block. 221 MachineBasicBlock::iterator 222 insertOutlinedCall(Module &M, MachineBasicBlock &MBB, 223 MachineBasicBlock::iterator &It, MachineFunction &MF, 224 outliner::Candidate &C) const override; 225 226 std::optional<RegImmPair> isAddImmediate(const MachineInstr &MI, 227 Register Reg) const override; 228 229 bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 230 unsigned &SrcOpIdx2) const override; 231 MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 232 unsigned OpIdx1, 233 unsigned OpIdx2) const override; 234 235 MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, 236 LiveIntervals *LIS) const override; 237 238 // MIR printer helper function to annotate Operands with a comment. 239 std::string 240 createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, 241 unsigned OpIdx, 242 const TargetRegisterInfo *TRI) const override; 243 244 /// Generate code to multiply the value in DestReg by Amt - handles all 245 /// the common optimizations for this idiom, and supports fallback for 246 /// subtargets which don't support multiply instructions. 247 void mulImm(MachineFunction &MF, MachineBasicBlock &MBB, 248 MachineBasicBlock::iterator II, const DebugLoc &DL, 249 Register DestReg, uint32_t Amt, MachineInstr::MIFlag Flag) const; 250 useMachineCombiner()251 bool useMachineCombiner() const override { return true; } 252 253 MachineTraceStrategy getMachineCombinerTraceStrategy() const override; 254 255 CombinerObjective getCombinerObjective(unsigned Pattern) const override; 256 257 bool getMachineCombinerPatterns(MachineInstr &Root, 258 SmallVectorImpl<unsigned> &Patterns, 259 bool DoRegPressureReduce) const override; 260 261 void 262 finalizeInsInstrs(MachineInstr &Root, unsigned &Pattern, 263 SmallVectorImpl<MachineInstr *> &InsInstrs) const override; 264 265 void genAlternativeCodeSequence( 266 MachineInstr &Root, unsigned Pattern, 267 SmallVectorImpl<MachineInstr *> &InsInstrs, 268 SmallVectorImpl<MachineInstr *> &DelInstrs, 269 DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override; 270 271 bool hasReassociableOperands(const MachineInstr &Inst, 272 const MachineBasicBlock *MBB) const override; 273 274 bool hasReassociableSibling(const MachineInstr &Inst, 275 bool &Commuted) const override; 276 277 bool isAssociativeAndCommutative(const MachineInstr &Inst, 278 bool Invert) const override; 279 280 std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override; 281 282 void getReassociateOperandIndices( 283 const MachineInstr &Root, unsigned Pattern, 284 std::array<unsigned, 5> &OperandIndices) const override; 285 286 ArrayRef<std::pair<MachineMemOperand::Flags, const char *>> 287 getSerializableMachineMemOperandTargetFlags() const override; 288 getUndefInitOpcode(unsigned RegClassID)289 unsigned getUndefInitOpcode(unsigned RegClassID) const override { 290 switch (RegClassID) { 291 case RISCV::VRRegClassID: 292 return RISCV::PseudoRVVInitUndefM1; 293 case RISCV::VRM2RegClassID: 294 return RISCV::PseudoRVVInitUndefM2; 295 case RISCV::VRM4RegClassID: 296 return RISCV::PseudoRVVInitUndefM4; 297 case RISCV::VRM8RegClassID: 298 return RISCV::PseudoRVVInitUndefM8; 299 default: 300 llvm_unreachable("Unexpected register class."); 301 } 302 } 303 304 protected: 305 const RISCVSubtarget &STI; 306 307 private: 308 unsigned getInstBundleLength(const MachineInstr &MI) const; 309 310 bool isVectorAssociativeAndCommutative(const MachineInstr &MI, 311 bool Invert = false) const; 312 bool areRVVInstsReassociable(const MachineInstr &MI1, 313 const MachineInstr &MI2) const; 314 bool hasReassociableVectorSibling(const MachineInstr &Inst, 315 bool &Commuted) const; 316 }; 317 318 namespace RISCV { 319 320 // Returns true if this is the sext.w pattern, addiw rd, rs1, 0. 321 bool isSEXT_W(const MachineInstr &MI); 322 bool isZEXT_W(const MachineInstr &MI); 323 bool isZEXT_B(const MachineInstr &MI); 324 325 // Returns true if the given MI is an RVV instruction opcode for which we may 326 // expect to see a FrameIndex operand. 327 bool isRVVSpill(const MachineInstr &MI); 328 329 std::optional<std::pair<unsigned, unsigned>> 330 isRVVSpillForZvlsseg(unsigned Opcode); 331 332 bool isFaultFirstLoad(const MachineInstr &MI); 333 334 // Implemented in RISCVGenInstrInfo.inc 335 int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); 336 337 // Return true if both input instructions have equal rounding mode. If at least 338 // one of the instructions does not have rounding mode, false will be returned. 339 bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2); 340 341 // If \p Opcode is a .vx vector instruction, returns the lower number of bits 342 // that are used from the scalar .x operand for a given \p Log2SEW. Otherwise 343 // returns null. 344 std::optional<unsigned> getVectorLowDemandedScalarBits(uint16_t Opcode, 345 unsigned Log2SEW); 346 347 // Returns the MC opcode of RVV pseudo instruction. 348 unsigned getRVVMCOpcode(unsigned RVVPseudoOpcode); 349 350 // Special immediate for AVL operand of V pseudo instructions to indicate VLMax. 351 static constexpr int64_t VLMaxSentinel = -1LL; 352 353 // Mask assignments for floating-point 354 static constexpr unsigned FPMASK_Negative_Infinity = 0x001; 355 static constexpr unsigned FPMASK_Negative_Normal = 0x002; 356 static constexpr unsigned FPMASK_Negative_Subnormal = 0x004; 357 static constexpr unsigned FPMASK_Negative_Zero = 0x008; 358 static constexpr unsigned FPMASK_Positive_Zero = 0x010; 359 static constexpr unsigned FPMASK_Positive_Subnormal = 0x020; 360 static constexpr unsigned FPMASK_Positive_Normal = 0x040; 361 static constexpr unsigned FPMASK_Positive_Infinity = 0x080; 362 static constexpr unsigned FPMASK_Signaling_NaN = 0x100; 363 static constexpr unsigned FPMASK_Quiet_NaN = 0x200; 364 } // namespace RISCV 365 366 namespace RISCVVPseudosTable { 367 368 struct PseudoInfo { 369 uint16_t Pseudo; 370 uint16_t BaseInstr; 371 }; 372 373 #define GET_RISCVVPseudosTable_DECL 374 #include "RISCVGenSearchableTables.inc" 375 376 } // end namespace RISCVVPseudosTable 377 378 namespace RISCV { 379 380 struct RISCVMaskedPseudoInfo { 381 uint16_t MaskedPseudo; 382 uint16_t UnmaskedPseudo; 383 uint8_t MaskOpIdx; 384 uint8_t ActiveElementsAffectResult : 1; 385 }; 386 #define GET_RISCVMaskedPseudosTable_DECL 387 #include "RISCVGenSearchableTables.inc" 388 } // end namespace RISCV 389 390 } // end namespace llvm 391 #endif 392