10b57cec5SDimitry Andric //===- SIInstrInfo.h - SI Instruction Info Interface ------------*- 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 /// \file 100b57cec5SDimitry Andric /// Interface definition for SIInstrInfo. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H 150b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H 160b57cec5SDimitry Andric 17e8d8bef9SDimitry Andric #include "AMDGPUMIRFormatter.h" 180b57cec5SDimitry Andric #include "SIRegisterInfo.h" 190b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h" 21e8d8bef9SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 22480093f4SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #define GET_INSTRINFO_HEADER 250b57cec5SDimitry Andric #include "AMDGPUGenInstrInfo.inc" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric namespace llvm { 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric class APInt; 30e8d8bef9SDimitry Andric class GCNSubtarget; 31e8d8bef9SDimitry Andric class LiveVariables; 320b57cec5SDimitry Andric class MachineDominatorTree; 330b57cec5SDimitry Andric class MachineRegisterInfo; 340b57cec5SDimitry Andric class RegScavenger; 350b57cec5SDimitry Andric class TargetRegisterClass; 36e8d8bef9SDimitry Andric class ScheduleHazardRecognizer; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric class SIInstrInfo final : public AMDGPUGenInstrInfo { 390b57cec5SDimitry Andric private: 400b57cec5SDimitry Andric const SIRegisterInfo RI; 410b57cec5SDimitry Andric const GCNSubtarget &ST; 42480093f4SDimitry Andric TargetSchedModel SchedModel; 43e8d8bef9SDimitry Andric mutable std::unique_ptr<AMDGPUMIRFormatter> Formatter; 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // The inverse predicate should have the negative value. 460b57cec5SDimitry Andric enum BranchPredicate { 470b57cec5SDimitry Andric INVALID_BR = 0, 480b57cec5SDimitry Andric SCC_TRUE = 1, 490b57cec5SDimitry Andric SCC_FALSE = -1, 500b57cec5SDimitry Andric VCCNZ = 2, 510b57cec5SDimitry Andric VCCZ = -2, 520b57cec5SDimitry Andric EXECNZ = -3, 530b57cec5SDimitry Andric EXECZ = 3 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric using SetVectorType = SmallSetVector<MachineInstr *, 32>; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric static unsigned getBranchOpcode(BranchPredicate Cond); 590b57cec5SDimitry Andric static BranchPredicate getBranchPredicate(unsigned Opcode); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric public: 620b57cec5SDimitry Andric unsigned buildExtractSubReg(MachineBasicBlock::iterator MI, 630b57cec5SDimitry Andric MachineRegisterInfo &MRI, 640b57cec5SDimitry Andric MachineOperand &SuperReg, 650b57cec5SDimitry Andric const TargetRegisterClass *SuperRC, 660b57cec5SDimitry Andric unsigned SubIdx, 670b57cec5SDimitry Andric const TargetRegisterClass *SubRC) const; 680b57cec5SDimitry Andric MachineOperand buildExtractSubRegOrImm(MachineBasicBlock::iterator MI, 690b57cec5SDimitry Andric MachineRegisterInfo &MRI, 700b57cec5SDimitry Andric MachineOperand &SuperReg, 710b57cec5SDimitry Andric const TargetRegisterClass *SuperRC, 720b57cec5SDimitry Andric unsigned SubIdx, 730b57cec5SDimitry Andric const TargetRegisterClass *SubRC) const; 740b57cec5SDimitry Andric private: 750b57cec5SDimitry Andric void swapOperands(MachineInstr &Inst) const; 760b57cec5SDimitry Andric 77e8d8bef9SDimitry Andric std::pair<bool, MachineBasicBlock *> 78e8d8bef9SDimitry Andric moveScalarAddSub(SetVectorType &Worklist, MachineInstr &Inst, 790b57cec5SDimitry Andric MachineDominatorTree *MDT = nullptr) const; 800b57cec5SDimitry Andric 81*349cc55cSDimitry Andric void lowerSelect32(SetVectorType &Worklist, MachineInstr &Inst, 82*349cc55cSDimitry Andric MachineDominatorTree *MDT = nullptr) const; 83*349cc55cSDimitry Andric 84*349cc55cSDimitry Andric void splitSelect64(SetVectorType &Worklist, MachineInstr &Inst, 855ffd83dbSDimitry Andric MachineDominatorTree *MDT = nullptr) const; 865ffd83dbSDimitry Andric 870b57cec5SDimitry Andric void lowerScalarAbs(SetVectorType &Worklist, 880b57cec5SDimitry Andric MachineInstr &Inst) const; 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric void lowerScalarXnor(SetVectorType &Worklist, 910b57cec5SDimitry Andric MachineInstr &Inst) const; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric void splitScalarNotBinop(SetVectorType &Worklist, 940b57cec5SDimitry Andric MachineInstr &Inst, 950b57cec5SDimitry Andric unsigned Opcode) const; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric void splitScalarBinOpN2(SetVectorType &Worklist, 980b57cec5SDimitry Andric MachineInstr &Inst, 990b57cec5SDimitry Andric unsigned Opcode) const; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void splitScalar64BitUnaryOp(SetVectorType &Worklist, 102fe6060f1SDimitry Andric MachineInstr &Inst, unsigned Opcode, 103fe6060f1SDimitry Andric bool Swap = false) const; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void splitScalar64BitAddSub(SetVectorType &Worklist, MachineInstr &Inst, 1060b57cec5SDimitry Andric MachineDominatorTree *MDT = nullptr) const; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric void splitScalar64BitBinaryOp(SetVectorType &Worklist, MachineInstr &Inst, 1090b57cec5SDimitry Andric unsigned Opcode, 1100b57cec5SDimitry Andric MachineDominatorTree *MDT = nullptr) const; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric void splitScalar64BitXnor(SetVectorType &Worklist, MachineInstr &Inst, 1130b57cec5SDimitry Andric MachineDominatorTree *MDT = nullptr) const; 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric void splitScalar64BitBCNT(SetVectorType &Worklist, 1160b57cec5SDimitry Andric MachineInstr &Inst) const; 1170b57cec5SDimitry Andric void splitScalar64BitBFE(SetVectorType &Worklist, 1180b57cec5SDimitry Andric MachineInstr &Inst) const; 1190b57cec5SDimitry Andric void movePackToVALU(SetVectorType &Worklist, 1200b57cec5SDimitry Andric MachineRegisterInfo &MRI, 1210b57cec5SDimitry Andric MachineInstr &Inst) const; 1220b57cec5SDimitry Andric 1235ffd83dbSDimitry Andric void addUsersToMoveToVALUWorklist(Register Reg, MachineRegisterInfo &MRI, 1240b57cec5SDimitry Andric SetVectorType &Worklist) const; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric void addSCCDefUsersToVALUWorklist(MachineOperand &Op, 1270b57cec5SDimitry Andric MachineInstr &SCCDefInst, 128*349cc55cSDimitry Andric SetVectorType &Worklist, 129*349cc55cSDimitry Andric Register NewCond = Register()) const; 130fe6060f1SDimitry Andric void addSCCDefsToVALUWorklist(MachineOperand &Op, 131fe6060f1SDimitry Andric SetVectorType &Worklist) const; 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric const TargetRegisterClass * 1340b57cec5SDimitry Andric getDestEquivalentVGPRClass(const MachineInstr &Inst) const; 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric bool checkInstOffsetsDoNotOverlap(const MachineInstr &MIa, 1370b57cec5SDimitry Andric const MachineInstr &MIb) const; 1380b57cec5SDimitry Andric 1395ffd83dbSDimitry Andric Register findUsedSGPR(const MachineInstr &MI, int OpIndices[3]) const; 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric protected: 1420b57cec5SDimitry Andric bool swapSourceModifiers(MachineInstr &MI, 1430b57cec5SDimitry Andric MachineOperand &Src0, unsigned Src0OpName, 1440b57cec5SDimitry Andric MachineOperand &Src1, unsigned Src1OpName) const; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric MachineInstr *commuteInstructionImpl(MachineInstr &MI, bool NewMI, 1470b57cec5SDimitry Andric unsigned OpIdx0, 1480b57cec5SDimitry Andric unsigned OpIdx1) const override; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric public: 1510b57cec5SDimitry Andric enum TargetOperandFlags { 1520b57cec5SDimitry Andric MO_MASK = 0xf, 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric MO_NONE = 0, 1550b57cec5SDimitry Andric // MO_GOTPCREL -> symbol@GOTPCREL -> R_AMDGPU_GOTPCREL. 1560b57cec5SDimitry Andric MO_GOTPCREL = 1, 1570b57cec5SDimitry Andric // MO_GOTPCREL32_LO -> symbol@gotpcrel32@lo -> R_AMDGPU_GOTPCREL32_LO. 1580b57cec5SDimitry Andric MO_GOTPCREL32 = 2, 1590b57cec5SDimitry Andric MO_GOTPCREL32_LO = 2, 1600b57cec5SDimitry Andric // MO_GOTPCREL32_HI -> symbol@gotpcrel32@hi -> R_AMDGPU_GOTPCREL32_HI. 1610b57cec5SDimitry Andric MO_GOTPCREL32_HI = 3, 1620b57cec5SDimitry Andric // MO_REL32_LO -> symbol@rel32@lo -> R_AMDGPU_REL32_LO. 1630b57cec5SDimitry Andric MO_REL32 = 4, 1640b57cec5SDimitry Andric MO_REL32_LO = 4, 1650b57cec5SDimitry Andric // MO_REL32_HI -> symbol@rel32@hi -> R_AMDGPU_REL32_HI. 1660b57cec5SDimitry Andric MO_REL32_HI = 5, 1670b57cec5SDimitry Andric 168fe6060f1SDimitry Andric MO_FAR_BRANCH_OFFSET = 6, 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric MO_ABS32_LO = 8, 1710b57cec5SDimitry Andric MO_ABS32_HI = 9, 1720b57cec5SDimitry Andric }; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric explicit SIInstrInfo(const GCNSubtarget &ST); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric const SIRegisterInfo &getRegisterInfo() const { 1770b57cec5SDimitry Andric return RI; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 180fe6060f1SDimitry Andric const GCNSubtarget &getSubtarget() const { 181fe6060f1SDimitry Andric return ST; 182fe6060f1SDimitry Andric } 183fe6060f1SDimitry Andric 1840b57cec5SDimitry Andric bool isReallyTriviallyReMaterializable(const MachineInstr &MI, 1858bcb0991SDimitry Andric AAResults *AA) const override; 1860b57cec5SDimitry Andric 187fe6060f1SDimitry Andric bool isIgnorableUse(const MachineOperand &MO) const override; 188fe6060f1SDimitry Andric 1890b57cec5SDimitry Andric bool areLoadsFromSameBasePtr(SDNode *Load1, SDNode *Load2, 1900b57cec5SDimitry Andric int64_t &Offset1, 1910b57cec5SDimitry Andric int64_t &Offset2) const override; 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric bool getMemOperandsWithOffsetWidth( 1945ffd83dbSDimitry Andric const MachineInstr &LdSt, 1955ffd83dbSDimitry Andric SmallVectorImpl<const MachineOperand *> &BaseOps, int64_t &Offset, 1965ffd83dbSDimitry Andric bool &OffsetIsScalable, unsigned &Width, 1970b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const final; 1980b57cec5SDimitry Andric 1995ffd83dbSDimitry Andric bool shouldClusterMemOps(ArrayRef<const MachineOperand *> BaseOps1, 2005ffd83dbSDimitry Andric ArrayRef<const MachineOperand *> BaseOps2, 2015ffd83dbSDimitry Andric unsigned NumLoads, unsigned NumBytes) const override; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric bool shouldScheduleLoadsNear(SDNode *Load0, SDNode *Load1, int64_t Offset0, 2040b57cec5SDimitry Andric int64_t Offset1, unsigned NumLoads) const override; 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 207480093f4SDimitry Andric const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, 2080b57cec5SDimitry Andric bool KillSrc) const override; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric void materializeImmediate(MachineBasicBlock &MBB, 2110b57cec5SDimitry Andric MachineBasicBlock::iterator MI, 2120b57cec5SDimitry Andric const DebugLoc &DL, 2130b57cec5SDimitry Andric unsigned DestReg, 2140b57cec5SDimitry Andric int64_t Value) const; 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric const TargetRegisterClass *getPreferredSelectRegClass( 2170b57cec5SDimitry Andric unsigned Size) const; 2180b57cec5SDimitry Andric 2195ffd83dbSDimitry Andric Register insertNE(MachineBasicBlock *MBB, 2200b57cec5SDimitry Andric MachineBasicBlock::iterator I, const DebugLoc &DL, 2215ffd83dbSDimitry Andric Register SrcReg, int Value) const; 2220b57cec5SDimitry Andric 2235ffd83dbSDimitry Andric Register insertEQ(MachineBasicBlock *MBB, 2240b57cec5SDimitry Andric MachineBasicBlock::iterator I, const DebugLoc &DL, 2255ffd83dbSDimitry Andric Register SrcReg, int Value) const; 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric void storeRegToStackSlot(MachineBasicBlock &MBB, 2285ffd83dbSDimitry Andric MachineBasicBlock::iterator MI, Register SrcReg, 2290b57cec5SDimitry Andric bool isKill, int FrameIndex, 2300b57cec5SDimitry Andric const TargetRegisterClass *RC, 2310b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric void loadRegFromStackSlot(MachineBasicBlock &MBB, 2345ffd83dbSDimitry Andric MachineBasicBlock::iterator MI, Register DestReg, 2350b57cec5SDimitry Andric int FrameIndex, const TargetRegisterClass *RC, 2360b57cec5SDimitry Andric const TargetRegisterInfo *TRI) const override; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric bool expandPostRAPseudo(MachineInstr &MI) const override; 2390b57cec5SDimitry Andric 2408bcb0991SDimitry Andric // Splits a V_MOV_B64_DPP_PSEUDO opcode into a pair of v_mov_b32_dpp 2418bcb0991SDimitry Andric // instructions. Returns a pair of generated instructions. 2428bcb0991SDimitry Andric // Can split either post-RA with physical registers or pre-RA with 2438bcb0991SDimitry Andric // virtual registers. In latter case IR needs to be in SSA form and 2448bcb0991SDimitry Andric // and a REG_SEQUENCE is produced to define original register. 2458bcb0991SDimitry Andric std::pair<MachineInstr*, MachineInstr*> 2468bcb0991SDimitry Andric expandMovDPP64(MachineInstr &MI) const; 2478bcb0991SDimitry Andric 2480b57cec5SDimitry Andric // Returns an opcode that can be used to move a value to a \p DstRC 2490b57cec5SDimitry Andric // register. If there is no hardware instruction that can store to \p 2500b57cec5SDimitry Andric // DstRC, then AMDGPU::COPY is returned. 2510b57cec5SDimitry Andric unsigned getMovOpcode(const TargetRegisterClass *DstRC) const; 2520b57cec5SDimitry Andric 253e8d8bef9SDimitry Andric const MCInstrDesc &getIndirectRegWriteMovRelPseudo(unsigned VecSize, 254e8d8bef9SDimitry Andric unsigned EltSize, 255e8d8bef9SDimitry Andric bool IsSGPR) const; 2565ffd83dbSDimitry Andric 257e8d8bef9SDimitry Andric const MCInstrDesc &getIndirectGPRIDXPseudo(unsigned VecSize, 258e8d8bef9SDimitry Andric bool IsIndirectSrc) const; 2590b57cec5SDimitry Andric LLVM_READONLY 2600b57cec5SDimitry Andric int commuteOpcode(unsigned Opc) const; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric LLVM_READONLY 2630b57cec5SDimitry Andric inline int commuteOpcode(const MachineInstr &MI) const { 2640b57cec5SDimitry Andric return commuteOpcode(MI.getOpcode()); 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2678bcb0991SDimitry Andric bool findCommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1, 2680b57cec5SDimitry Andric unsigned &SrcOpIdx2) const override; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric bool findCommutedOpIndices(MCInstrDesc Desc, unsigned & SrcOpIdx0, 2710b57cec5SDimitry Andric unsigned & SrcOpIdx1) const; 2720b57cec5SDimitry Andric 2730b57cec5SDimitry Andric bool isBranchOffsetInRange(unsigned BranchOpc, 2740b57cec5SDimitry Andric int64_t BrOffset) const override; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; 2770b57cec5SDimitry Andric 278*349cc55cSDimitry Andric void insertIndirectBranch(MachineBasicBlock &MBB, 2790b57cec5SDimitry Andric MachineBasicBlock &NewDestBB, 280*349cc55cSDimitry Andric MachineBasicBlock &RestoreBB, const DebugLoc &DL, 281*349cc55cSDimitry Andric int64_t BrOffset, RegScavenger *RS) const override; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric bool analyzeBranchImpl(MachineBasicBlock &MBB, 2840b57cec5SDimitry Andric MachineBasicBlock::iterator I, 2850b57cec5SDimitry Andric MachineBasicBlock *&TBB, 2860b57cec5SDimitry Andric MachineBasicBlock *&FBB, 2870b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 2880b57cec5SDimitry Andric bool AllowModify) const; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 2910b57cec5SDimitry Andric MachineBasicBlock *&FBB, 2920b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond, 2930b57cec5SDimitry Andric bool AllowModify = false) const override; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric unsigned removeBranch(MachineBasicBlock &MBB, 2960b57cec5SDimitry Andric int *BytesRemoved = nullptr) const override; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 2990b57cec5SDimitry Andric MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, 3000b57cec5SDimitry Andric const DebugLoc &DL, 3010b57cec5SDimitry Andric int *BytesAdded = nullptr) const override; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric bool reverseBranchCondition( 3040b57cec5SDimitry Andric SmallVectorImpl<MachineOperand> &Cond) const override; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric bool canInsertSelect(const MachineBasicBlock &MBB, 3075ffd83dbSDimitry Andric ArrayRef<MachineOperand> Cond, Register DstReg, 3085ffd83dbSDimitry Andric Register TrueReg, Register FalseReg, int &CondCycles, 3090b57cec5SDimitry Andric int &TrueCycles, int &FalseCycles) const override; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric void insertSelect(MachineBasicBlock &MBB, 3120b57cec5SDimitry Andric MachineBasicBlock::iterator I, const DebugLoc &DL, 3135ffd83dbSDimitry Andric Register DstReg, ArrayRef<MachineOperand> Cond, 3145ffd83dbSDimitry Andric Register TrueReg, Register FalseReg) const override; 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric void insertVectorSelect(MachineBasicBlock &MBB, 3170b57cec5SDimitry Andric MachineBasicBlock::iterator I, const DebugLoc &DL, 3185ffd83dbSDimitry Andric Register DstReg, ArrayRef<MachineOperand> Cond, 3195ffd83dbSDimitry Andric Register TrueReg, Register FalseReg) const; 3200b57cec5SDimitry Andric 321*349cc55cSDimitry Andric bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, 322*349cc55cSDimitry Andric Register &SrcReg2, int64_t &CmpMask, 323*349cc55cSDimitry Andric int64_t &CmpValue) const override; 324*349cc55cSDimitry Andric 325*349cc55cSDimitry Andric bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, 326*349cc55cSDimitry Andric Register SrcReg2, int64_t CmpMask, int64_t CmpValue, 327*349cc55cSDimitry Andric const MachineRegisterInfo *MRI) const override; 328*349cc55cSDimitry Andric 3290b57cec5SDimitry Andric unsigned getAddressSpaceForPseudoSourceKind( 3300b57cec5SDimitry Andric unsigned Kind) const override; 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric bool 3330b57cec5SDimitry Andric areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, 3348bcb0991SDimitry Andric const MachineInstr &MIb) const override; 3350b57cec5SDimitry Andric 336*349cc55cSDimitry Andric static bool isFoldableCopy(const MachineInstr &MI); 3370b57cec5SDimitry Andric 3385ffd83dbSDimitry Andric bool FoldImmediate(MachineInstr &UseMI, MachineInstr &DefMI, Register Reg, 3390b57cec5SDimitry Andric MachineRegisterInfo *MRI) const final; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric unsigned getMachineCSELookAheadLimit() const override { return 500; } 3420b57cec5SDimitry Andric 343*349cc55cSDimitry Andric MachineInstr *convertToThreeAddress(MachineInstr &MI, LiveVariables *LV, 344*349cc55cSDimitry Andric LiveIntervals *LIS) const override; 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric bool isSchedulingBoundary(const MachineInstr &MI, 3470b57cec5SDimitry Andric const MachineBasicBlock *MBB, 3480b57cec5SDimitry Andric const MachineFunction &MF) const override; 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric static bool isSALU(const MachineInstr &MI) { 3510b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SALU; 3520b57cec5SDimitry Andric } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric bool isSALU(uint16_t Opcode) const { 3550b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SALU; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric 3580b57cec5SDimitry Andric static bool isVALU(const MachineInstr &MI) { 3590b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VALU; 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric bool isVALU(uint16_t Opcode) const { 3630b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VALU; 3640b57cec5SDimitry Andric } 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric static bool isVMEM(const MachineInstr &MI) { 3670b57cec5SDimitry Andric return isMUBUF(MI) || isMTBUF(MI) || isMIMG(MI); 3680b57cec5SDimitry Andric } 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric bool isVMEM(uint16_t Opcode) const { 3710b57cec5SDimitry Andric return isMUBUF(Opcode) || isMTBUF(Opcode) || isMIMG(Opcode); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric static bool isSOP1(const MachineInstr &MI) { 3750b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOP1; 3760b57cec5SDimitry Andric } 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric bool isSOP1(uint16_t Opcode) const { 3790b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOP1; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric static bool isSOP2(const MachineInstr &MI) { 3830b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOP2; 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric bool isSOP2(uint16_t Opcode) const { 3870b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOP2; 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric static bool isSOPC(const MachineInstr &MI) { 3910b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOPC; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric bool isSOPC(uint16_t Opcode) const { 3950b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOPC; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric static bool isSOPK(const MachineInstr &MI) { 3990b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOPK; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric bool isSOPK(uint16_t Opcode) const { 4030b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOPK; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric static bool isSOPP(const MachineInstr &MI) { 4070b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOPP; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric bool isSOPP(uint16_t Opcode) const { 4110b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOPP; 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric static bool isPacked(const MachineInstr &MI) { 4150b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IsPacked; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric bool isPacked(uint16_t Opcode) const { 4190b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::IsPacked; 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric static bool isVOP1(const MachineInstr &MI) { 4230b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VOP1; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric bool isVOP1(uint16_t Opcode) const { 4270b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VOP1; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric static bool isVOP2(const MachineInstr &MI) { 4310b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VOP2; 4320b57cec5SDimitry Andric } 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric bool isVOP2(uint16_t Opcode) const { 4350b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VOP2; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric static bool isVOP3(const MachineInstr &MI) { 4390b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VOP3; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric bool isVOP3(uint16_t Opcode) const { 4430b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VOP3; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric static bool isSDWA(const MachineInstr &MI) { 4470b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SDWA; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric bool isSDWA(uint16_t Opcode) const { 4510b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SDWA; 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric static bool isVOPC(const MachineInstr &MI) { 4550b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VOPC; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric bool isVOPC(uint16_t Opcode) const { 4590b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VOPC; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric static bool isMUBUF(const MachineInstr &MI) { 4630b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::MUBUF; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric 4660b57cec5SDimitry Andric bool isMUBUF(uint16_t Opcode) const { 4670b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::MUBUF; 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric static bool isMTBUF(const MachineInstr &MI) { 4710b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::MTBUF; 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric bool isMTBUF(uint16_t Opcode) const { 4750b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::MTBUF; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric static bool isSMRD(const MachineInstr &MI) { 4790b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SMRD; 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric bool isSMRD(uint16_t Opcode) const { 4830b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SMRD; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric bool isBufferSMRD(const MachineInstr &MI) const; 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric static bool isDS(const MachineInstr &MI) { 4890b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::DS; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric bool isDS(uint16_t Opcode) const { 4930b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::DS; 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric bool isAlwaysGDS(uint16_t Opcode) const; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric static bool isMIMG(const MachineInstr &MI) { 4990b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::MIMG; 5000b57cec5SDimitry Andric } 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric bool isMIMG(uint16_t Opcode) const { 5030b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::MIMG; 5040b57cec5SDimitry Andric } 5050b57cec5SDimitry Andric 5060b57cec5SDimitry Andric static bool isGather4(const MachineInstr &MI) { 5070b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::Gather4; 5080b57cec5SDimitry Andric } 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric bool isGather4(uint16_t Opcode) const { 5110b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::Gather4; 5120b57cec5SDimitry Andric } 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric static bool isFLAT(const MachineInstr &MI) { 5150b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FLAT; 5160b57cec5SDimitry Andric } 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric // Is a FLAT encoded instruction which accesses a specific segment, 5190b57cec5SDimitry Andric // i.e. global_* or scratch_*. 5200b57cec5SDimitry Andric static bool isSegmentSpecificFLAT(const MachineInstr &MI) { 5210b57cec5SDimitry Andric auto Flags = MI.getDesc().TSFlags; 522fe6060f1SDimitry Andric return Flags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch); 5230b57cec5SDimitry Andric } 5240b57cec5SDimitry Andric 525e8d8bef9SDimitry Andric bool isSegmentSpecificFLAT(uint16_t Opcode) const { 526e8d8bef9SDimitry Andric auto Flags = get(Opcode).TSFlags; 527fe6060f1SDimitry Andric return Flags & (SIInstrFlags::FlatGlobal | SIInstrFlags::FlatScratch); 528e8d8bef9SDimitry Andric } 529e8d8bef9SDimitry Andric 530e8d8bef9SDimitry Andric static bool isFLATGlobal(const MachineInstr &MI) { 531fe6060f1SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FlatGlobal; 532e8d8bef9SDimitry Andric } 533e8d8bef9SDimitry Andric 534e8d8bef9SDimitry Andric bool isFLATGlobal(uint16_t Opcode) const { 535fe6060f1SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FlatGlobal; 536e8d8bef9SDimitry Andric } 537e8d8bef9SDimitry Andric 5380b57cec5SDimitry Andric static bool isFLATScratch(const MachineInstr &MI) { 539fe6060f1SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FlatScratch; 540e8d8bef9SDimitry Andric } 541e8d8bef9SDimitry Andric 542e8d8bef9SDimitry Andric bool isFLATScratch(uint16_t Opcode) const { 543fe6060f1SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FlatScratch; 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric // Any FLAT encoded instruction, including global_* and scratch_*. 5470b57cec5SDimitry Andric bool isFLAT(uint16_t Opcode) const { 5480b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FLAT; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric static bool isEXP(const MachineInstr &MI) { 5520b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::EXP; 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric bool isEXP(uint16_t Opcode) const { 5560b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::EXP; 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 559fe6060f1SDimitry Andric static bool isAtomicNoRet(const MachineInstr &MI) { 560fe6060f1SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IsAtomicNoRet; 561fe6060f1SDimitry Andric } 562fe6060f1SDimitry Andric 563fe6060f1SDimitry Andric bool isAtomicNoRet(uint16_t Opcode) const { 564fe6060f1SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::IsAtomicNoRet; 565fe6060f1SDimitry Andric } 566fe6060f1SDimitry Andric 567fe6060f1SDimitry Andric static bool isAtomicRet(const MachineInstr &MI) { 568fe6060f1SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IsAtomicRet; 569fe6060f1SDimitry Andric } 570fe6060f1SDimitry Andric 571fe6060f1SDimitry Andric bool isAtomicRet(uint16_t Opcode) const { 572fe6060f1SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::IsAtomicRet; 573fe6060f1SDimitry Andric } 574fe6060f1SDimitry Andric 575fe6060f1SDimitry Andric static bool isAtomic(const MachineInstr &MI) { 576fe6060f1SDimitry Andric return MI.getDesc().TSFlags & (SIInstrFlags::IsAtomicRet | 577fe6060f1SDimitry Andric SIInstrFlags::IsAtomicNoRet); 578fe6060f1SDimitry Andric } 579fe6060f1SDimitry Andric 580fe6060f1SDimitry Andric bool isAtomic(uint16_t Opcode) const { 581fe6060f1SDimitry Andric return get(Opcode).TSFlags & (SIInstrFlags::IsAtomicRet | 582fe6060f1SDimitry Andric SIInstrFlags::IsAtomicNoRet); 583fe6060f1SDimitry Andric } 584fe6060f1SDimitry Andric 5850b57cec5SDimitry Andric static bool isWQM(const MachineInstr &MI) { 5860b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::WQM; 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric bool isWQM(uint16_t Opcode) const { 5900b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::WQM; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric static bool isDisableWQM(const MachineInstr &MI) { 5940b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::DisableWQM; 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric bool isDisableWQM(uint16_t Opcode) const { 5980b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::DisableWQM; 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric static bool isVGPRSpill(const MachineInstr &MI) { 6020b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VGPRSpill; 6030b57cec5SDimitry Andric } 6040b57cec5SDimitry Andric 6050b57cec5SDimitry Andric bool isVGPRSpill(uint16_t Opcode) const { 6060b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VGPRSpill; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric static bool isSGPRSpill(const MachineInstr &MI) { 6100b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SGPRSpill; 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric bool isSGPRSpill(uint16_t Opcode) const { 6140b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SGPRSpill; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric static bool isDPP(const MachineInstr &MI) { 6180b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::DPP; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric bool isDPP(uint16_t Opcode) const { 6220b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::DPP; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 625e8d8bef9SDimitry Andric static bool isTRANS(const MachineInstr &MI) { 626e8d8bef9SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::TRANS; 627e8d8bef9SDimitry Andric } 628e8d8bef9SDimitry Andric 629e8d8bef9SDimitry Andric bool isTRANS(uint16_t Opcode) const { 630e8d8bef9SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::TRANS; 631e8d8bef9SDimitry Andric } 632e8d8bef9SDimitry Andric 6330b57cec5SDimitry Andric static bool isVOP3P(const MachineInstr &MI) { 6340b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VOP3P; 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric bool isVOP3P(uint16_t Opcode) const { 6380b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VOP3P; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric static bool isVINTRP(const MachineInstr &MI) { 6420b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VINTRP; 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric bool isVINTRP(uint16_t Opcode) const { 6460b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::VINTRP; 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric static bool isMAI(const MachineInstr &MI) { 6500b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IsMAI; 6510b57cec5SDimitry Andric } 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric bool isMAI(uint16_t Opcode) const { 6540b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::IsMAI; 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6578bcb0991SDimitry Andric static bool isDOT(const MachineInstr &MI) { 6588bcb0991SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IsDOT; 6598bcb0991SDimitry Andric } 6608bcb0991SDimitry Andric 6618bcb0991SDimitry Andric bool isDOT(uint16_t Opcode) const { 6628bcb0991SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::IsDOT; 6638bcb0991SDimitry Andric } 6648bcb0991SDimitry Andric 6650b57cec5SDimitry Andric static bool isScalarUnit(const MachineInstr &MI) { 6660b57cec5SDimitry Andric return MI.getDesc().TSFlags & (SIInstrFlags::SALU | SIInstrFlags::SMRD); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric static bool usesVM_CNT(const MachineInstr &MI) { 6700b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::VM_CNT; 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric static bool usesLGKM_CNT(const MachineInstr &MI) { 6740b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::LGKM_CNT; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric static bool sopkIsZext(const MachineInstr &MI) { 6780b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SOPK_ZEXT; 6790b57cec5SDimitry Andric } 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric bool sopkIsZext(uint16_t Opcode) const { 6820b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SOPK_ZEXT; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric /// \returns true if this is an s_store_dword* instruction. This is more 6860b57cec5SDimitry Andric /// specific than than isSMEM && mayStore. 6870b57cec5SDimitry Andric static bool isScalarStore(const MachineInstr &MI) { 6880b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::SCALAR_STORE; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric bool isScalarStore(uint16_t Opcode) const { 6920b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::SCALAR_STORE; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric static bool isFixedSize(const MachineInstr &MI) { 6960b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FIXED_SIZE; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric bool isFixedSize(uint16_t Opcode) const { 7000b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FIXED_SIZE; 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric static bool hasFPClamp(const MachineInstr &MI) { 7040b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FPClamp; 7050b57cec5SDimitry Andric } 7060b57cec5SDimitry Andric 7070b57cec5SDimitry Andric bool hasFPClamp(uint16_t Opcode) const { 7080b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FPClamp; 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric static bool hasIntClamp(const MachineInstr &MI) { 7120b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::IntClamp; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric uint64_t getClampMask(const MachineInstr &MI) const { 7160b57cec5SDimitry Andric const uint64_t ClampFlags = SIInstrFlags::FPClamp | 7170b57cec5SDimitry Andric SIInstrFlags::IntClamp | 7180b57cec5SDimitry Andric SIInstrFlags::ClampLo | 7190b57cec5SDimitry Andric SIInstrFlags::ClampHi; 7200b57cec5SDimitry Andric return MI.getDesc().TSFlags & ClampFlags; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric static bool usesFPDPRounding(const MachineInstr &MI) { 7240b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FPDPRounding; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric bool usesFPDPRounding(uint16_t Opcode) const { 7280b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FPDPRounding; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric static bool isFPAtomic(const MachineInstr &MI) { 7320b57cec5SDimitry Andric return MI.getDesc().TSFlags & SIInstrFlags::FPAtomic; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric 7350b57cec5SDimitry Andric bool isFPAtomic(uint16_t Opcode) const { 7360b57cec5SDimitry Andric return get(Opcode).TSFlags & SIInstrFlags::FPAtomic; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric bool isVGPRCopy(const MachineInstr &MI) const { 7400b57cec5SDimitry Andric assert(MI.isCopy()); 741e8d8bef9SDimitry Andric Register Dest = MI.getOperand(0).getReg(); 7420b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 7430b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 7440b57cec5SDimitry Andric return !RI.isSGPRReg(MRI, Dest); 7450b57cec5SDimitry Andric } 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric bool hasVGPRUses(const MachineInstr &MI) const { 7480b57cec5SDimitry Andric const MachineFunction &MF = *MI.getParent()->getParent(); 7490b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 7500b57cec5SDimitry Andric return llvm::any_of(MI.explicit_uses(), 7510b57cec5SDimitry Andric [&MRI, this](const MachineOperand &MO) { 7520b57cec5SDimitry Andric return MO.isReg() && RI.isVGPR(MRI, MO.getReg());}); 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7555ffd83dbSDimitry Andric /// Return true if the instruction modifies the mode register.q 7565ffd83dbSDimitry Andric static bool modifiesModeRegister(const MachineInstr &MI); 7575ffd83dbSDimitry Andric 7580b57cec5SDimitry Andric /// Whether we must prevent this instruction from executing with EXEC = 0. 7590b57cec5SDimitry Andric bool hasUnwantedEffectsWhenEXECEmpty(const MachineInstr &MI) const; 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric /// Returns true if the instruction could potentially depend on the value of 7620b57cec5SDimitry Andric /// exec. If false, exec dependencies may safely be ignored. 7630b57cec5SDimitry Andric bool mayReadEXEC(const MachineRegisterInfo &MRI, const MachineInstr &MI) const; 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric bool isInlineConstant(const APInt &Imm) const; 7660b57cec5SDimitry Andric 767480093f4SDimitry Andric bool isInlineConstant(const APFloat &Imm) const { 768480093f4SDimitry Andric return isInlineConstant(Imm.bitcastToAPInt()); 769480093f4SDimitry Andric } 770480093f4SDimitry Andric 7710b57cec5SDimitry Andric bool isInlineConstant(const MachineOperand &MO, uint8_t OperandType) const; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric bool isInlineConstant(const MachineOperand &MO, 7740b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const { 7750b57cec5SDimitry Andric return isInlineConstant(MO, OpInfo.OperandType); 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric /// \p returns true if \p UseMO is substituted with \p DefMO in \p MI it would 7790b57cec5SDimitry Andric /// be an inline immediate. 7800b57cec5SDimitry Andric bool isInlineConstant(const MachineInstr &MI, 7810b57cec5SDimitry Andric const MachineOperand &UseMO, 7820b57cec5SDimitry Andric const MachineOperand &DefMO) const { 7830b57cec5SDimitry Andric assert(UseMO.getParent() == &MI); 7840b57cec5SDimitry Andric int OpIdx = MI.getOperandNo(&UseMO); 7850b57cec5SDimitry Andric if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) { 7860b57cec5SDimitry Andric return false; 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric return isInlineConstant(DefMO, MI.getDesc().OpInfo[OpIdx]); 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric /// \p returns true if the operand \p OpIdx in \p MI is a valid inline 7930b57cec5SDimitry Andric /// immediate. 7940b57cec5SDimitry Andric bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx) const { 7950b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 7960b57cec5SDimitry Andric return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType); 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric bool isInlineConstant(const MachineInstr &MI, unsigned OpIdx, 8000b57cec5SDimitry Andric const MachineOperand &MO) const { 8010b57cec5SDimitry Andric if (!MI.getDesc().OpInfo || OpIdx >= MI.getDesc().NumOperands) 8020b57cec5SDimitry Andric return false; 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric if (MI.isCopy()) { 8050b57cec5SDimitry Andric unsigned Size = getOpSize(MI, OpIdx); 8060b57cec5SDimitry Andric assert(Size == 8 || Size == 4); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric uint8_t OpType = (Size == 8) ? 8090b57cec5SDimitry Andric AMDGPU::OPERAND_REG_IMM_INT64 : AMDGPU::OPERAND_REG_IMM_INT32; 8100b57cec5SDimitry Andric return isInlineConstant(MO, OpType); 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric return isInlineConstant(MO, MI.getDesc().OpInfo[OpIdx].OperandType); 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric bool isInlineConstant(const MachineOperand &MO) const { 8170b57cec5SDimitry Andric const MachineInstr *Parent = MO.getParent(); 8180b57cec5SDimitry Andric return isInlineConstant(*Parent, Parent->getOperandNo(&MO)); 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric bool isLiteralConstant(const MachineOperand &MO, 8220b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const { 8230b57cec5SDimitry Andric return MO.isImm() && !isInlineConstant(MO, OpInfo.OperandType); 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric 8260b57cec5SDimitry Andric bool isLiteralConstant(const MachineInstr &MI, int OpIdx) const { 8270b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 8280b57cec5SDimitry Andric return MO.isImm() && !isInlineConstant(MI, OpIdx); 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric // Returns true if this operand could potentially require a 32-bit literal 8320b57cec5SDimitry Andric // operand, but not necessarily. A FrameIndex for example could resolve to an 8330b57cec5SDimitry Andric // inline immediate value that will not require an additional 4-bytes; this 8340b57cec5SDimitry Andric // assumes that it will. 8350b57cec5SDimitry Andric bool isLiteralConstantLike(const MachineOperand &MO, 8360b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const; 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric bool isImmOperandLegal(const MachineInstr &MI, unsigned OpNo, 8390b57cec5SDimitry Andric const MachineOperand &MO) const; 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric /// Return true if this 64-bit VALU instruction has a 32-bit encoding. 8420b57cec5SDimitry Andric /// This function will return false if you pass it a 32-bit instruction. 8430b57cec5SDimitry Andric bool hasVALU32BitEncoding(unsigned Opcode) const; 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric /// Returns true if this operand uses the constant bus. 8460b57cec5SDimitry Andric bool usesConstantBus(const MachineRegisterInfo &MRI, 8470b57cec5SDimitry Andric const MachineOperand &MO, 8480b57cec5SDimitry Andric const MCOperandInfo &OpInfo) const; 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric /// Return true if this instruction has any modifiers. 8510b57cec5SDimitry Andric /// e.g. src[012]_mod, omod, clamp. 8520b57cec5SDimitry Andric bool hasModifiers(unsigned Opcode) const; 8530b57cec5SDimitry Andric 8540b57cec5SDimitry Andric bool hasModifiersSet(const MachineInstr &MI, 8550b57cec5SDimitry Andric unsigned OpName) const; 8560b57cec5SDimitry Andric bool hasAnyModifiersSet(const MachineInstr &MI) const; 8570b57cec5SDimitry Andric 8580b57cec5SDimitry Andric bool canShrink(const MachineInstr &MI, 8590b57cec5SDimitry Andric const MachineRegisterInfo &MRI) const; 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric MachineInstr *buildShrunkInst(MachineInstr &MI, 8620b57cec5SDimitry Andric unsigned NewOpcode) const; 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric bool verifyInstruction(const MachineInstr &MI, 8650b57cec5SDimitry Andric StringRef &ErrInfo) const override; 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric unsigned getVALUOp(const MachineInstr &MI) const; 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric /// Return the correct register class for \p OpNo. For target-specific 8700b57cec5SDimitry Andric /// instructions, this will return the register class that has been defined 8710b57cec5SDimitry Andric /// in tablegen. For generic instructions, like REG_SEQUENCE it will return 8720b57cec5SDimitry Andric /// the register class of its machine operand. 8730b57cec5SDimitry Andric /// to infer the correct register class base on the other operands. 8740b57cec5SDimitry Andric const TargetRegisterClass *getOpRegClass(const MachineInstr &MI, 8750b57cec5SDimitry Andric unsigned OpNo) const; 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric /// Return the size in bytes of the operand OpNo on the given 8780b57cec5SDimitry Andric // instruction opcode. 8790b57cec5SDimitry Andric unsigned getOpSize(uint16_t Opcode, unsigned OpNo) const { 8800b57cec5SDimitry Andric const MCOperandInfo &OpInfo = get(Opcode).OpInfo[OpNo]; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric if (OpInfo.RegClass == -1) { 8830b57cec5SDimitry Andric // If this is an immediate operand, this must be a 32-bit literal. 8840b57cec5SDimitry Andric assert(OpInfo.OperandType == MCOI::OPERAND_IMMEDIATE); 8850b57cec5SDimitry Andric return 4; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric return RI.getRegSizeInBits(*RI.getRegClass(OpInfo.RegClass)) / 8; 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric /// This form should usually be preferred since it handles operands 8920b57cec5SDimitry Andric /// with unknown register classes. 8930b57cec5SDimitry Andric unsigned getOpSize(const MachineInstr &MI, unsigned OpNo) const { 8940b57cec5SDimitry Andric const MachineOperand &MO = MI.getOperand(OpNo); 8950b57cec5SDimitry Andric if (MO.isReg()) { 8960b57cec5SDimitry Andric if (unsigned SubReg = MO.getSubReg()) { 8975ffd83dbSDimitry Andric return RI.getSubRegIdxSize(SubReg) / 8; 8980b57cec5SDimitry Andric } 8990b57cec5SDimitry Andric } 9000b57cec5SDimitry Andric return RI.getRegSizeInBits(*getOpRegClass(MI, OpNo)) / 8; 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric /// Legalize the \p OpIndex operand of this instruction by inserting 9040b57cec5SDimitry Andric /// a MOV. For example: 9050b57cec5SDimitry Andric /// ADD_I32_e32 VGPR0, 15 9060b57cec5SDimitry Andric /// to 9070b57cec5SDimitry Andric /// MOV VGPR1, 15 9080b57cec5SDimitry Andric /// ADD_I32_e32 VGPR0, VGPR1 9090b57cec5SDimitry Andric /// 9100b57cec5SDimitry Andric /// If the operand being legalized is a register, then a COPY will be used 9110b57cec5SDimitry Andric /// instead of MOV. 9120b57cec5SDimitry Andric void legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const; 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric /// Check if \p MO is a legal operand if it was the \p OpIdx Operand 9150b57cec5SDimitry Andric /// for \p MI. 9160b57cec5SDimitry Andric bool isOperandLegal(const MachineInstr &MI, unsigned OpIdx, 9170b57cec5SDimitry Andric const MachineOperand *MO = nullptr) const; 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric /// Check if \p MO would be a valid operand for the given operand 9200b57cec5SDimitry Andric /// definition \p OpInfo. Note this does not attempt to validate constant bus 9210b57cec5SDimitry Andric /// restrictions (e.g. literal constant usage). 9220b57cec5SDimitry Andric bool isLegalVSrcOperand(const MachineRegisterInfo &MRI, 9230b57cec5SDimitry Andric const MCOperandInfo &OpInfo, 9240b57cec5SDimitry Andric const MachineOperand &MO) const; 9250b57cec5SDimitry Andric 9260b57cec5SDimitry Andric /// Check if \p MO (a register operand) is a legal register for the 9270b57cec5SDimitry Andric /// given operand description. 9280b57cec5SDimitry Andric bool isLegalRegOperand(const MachineRegisterInfo &MRI, 9290b57cec5SDimitry Andric const MCOperandInfo &OpInfo, 9300b57cec5SDimitry Andric const MachineOperand &MO) const; 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric /// Legalize operands in \p MI by either commuting it or inserting a 9330b57cec5SDimitry Andric /// copy of src1. 9340b57cec5SDimitry Andric void legalizeOperandsVOP2(MachineRegisterInfo &MRI, MachineInstr &MI) const; 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric /// Fix operands in \p MI to satisfy constant bus requirements. 9370b57cec5SDimitry Andric void legalizeOperandsVOP3(MachineRegisterInfo &MRI, MachineInstr &MI) const; 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric /// Copy a value from a VGPR (\p SrcReg) to SGPR. This function can only 9400b57cec5SDimitry Andric /// be used when it is know that the value in SrcReg is same across all 9410b57cec5SDimitry Andric /// threads in the wave. 9420b57cec5SDimitry Andric /// \returns The SGPR register that \p SrcReg was copied to. 9435ffd83dbSDimitry Andric Register readlaneVGPRToSGPR(Register SrcReg, MachineInstr &UseMI, 9440b57cec5SDimitry Andric MachineRegisterInfo &MRI) const; 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric void legalizeOperandsSMRD(MachineRegisterInfo &MRI, MachineInstr &MI) const; 947e8d8bef9SDimitry Andric void legalizeOperandsFLAT(MachineRegisterInfo &MRI, MachineInstr &MI) const; 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric void legalizeGenericOperand(MachineBasicBlock &InsertMBB, 9500b57cec5SDimitry Andric MachineBasicBlock::iterator I, 9510b57cec5SDimitry Andric const TargetRegisterClass *DstRC, 9520b57cec5SDimitry Andric MachineOperand &Op, MachineRegisterInfo &MRI, 9530b57cec5SDimitry Andric const DebugLoc &DL) const; 9540b57cec5SDimitry Andric 9550b57cec5SDimitry Andric /// Legalize all operands in this instruction. This function may create new 9560b57cec5SDimitry Andric /// instructions and control-flow around \p MI. If present, \p MDT is 9570b57cec5SDimitry Andric /// updated. 958e8d8bef9SDimitry Andric /// \returns A new basic block that contains \p MI if new blocks were created. 959e8d8bef9SDimitry Andric MachineBasicBlock * 960e8d8bef9SDimitry Andric legalizeOperands(MachineInstr &MI, MachineDominatorTree *MDT = nullptr) const; 9610b57cec5SDimitry Andric 962fe6060f1SDimitry Andric /// Change SADDR form of a FLAT \p Inst to its VADDR form if saddr operand 963fe6060f1SDimitry Andric /// was moved to VGPR. \returns true if succeeded. 964fe6060f1SDimitry Andric bool moveFlatAddrToVGPR(MachineInstr &Inst) const; 965fe6060f1SDimitry Andric 9660b57cec5SDimitry Andric /// Replace this instruction's opcode with the equivalent VALU 9670b57cec5SDimitry Andric /// opcode. This function will also move the users of \p MI to the 9680b57cec5SDimitry Andric /// VALU if necessary. If present, \p MDT is updated. 969e8d8bef9SDimitry Andric MachineBasicBlock *moveToVALU(MachineInstr &MI, 970e8d8bef9SDimitry Andric MachineDominatorTree *MDT = nullptr) const; 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric void insertNoop(MachineBasicBlock &MBB, 9730b57cec5SDimitry Andric MachineBasicBlock::iterator MI) const override; 9740b57cec5SDimitry Andric 975e8d8bef9SDimitry Andric void insertNoops(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 976e8d8bef9SDimitry Andric unsigned Quantity) const override; 977e8d8bef9SDimitry Andric 9780b57cec5SDimitry Andric void insertReturn(MachineBasicBlock &MBB) const; 9790b57cec5SDimitry Andric /// Return the number of wait states that result from executing this 9800b57cec5SDimitry Andric /// instruction. 9810b57cec5SDimitry Andric static unsigned getNumWaitStates(const MachineInstr &MI); 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric /// Returns the operand named \p Op. If \p MI does not have an 9840b57cec5SDimitry Andric /// operand named \c Op, this function returns nullptr. 9850b57cec5SDimitry Andric LLVM_READONLY 9860b57cec5SDimitry Andric MachineOperand *getNamedOperand(MachineInstr &MI, unsigned OperandName) const; 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric LLVM_READONLY 9890b57cec5SDimitry Andric const MachineOperand *getNamedOperand(const MachineInstr &MI, 9900b57cec5SDimitry Andric unsigned OpName) const { 9910b57cec5SDimitry Andric return getNamedOperand(const_cast<MachineInstr &>(MI), OpName); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9940b57cec5SDimitry Andric /// Get required immediate operand 9950b57cec5SDimitry Andric int64_t getNamedImmOperand(const MachineInstr &MI, unsigned OpName) const { 9960b57cec5SDimitry Andric int Idx = AMDGPU::getNamedOperandIdx(MI.getOpcode(), OpName); 9970b57cec5SDimitry Andric return MI.getOperand(Idx).getImm(); 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric uint64_t getDefaultRsrcDataFormat() const; 10010b57cec5SDimitry Andric uint64_t getScratchRsrcWords23() const; 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric bool isLowLatencyInstruction(const MachineInstr &MI) const; 10045ffd83dbSDimitry Andric bool isHighLatencyDef(int Opc) const override; 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric /// Return the descriptor of the target-specific machine instruction 10070b57cec5SDimitry Andric /// that corresponds to the specified pseudo or native opcode. 10080b57cec5SDimitry Andric const MCInstrDesc &getMCOpcodeFromPseudo(unsigned Opcode) const { 10090b57cec5SDimitry Andric return get(pseudoToMCOpcode(Opcode)); 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric unsigned isStackAccess(const MachineInstr &MI, int &FrameIndex) const; 10130b57cec5SDimitry Andric unsigned isSGPRStackAccess(const MachineInstr &MI, int &FrameIndex) const; 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric unsigned isLoadFromStackSlot(const MachineInstr &MI, 10160b57cec5SDimitry Andric int &FrameIndex) const override; 10170b57cec5SDimitry Andric unsigned isStoreToStackSlot(const MachineInstr &MI, 10180b57cec5SDimitry Andric int &FrameIndex) const override; 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric unsigned getInstBundleSize(const MachineInstr &MI) const; 10210b57cec5SDimitry Andric unsigned getInstSizeInBytes(const MachineInstr &MI) const override; 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric bool mayAccessFlatAddressSpace(const MachineInstr &MI) const; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric bool isNonUniformBranchInstr(MachineInstr &Instr) const; 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric void convertNonUniformIfRegion(MachineBasicBlock *IfEntry, 10280b57cec5SDimitry Andric MachineBasicBlock *IfEnd) const; 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric void convertNonUniformLoopRegion(MachineBasicBlock *LoopEntry, 10310b57cec5SDimitry Andric MachineBasicBlock *LoopEnd) const; 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric std::pair<unsigned, unsigned> 10340b57cec5SDimitry Andric decomposeMachineOperandsTargetFlags(unsigned TF) const override; 10350b57cec5SDimitry Andric 10360b57cec5SDimitry Andric ArrayRef<std::pair<int, const char *>> 10370b57cec5SDimitry Andric getSerializableTargetIndices() const override; 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric ArrayRef<std::pair<unsigned, const char *>> 10400b57cec5SDimitry Andric getSerializableDirectMachineOperandTargetFlags() const override; 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric ScheduleHazardRecognizer * 10430b57cec5SDimitry Andric CreateTargetPostRAHazardRecognizer(const InstrItineraryData *II, 10440b57cec5SDimitry Andric const ScheduleDAG *DAG) const override; 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric ScheduleHazardRecognizer * 10470b57cec5SDimitry Andric CreateTargetPostRAHazardRecognizer(const MachineFunction &MF) const override; 10480b57cec5SDimitry Andric 1049*349cc55cSDimitry Andric ScheduleHazardRecognizer * 1050*349cc55cSDimitry Andric CreateTargetMIHazardRecognizer(const InstrItineraryData *II, 1051*349cc55cSDimitry Andric const ScheduleDAGMI *DAG) const override; 1052*349cc55cSDimitry Andric 10530b57cec5SDimitry Andric bool isBasicBlockPrologue(const MachineInstr &MI) const override; 10540b57cec5SDimitry Andric 10558bcb0991SDimitry Andric MachineInstr *createPHIDestinationCopy(MachineBasicBlock &MBB, 10568bcb0991SDimitry Andric MachineBasicBlock::iterator InsPt, 10578bcb0991SDimitry Andric const DebugLoc &DL, Register Src, 10588bcb0991SDimitry Andric Register Dst) const override; 10598bcb0991SDimitry Andric 10608bcb0991SDimitry Andric MachineInstr *createPHISourceCopy(MachineBasicBlock &MBB, 10618bcb0991SDimitry Andric MachineBasicBlock::iterator InsPt, 10628bcb0991SDimitry Andric const DebugLoc &DL, Register Src, 1063480093f4SDimitry Andric unsigned SrcSubReg, 10648bcb0991SDimitry Andric Register Dst) const override; 10658bcb0991SDimitry Andric 10668bcb0991SDimitry Andric bool isWave32() const; 10678bcb0991SDimitry Andric 10680b57cec5SDimitry Andric /// Return a partially built integer add instruction without carry. 10690b57cec5SDimitry Andric /// Caller must add source operands. 10700b57cec5SDimitry Andric /// For pre-GFX9 it will generate unused carry destination operand. 10710b57cec5SDimitry Andric /// TODO: After GFX9 it should return a no-carry operation. 10720b57cec5SDimitry Andric MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, 10730b57cec5SDimitry Andric MachineBasicBlock::iterator I, 10740b57cec5SDimitry Andric const DebugLoc &DL, 10755ffd83dbSDimitry Andric Register DestReg) const; 10760b57cec5SDimitry Andric 10778bcb0991SDimitry Andric MachineInstrBuilder getAddNoCarry(MachineBasicBlock &MBB, 10788bcb0991SDimitry Andric MachineBasicBlock::iterator I, 10798bcb0991SDimitry Andric const DebugLoc &DL, 10808bcb0991SDimitry Andric Register DestReg, 10818bcb0991SDimitry Andric RegScavenger &RS) const; 10828bcb0991SDimitry Andric 10830b57cec5SDimitry Andric static bool isKillTerminator(unsigned Opcode); 10840b57cec5SDimitry Andric const MCInstrDesc &getKillTerminatorFromPseudo(unsigned Opcode) const; 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric static bool isLegalMUBUFImmOffset(unsigned Imm) { 10870b57cec5SDimitry Andric return isUInt<12>(Imm); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric /// Returns if \p Offset is legal for the subtarget as the offset to a FLAT 10910b57cec5SDimitry Andric /// encoded instruction. If \p Signed, this is for an instruction that 10920b57cec5SDimitry Andric /// interprets the offset as signed. 10930b57cec5SDimitry Andric bool isLegalFLATOffset(int64_t Offset, unsigned AddrSpace, 1094fe6060f1SDimitry Andric uint64_t FlatVariant) const; 10950b57cec5SDimitry Andric 1096e8d8bef9SDimitry Andric /// Split \p COffsetVal into {immediate offset field, remainder offset} 1097e8d8bef9SDimitry Andric /// values. 1098e8d8bef9SDimitry Andric std::pair<int64_t, int64_t> splitFlatOffset(int64_t COffsetVal, 1099e8d8bef9SDimitry Andric unsigned AddrSpace, 1100fe6060f1SDimitry Andric uint64_t FlatVariant) const; 1101e8d8bef9SDimitry Andric 11020b57cec5SDimitry Andric /// \brief Return a target-specific opcode if Opcode is a pseudo instruction. 11030b57cec5SDimitry Andric /// Return -1 if the target-specific opcode for the pseudo instruction does 11040b57cec5SDimitry Andric /// not exist. If Opcode is not a pseudo instruction, this is identity. 11050b57cec5SDimitry Andric int pseudoToMCOpcode(int Opcode) const; 11060b57cec5SDimitry Andric 1107480093f4SDimitry Andric /// \brief Check if this instruction should only be used by assembler. 1108480093f4SDimitry Andric /// Return true if this opcode should not be used by codegen. 1109480093f4SDimitry Andric bool isAsmOnlyOpcode(int MCOp) const; 1110480093f4SDimitry Andric 11110b57cec5SDimitry Andric const TargetRegisterClass *getRegClass(const MCInstrDesc &TID, unsigned OpNum, 11120b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 11130b57cec5SDimitry Andric const MachineFunction &MF) 1114fe6060f1SDimitry Andric const override; 11150b57cec5SDimitry Andric 11160b57cec5SDimitry Andric void fixImplicitOperands(MachineInstr &MI) const; 1117480093f4SDimitry Andric 1118480093f4SDimitry Andric MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, 1119480093f4SDimitry Andric ArrayRef<unsigned> Ops, 1120480093f4SDimitry Andric MachineBasicBlock::iterator InsertPt, 1121480093f4SDimitry Andric int FrameIndex, 1122480093f4SDimitry Andric LiveIntervals *LIS = nullptr, 1123480093f4SDimitry Andric VirtRegMap *VRM = nullptr) const override; 1124480093f4SDimitry Andric 1125480093f4SDimitry Andric unsigned getInstrLatency(const InstrItineraryData *ItinData, 1126480093f4SDimitry Andric const MachineInstr &MI, 1127480093f4SDimitry Andric unsigned *PredCost = nullptr) const override; 1128e8d8bef9SDimitry Andric 1129e8d8bef9SDimitry Andric const MIRFormatter *getMIRFormatter() const override { 1130e8d8bef9SDimitry Andric if (!Formatter.get()) 1131e8d8bef9SDimitry Andric Formatter = std::make_unique<AMDGPUMIRFormatter>(); 1132e8d8bef9SDimitry Andric return Formatter.get(); 1133e8d8bef9SDimitry Andric } 1134e8d8bef9SDimitry Andric 1135e8d8bef9SDimitry Andric static unsigned getDSShaderTypeValue(const MachineFunction &MF); 1136*349cc55cSDimitry Andric 1137*349cc55cSDimitry Andric const TargetSchedModel &getSchedModel() const { return SchedModel; } 11380b57cec5SDimitry Andric }; 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric /// \brief Returns true if a reg:subreg pair P has a TRC class 11410b57cec5SDimitry Andric inline bool isOfRegClass(const TargetInstrInfo::RegSubRegPair &P, 11420b57cec5SDimitry Andric const TargetRegisterClass &TRC, 11430b57cec5SDimitry Andric MachineRegisterInfo &MRI) { 11440b57cec5SDimitry Andric auto *RC = MRI.getRegClass(P.Reg); 11450b57cec5SDimitry Andric if (!P.SubReg) 11460b57cec5SDimitry Andric return RC == &TRC; 11470b57cec5SDimitry Andric auto *TRI = MRI.getTargetRegisterInfo(); 11480b57cec5SDimitry Andric return RC == TRI->getMatchingSuperRegClass(RC, &TRC, P.SubReg); 11490b57cec5SDimitry Andric } 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric /// \brief Create RegSubRegPair from a register MachineOperand 11520b57cec5SDimitry Andric inline 11530b57cec5SDimitry Andric TargetInstrInfo::RegSubRegPair getRegSubRegPair(const MachineOperand &O) { 11540b57cec5SDimitry Andric assert(O.isReg()); 11550b57cec5SDimitry Andric return TargetInstrInfo::RegSubRegPair(O.getReg(), O.getSubReg()); 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric /// \brief Return the SubReg component from REG_SEQUENCE 11590b57cec5SDimitry Andric TargetInstrInfo::RegSubRegPair getRegSequenceSubReg(MachineInstr &MI, 11600b57cec5SDimitry Andric unsigned SubReg); 11610b57cec5SDimitry Andric 11620b57cec5SDimitry Andric /// \brief Return the defining instruction for a given reg:subreg pair 11630b57cec5SDimitry Andric /// skipping copy like instructions and subreg-manipulation pseudos. 11640b57cec5SDimitry Andric /// Following another subreg of a reg:subreg isn't supported. 11650b57cec5SDimitry Andric MachineInstr *getVRegSubRegDef(const TargetInstrInfo::RegSubRegPair &P, 11660b57cec5SDimitry Andric MachineRegisterInfo &MRI); 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric /// \brief Return false if EXEC is not changed between the def of \p VReg at \p 11690b57cec5SDimitry Andric /// DefMI and the use at \p UseMI. Should be run on SSA. Currently does not 11700b57cec5SDimitry Andric /// attempt to track between blocks. 11710b57cec5SDimitry Andric bool execMayBeModifiedBeforeUse(const MachineRegisterInfo &MRI, 11720b57cec5SDimitry Andric Register VReg, 11730b57cec5SDimitry Andric const MachineInstr &DefMI, 11740b57cec5SDimitry Andric const MachineInstr &UseMI); 11750b57cec5SDimitry Andric 11760b57cec5SDimitry Andric /// \brief Return false if EXEC is not changed between the def of \p VReg at \p 11770b57cec5SDimitry Andric /// DefMI and all its uses. Should be run on SSA. Currently does not attempt to 11780b57cec5SDimitry Andric /// track between blocks. 11790b57cec5SDimitry Andric bool execMayBeModifiedBeforeAnyUse(const MachineRegisterInfo &MRI, 11800b57cec5SDimitry Andric Register VReg, 11810b57cec5SDimitry Andric const MachineInstr &DefMI); 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric namespace AMDGPU { 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric LLVM_READONLY 11860b57cec5SDimitry Andric int getVOPe64(uint16_t Opcode); 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andric LLVM_READONLY 11890b57cec5SDimitry Andric int getVOPe32(uint16_t Opcode); 11900b57cec5SDimitry Andric 11910b57cec5SDimitry Andric LLVM_READONLY 11920b57cec5SDimitry Andric int getSDWAOp(uint16_t Opcode); 11930b57cec5SDimitry Andric 11940b57cec5SDimitry Andric LLVM_READONLY 11950b57cec5SDimitry Andric int getDPPOp32(uint16_t Opcode); 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric LLVM_READONLY 11980b57cec5SDimitry Andric int getBasicFromSDWAOp(uint16_t Opcode); 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric LLVM_READONLY 12010b57cec5SDimitry Andric int getCommuteRev(uint16_t Opcode); 12020b57cec5SDimitry Andric 12030b57cec5SDimitry Andric LLVM_READONLY 12040b57cec5SDimitry Andric int getCommuteOrig(uint16_t Opcode); 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric LLVM_READONLY 12070b57cec5SDimitry Andric int getAddr64Inst(uint16_t Opcode); 12080b57cec5SDimitry Andric 12090b57cec5SDimitry Andric /// Check if \p Opcode is an Addr64 opcode. 12100b57cec5SDimitry Andric /// 12110b57cec5SDimitry Andric /// \returns \p Opcode if it is an Addr64 opcode, otherwise -1. 12120b57cec5SDimitry Andric LLVM_READONLY 12130b57cec5SDimitry Andric int getIfAddr64Inst(uint16_t Opcode); 12140b57cec5SDimitry Andric 12150b57cec5SDimitry Andric LLVM_READONLY 12160b57cec5SDimitry Andric int getMUBUFNoLdsInst(uint16_t Opcode); 12170b57cec5SDimitry Andric 12180b57cec5SDimitry Andric LLVM_READONLY 12190b57cec5SDimitry Andric int getAtomicNoRetOp(uint16_t Opcode); 12200b57cec5SDimitry Andric 12210b57cec5SDimitry Andric LLVM_READONLY 12220b57cec5SDimitry Andric int getSOPKOp(uint16_t Opcode); 12230b57cec5SDimitry Andric 1224fe6060f1SDimitry Andric /// \returns SADDR form of a FLAT Global instruction given an \p Opcode 1225fe6060f1SDimitry Andric /// of a VADDR form. 12260b57cec5SDimitry Andric LLVM_READONLY 12270b57cec5SDimitry Andric int getGlobalSaddrOp(uint16_t Opcode); 12280b57cec5SDimitry Andric 1229fe6060f1SDimitry Andric /// \returns VADDR form of a FLAT Global instruction given an \p Opcode 1230fe6060f1SDimitry Andric /// of a SADDR form. 1231fe6060f1SDimitry Andric LLVM_READONLY 1232fe6060f1SDimitry Andric int getGlobalVaddrOp(uint16_t Opcode); 1233fe6060f1SDimitry Andric 12340b57cec5SDimitry Andric LLVM_READONLY 12350b57cec5SDimitry Andric int getVCMPXNoSDstOp(uint16_t Opcode); 12360b57cec5SDimitry Andric 1237fe6060f1SDimitry Andric /// \returns ST form with only immediate offset of a FLAT Scratch instruction 1238fe6060f1SDimitry Andric /// given an \p Opcode of an SS (SADDR) form. 1239e8d8bef9SDimitry Andric LLVM_READONLY 1240e8d8bef9SDimitry Andric int getFlatScratchInstSTfromSS(uint16_t Opcode); 1241e8d8bef9SDimitry Andric 1242fe6060f1SDimitry Andric /// \returns SS (SADDR) form of a FLAT Scratch instruction given an \p Opcode 1243fe6060f1SDimitry Andric /// of an SV (VADDR) form. 1244e8d8bef9SDimitry Andric LLVM_READONLY 1245e8d8bef9SDimitry Andric int getFlatScratchInstSSfromSV(uint16_t Opcode); 1246e8d8bef9SDimitry Andric 1247fe6060f1SDimitry Andric /// \returns SV (VADDR) form of a FLAT Scratch instruction given an \p Opcode 1248fe6060f1SDimitry Andric /// of an SS (SADDR) form. 1249fe6060f1SDimitry Andric LLVM_READONLY 1250fe6060f1SDimitry Andric int getFlatScratchInstSVfromSS(uint16_t Opcode); 1251fe6060f1SDimitry Andric 12520b57cec5SDimitry Andric const uint64_t RSRC_DATA_FORMAT = 0xf00000000000LL; 12530b57cec5SDimitry Andric const uint64_t RSRC_ELEMENT_SIZE_SHIFT = (32 + 19); 12540b57cec5SDimitry Andric const uint64_t RSRC_INDEX_STRIDE_SHIFT = (32 + 21); 12550b57cec5SDimitry Andric const uint64_t RSRC_TID_ENABLE = UINT64_C(1) << (32 + 23); 12560b57cec5SDimitry Andric 12570b57cec5SDimitry Andric } // end namespace AMDGPU 12580b57cec5SDimitry Andric 12590b57cec5SDimitry Andric namespace SI { 12600b57cec5SDimitry Andric namespace KernelInputOffsets { 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric /// Offsets in bytes from the start of the input buffer 12630b57cec5SDimitry Andric enum Offsets { 12640b57cec5SDimitry Andric NGROUPS_X = 0, 12650b57cec5SDimitry Andric NGROUPS_Y = 4, 12660b57cec5SDimitry Andric NGROUPS_Z = 8, 12670b57cec5SDimitry Andric GLOBAL_SIZE_X = 12, 12680b57cec5SDimitry Andric GLOBAL_SIZE_Y = 16, 12690b57cec5SDimitry Andric GLOBAL_SIZE_Z = 20, 12700b57cec5SDimitry Andric LOCAL_SIZE_X = 24, 12710b57cec5SDimitry Andric LOCAL_SIZE_Y = 28, 12720b57cec5SDimitry Andric LOCAL_SIZE_Z = 32 12730b57cec5SDimitry Andric }; 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric } // end namespace KernelInputOffsets 12760b57cec5SDimitry Andric } // end namespace SI 12770b57cec5SDimitry Andric 12780b57cec5SDimitry Andric } // end namespace llvm 12790b57cec5SDimitry Andric 12800b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_SIINSTRINFO_H 1281