10b57cec5SDimitry Andric //===-- RISCVInstrInfo.h - RISCV Instruction Information --------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains the RISCV implementation of the TargetInstrInfo class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_RISCV_RISCVINSTRINFO_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "RISCVRegisterInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 18fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER 210eae32dcSDimitry Andric #define GET_INSTRINFO_OPERAND_ENUM 220b57cec5SDimitry Andric #include "RISCVGenInstrInfo.inc" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 268bcb0991SDimitry Andric class RISCVSubtarget; 278bcb0991SDimitry Andric 28349cc55cSDimitry Andric namespace RISCVCC { 29349cc55cSDimitry Andric 30349cc55cSDimitry Andric enum CondCode { 31349cc55cSDimitry Andric COND_EQ, 32349cc55cSDimitry Andric COND_NE, 33349cc55cSDimitry Andric COND_LT, 34349cc55cSDimitry Andric COND_GE, 35349cc55cSDimitry Andric COND_LTU, 36349cc55cSDimitry Andric COND_GEU, 37349cc55cSDimitry Andric COND_INVALID 38349cc55cSDimitry Andric }; 39349cc55cSDimitry Andric 40349cc55cSDimitry Andric CondCode getOppositeBranchCondition(CondCode); 41349cc55cSDimitry Andric 42349cc55cSDimitry Andric } // end of namespace RISCVCC 43349cc55cSDimitry Andric 440b57cec5SDimitry Andric class RISCVInstrInfo : public RISCVGenInstrInfo { 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric public: 478bcb0991SDimitry Andric explicit RISCVInstrInfo(RISCVSubtarget &STI); 480b57cec5SDimitry Andric 49fe6060f1SDimitry Andric MCInst getNop() const override; 50349cc55cSDimitry Andric const MCInstrDesc &getBrCond(RISCVCC::CondCode CC) const; 51fe6060f1SDimitry Andric 520b57cec5SDimitry Andric unsigned isLoadFromStackSlot(const MachineInstr &MI, 530b57cec5SDimitry Andric int &FrameIndex) const override; 540b57cec5SDimitry Andric unsigned isStoreToStackSlot(const MachineInstr &MI, 550b57cec5SDimitry Andric int &FrameIndex) const override; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 58480093f4SDimitry Andric const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, 590b57cec5SDimitry Andric bool KillSrc) const override; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric void storeRegToStackSlot(MachineBasicBlock &MBB, 625ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, Register SrcReg, 630b57cec5SDimitry Andric bool IsKill, int FrameIndex, 640b57cec5SDimitry Andric const TargetRegisterClass *RC, 65*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 66*bdd1243dSDimitry Andric Register VReg) const override; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric void loadRegFromStackSlot(MachineBasicBlock &MBB, 695ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI, Register DstReg, 700b57cec5SDimitry Andric int FrameIndex, const TargetRegisterClass *RC, 71*bdd1243dSDimitry Andric const TargetRegisterInfo *TRI, 72*bdd1243dSDimitry Andric Register VReg) const override; 730b57cec5SDimitry Andric 74fcaf7f86SDimitry Andric using TargetInstrInfo::foldMemoryOperandImpl; 75fcaf7f86SDimitry Andric MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 76fcaf7f86SDimitry Andric ArrayRef<unsigned> Ops, 77fcaf7f86SDimitry Andric MachineBasicBlock::iterator InsertPt, 78fcaf7f86SDimitry Andric int FrameIndex, 79fcaf7f86SDimitry Andric LiveIntervals *LIS = nullptr, 80fcaf7f86SDimitry Andric VirtRegMap *VRM = nullptr) const override; 81fcaf7f86SDimitry Andric 828bcb0991SDimitry Andric // Materializes the given integer Val into DstReg. 838bcb0991SDimitry Andric void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 848bcb0991SDimitry Andric const DebugLoc &DL, Register DstReg, uint64_t Val, 850b57cec5SDimitry Andric MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 900b57cec5SDimitry Andric MachineBasicBlock *&FBB, 910b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 920b57cec5SDimitry Andric bool AllowModify) const override; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 950b57cec5SDimitry Andric MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 960b57cec5SDimitry Andric const DebugLoc &dl, 970b57cec5SDimitry Andric int *BytesAdded = nullptr) const override; 980b57cec5SDimitry Andric 99349cc55cSDimitry Andric void insertIndirectBranch(MachineBasicBlock &MBB, 1000b57cec5SDimitry Andric MachineBasicBlock &NewDestBB, 101349cc55cSDimitry Andric MachineBasicBlock &RestoreBB, const DebugLoc &DL, 102349cc55cSDimitry Andric int64_t BrOffset, RegScavenger *RS) const override; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric unsigned removeBranch(MachineBasicBlock &MBB, 1050b57cec5SDimitry Andric int *BytesRemoved = nullptr) const override; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric bool 1080b57cec5SDimitry Andric reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric bool isBranchOffsetInRange(unsigned BranchOpc, 1130b57cec5SDimitry Andric int64_t BrOffset) const override; 1140b57cec5SDimitry Andric 115*bdd1243dSDimitry Andric bool analyzeSelect(const MachineInstr &MI, 116*bdd1243dSDimitry Andric SmallVectorImpl<MachineOperand> &Cond, unsigned &TrueOp, 117*bdd1243dSDimitry Andric unsigned &FalseOp, bool &Optimizable) const override; 118*bdd1243dSDimitry Andric 119*bdd1243dSDimitry Andric MachineInstr *optimizeSelect(MachineInstr &MI, 120*bdd1243dSDimitry Andric SmallPtrSetImpl<MachineInstr *> &SeenMIs, 121*bdd1243dSDimitry Andric bool) const override; 122*bdd1243dSDimitry Andric 1230b57cec5SDimitry Andric bool isAsCheapAsAMove(const MachineInstr &MI) const override; 1248bcb0991SDimitry Andric 125*bdd1243dSDimitry Andric std::optional<DestSourcePair> 126e8d8bef9SDimitry Andric isCopyInstrImpl(const MachineInstr &MI) const override; 127e8d8bef9SDimitry Andric 1288bcb0991SDimitry Andric bool verifyInstruction(const MachineInstr &MI, 1298bcb0991SDimitry Andric StringRef &ErrInfo) const override; 1308bcb0991SDimitry Andric 131480093f4SDimitry Andric bool getMemOperandWithOffsetWidth(const MachineInstr &LdSt, 132480093f4SDimitry Andric const MachineOperand *&BaseOp, 133480093f4SDimitry Andric int64_t &Offset, unsigned &Width, 134480093f4SDimitry Andric const TargetRegisterInfo *TRI) const; 135480093f4SDimitry Andric 136480093f4SDimitry Andric bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 137480093f4SDimitry Andric const MachineInstr &MIb) const override; 138480093f4SDimitry Andric 139480093f4SDimitry Andric 140480093f4SDimitry Andric std::pair<unsigned, unsigned> 141480093f4SDimitry Andric decomposeMachineOperandsTargetFlags(unsigned TF) const override; 142480093f4SDimitry Andric 143480093f4SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 144480093f4SDimitry Andric getSerializableDirectMachineOperandTargetFlags() const override; 145480093f4SDimitry Andric 146480093f4SDimitry Andric // Return true if the function can safely be outlined from. 147972a253aSDimitry Andric bool isFunctionSafeToOutlineFrom(MachineFunction &MF, 148480093f4SDimitry Andric bool OutlineFromLinkOnceODRs) const override; 149480093f4SDimitry Andric 150480093f4SDimitry Andric // Return true if MBB is safe to outline from, and return any target-specific 151480093f4SDimitry Andric // information in Flags. 152972a253aSDimitry Andric bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, 153480093f4SDimitry Andric unsigned &Flags) const override; 154480093f4SDimitry Andric 15581ad6265SDimitry Andric bool shouldOutlineFromFunctionByDefault(MachineFunction &MF) const override; 15681ad6265SDimitry Andric 157480093f4SDimitry Andric // Calculate target-specific information for a set of outlining candidates. 158480093f4SDimitry Andric outliner::OutlinedFunction getOutliningCandidateInfo( 159480093f4SDimitry Andric std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override; 160480093f4SDimitry Andric 161480093f4SDimitry Andric // Return if/how a given MachineInstr should be outlined. 162972a253aSDimitry Andric outliner::InstrType getOutliningType(MachineBasicBlock::iterator &MBBI, 163480093f4SDimitry Andric unsigned Flags) const override; 164480093f4SDimitry Andric 165480093f4SDimitry Andric // Insert a custom frame for outlined functions. 166972a253aSDimitry Andric void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF, 167480093f4SDimitry Andric const outliner::OutlinedFunction &OF) const override; 168480093f4SDimitry Andric 169480093f4SDimitry Andric // Insert a call to an outlined function into a given basic block. 170972a253aSDimitry Andric MachineBasicBlock::iterator 171480093f4SDimitry Andric insertOutlinedCall(Module &M, MachineBasicBlock &MBB, 172480093f4SDimitry Andric MachineBasicBlock::iterator &It, MachineFunction &MF, 17381ad6265SDimitry Andric outliner::Candidate &C) const override; 174fe6060f1SDimitry Andric 175fe6060f1SDimitry Andric bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 176fe6060f1SDimitry Andric unsigned &SrcOpIdx2) const override; 177fe6060f1SDimitry Andric MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 178fe6060f1SDimitry Andric unsigned OpIdx1, 179fe6060f1SDimitry Andric unsigned OpIdx2) const override; 180fe6060f1SDimitry Andric 181349cc55cSDimitry Andric MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, 182349cc55cSDimitry Andric LiveIntervals *LIS) const override; 183fe6060f1SDimitry Andric 18481ad6265SDimitry Andric // MIR printer helper function to annotate Operands with a comment. 18581ad6265SDimitry Andric std::string 18681ad6265SDimitry Andric createMIROperandComment(const MachineInstr &MI, const MachineOperand &Op, 18781ad6265SDimitry Andric unsigned OpIdx, 18881ad6265SDimitry Andric const TargetRegisterInfo *TRI) const override; 18981ad6265SDimitry Andric 190*bdd1243dSDimitry Andric void getVLENFactoredAmount( 191fe6060f1SDimitry Andric MachineFunction &MF, MachineBasicBlock &MBB, 192*bdd1243dSDimitry Andric MachineBasicBlock::iterator II, const DebugLoc &DL, Register DestReg, 193*bdd1243dSDimitry Andric int64_t Amount, MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; 194*bdd1243dSDimitry Andric 195*bdd1243dSDimitry Andric bool useMachineCombiner() const override { return true; } 196*bdd1243dSDimitry Andric 197*bdd1243dSDimitry Andric void setSpecialOperandAttr(MachineInstr &OldMI1, MachineInstr &OldMI2, 198*bdd1243dSDimitry Andric MachineInstr &NewMI1, 199*bdd1243dSDimitry Andric MachineInstr &NewMI2) const override; 200*bdd1243dSDimitry Andric bool 201*bdd1243dSDimitry Andric getMachineCombinerPatterns(MachineInstr &Root, 202*bdd1243dSDimitry Andric SmallVectorImpl<MachineCombinerPattern> &Patterns, 203*bdd1243dSDimitry Andric bool DoRegPressureReduce) const override; 204*bdd1243dSDimitry Andric 205*bdd1243dSDimitry Andric void 206*bdd1243dSDimitry Andric finalizeInsInstrs(MachineInstr &Root, MachineCombinerPattern &P, 207*bdd1243dSDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs) const override; 208*bdd1243dSDimitry Andric 209*bdd1243dSDimitry Andric void genAlternativeCodeSequence( 210*bdd1243dSDimitry Andric MachineInstr &Root, MachineCombinerPattern Pattern, 211*bdd1243dSDimitry Andric SmallVectorImpl<MachineInstr *> &InsInstrs, 212*bdd1243dSDimitry Andric SmallVectorImpl<MachineInstr *> &DelInstrs, 213*bdd1243dSDimitry Andric DenseMap<unsigned, unsigned> &InstrIdxForVirtReg) const override; 214*bdd1243dSDimitry Andric 215*bdd1243dSDimitry Andric bool hasReassociableSibling(const MachineInstr &Inst, 216*bdd1243dSDimitry Andric bool &Commuted) const override; 217*bdd1243dSDimitry Andric 218*bdd1243dSDimitry Andric bool isAssociativeAndCommutative(const MachineInstr &Inst, 219*bdd1243dSDimitry Andric bool Invert) const override; 220*bdd1243dSDimitry Andric 221*bdd1243dSDimitry Andric std::optional<unsigned> getInverseOpcode(unsigned Opcode) const override; 222*bdd1243dSDimitry Andric 223*bdd1243dSDimitry Andric // Returns true if all uses of OrigMI only depend on the lower \p NBits bits 224*bdd1243dSDimitry Andric // of its output. 225*bdd1243dSDimitry Andric bool hasAllNBitUsers(const MachineInstr &MI, const MachineRegisterInfo &MRI, 226*bdd1243dSDimitry Andric unsigned NBits) const; 227*bdd1243dSDimitry Andric // Returns true if all uses of OrigMI only depend on the lower word of its 228*bdd1243dSDimitry Andric // output, so we can transform OrigMI to the corresponding W-version. 229*bdd1243dSDimitry Andric bool hasAllWUsers(const MachineInstr &MI, 230*bdd1243dSDimitry Andric const MachineRegisterInfo &MRI) const { 231*bdd1243dSDimitry Andric return hasAllNBitUsers(MI, MRI, 32); 232*bdd1243dSDimitry Andric } 233fe6060f1SDimitry Andric 2348bcb0991SDimitry Andric protected: 2358bcb0991SDimitry Andric const RISCVSubtarget &STI; 2360b57cec5SDimitry Andric }; 2375ffd83dbSDimitry Andric 238349cc55cSDimitry Andric namespace RISCV { 2390eae32dcSDimitry Andric 240fcaf7f86SDimitry Andric // Returns true if this is the sext.w pattern, addiw rd, rs1, 0. 241fcaf7f86SDimitry Andric bool isSEXT_W(const MachineInstr &MI); 242fcaf7f86SDimitry Andric bool isZEXT_W(const MachineInstr &MI); 243fcaf7f86SDimitry Andric bool isZEXT_B(const MachineInstr &MI); 244fcaf7f86SDimitry Andric 24581ad6265SDimitry Andric // Returns true if the given MI is an RVV instruction opcode for which we may 24681ad6265SDimitry Andric // expect to see a FrameIndex operand. 24781ad6265SDimitry Andric bool isRVVSpill(const MachineInstr &MI); 24881ad6265SDimitry Andric 249*bdd1243dSDimitry Andric std::optional<std::pair<unsigned, unsigned>> 250*bdd1243dSDimitry Andric isRVVSpillForZvlsseg(unsigned Opcode); 25181ad6265SDimitry Andric 25281ad6265SDimitry Andric bool isFaultFirstLoad(const MachineInstr &MI); 25381ad6265SDimitry Andric 2540eae32dcSDimitry Andric // Implemented in RISCVGenInstrInfo.inc 2550eae32dcSDimitry Andric int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIndex); 2560eae32dcSDimitry Andric 257*bdd1243dSDimitry Andric // Return true if both input instructions have equal rounding mode. If at least 258*bdd1243dSDimitry Andric // one of the instructions does not have rounding mode, false will be returned. 259*bdd1243dSDimitry Andric bool hasEqualFRM(const MachineInstr &MI1, const MachineInstr &MI2); 260*bdd1243dSDimitry Andric 261349cc55cSDimitry Andric // Special immediate for AVL operand of V pseudo instructions to indicate VLMax. 262349cc55cSDimitry Andric static constexpr int64_t VLMaxSentinel = -1LL; 263*bdd1243dSDimitry Andric 264349cc55cSDimitry Andric } // namespace RISCV 265349cc55cSDimitry Andric 266fe6060f1SDimitry Andric namespace RISCVVPseudosTable { 267fe6060f1SDimitry Andric 268fe6060f1SDimitry Andric struct PseudoInfo { 269fe6060f1SDimitry Andric uint16_t Pseudo; 270fe6060f1SDimitry Andric uint16_t BaseInstr; 271fe6060f1SDimitry Andric }; 272fe6060f1SDimitry Andric 273fe6060f1SDimitry Andric #define GET_RISCVVPseudosTable_DECL 274fe6060f1SDimitry Andric #include "RISCVGenSearchableTables.inc" 275fe6060f1SDimitry Andric 276fe6060f1SDimitry Andric } // end namespace RISCVVPseudosTable 277fe6060f1SDimitry Andric 2785ffd83dbSDimitry Andric } // end namespace llvm 2790b57cec5SDimitry Andric #endif 280