35#define DEBUG_TYPE "gcn-vopd-utils"
45 if (IsVOPD3 && !ST.hasVOPD3())
47 if (!IsVOPD3 && (
TII.isVOP3(FirstMI) ||
TII.isVOP3(SecondMI)))
49 if (
TII.isDPP(FirstMI) ||
TII.isDPP(SecondMI))
57 for (
auto &
Literal : UniqueLiterals) {
61 UniqueLiterals.push_back(&
Op);
66 MII != FirstMI.
getParent()->instr_end(); ++MII) {
67 if (&*MII == &SecondMI)
71 }() &&
"Expected FirstMI to precede SecondMI");
73 for (
const auto &
Use : SecondMI.
uses())
77 auto getVRegIdx = [&](
unsigned OpcodeIdx,
unsigned OperandIdx) {
78 const MachineInstr &
MI = (OpcodeIdx == VOPD::X) ? FirstMI : SecondMI;
88 for (
auto CompIdx : VOPD::COMPONENTS) {
89 const MachineInstr &
MI = (CompIdx == VOPD::X) ? FirstMI : SecondMI;
97 }
else if (!
TII.isInlineConstant(Src0)) {
103 if (InstInfo[CompIdx].hasMandatoryLiteral()) {
107 auto CompOprIdx = InstInfo[CompIdx].getMandatoryLiteralCompOperandIndex();
108 addLiteral(
MI.getOperand(CompOprIdx));
110 if (
MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))
111 UniqueScalarRegs.
push_back(AMDGPU::VCC_LO);
114 for (
auto OpName : {AMDGPU::OpName::src1, AMDGPU::OpName::src2}) {
118 if (
OpName == AMDGPU::OpName::src2) {
121 if (
MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64) {
122 UniqueScalarRegs.
push_back(Src->getReg());
126 if (!Src->isReg() || !
TRI->isVGPR(
MRI, Src->getReg()))
130 for (
auto OpName : {AMDGPU::OpName::clamp, AMDGPU::OpName::omod,
131 AMDGPU::OpName::op_sel}) {
139 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
140 AMDGPU::OpName::src2_modifiers}) {
148 if (UniqueLiterals.
size() > 1)
150 if ((UniqueLiterals.
size() + UniqueScalarRegs.
size()) > 2)
156 FirstMI.
getOpcode() == AMDGPU::V_MOV_B32_e32 &&
157 SecondMI.
getOpcode() == AMDGPU::V_MOV_B32_e32;
158 bool AllowSameVGPR = ST.hasGFX1250Insts();
160 if (InstInfo.hasInvalidOperand(getVRegIdx, *
TRI, SkipSrc, AllowSameVGPR,
168 *
TII.getNamedOperand(SecondMI, AMDGPU::OpName::src2);
174 *
TII.getNamedOperand(FirstMI, AMDGPU::OpName::src2);
180 LLVM_DEBUG(
dbgs() <<
"VOPD Reg Constraints Passed\n\tX: " << FirstMI
181 <<
"\n\tY: " << SecondMI <<
"\n");
197 const auto checkVOPD = [&](
bool VOPD3) ->
bool {
202 return SecondCanBeVOPD.Y || SecondCanBeVOPD.X;
207 if (!((FirstCanBeVOPD.X && SecondCanBeVOPD.Y) ||
208 (FirstCanBeVOPD.Y && SecondCanBeVOPD.X)))
214 return checkVOPD(
false) || (ST.hasVOPD3() && checkVOPD(
true));
222struct VOPDPairingMutation : ScheduleDAGMutation {
229 void apply(ScheduleDAGInstrs *DAG)
override {
230 const TargetInstrInfo &
TII = *DAG->
TII;
233 LLVM_DEBUG(
dbgs() <<
"Target does not support VOPDPairingMutation\n");
237 std::vector<SUnit>::iterator ISUI, JSUI;
238 for (ISUI = DAG->
SUnits.begin(); ISUI != DAG->
SUnits.end(); ++ISUI) {
239 const MachineInstr *IMI = ISUI->getInstr();
245 for (JSUI = ISUI + 1; JSUI != DAG->
SUnits.end(); ++JSUI) {
246 if (JSUI->isBoundaryNode())
248 const MachineInstr *JMI = JSUI->getInstr();
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
const TargetInstrInfo & TII
Provides AMDGPU specific target descriptions.
Base class for AMDGPU specific classes of TargetSubtarget.
AMD GCN specific subclass of TargetSubtarget.
static bool shouldScheduleVOPDAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be scheduled together.
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Interface definition for SIInstrInfo.
This file defines the SmallVector class.
MachineInstrBundleIterator< const MachineInstr > const_iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
bool modifiesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr modifies (fully define or partially define) the specified register.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
mop_range uses()
Returns all operands which may be register uses.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const GCNSubtarget & getSubtarget() const
const TargetInstrInfo * TII
Target instruction information.
std::vector< SUnit > SUnits
The scheduling units.
MachineFunction & MF
Machine function.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetSubtargetInfo - Generic base class for all target subtargets.
A Use represents the edge between a Value definition and its users.
CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3)
LLVM_READONLY bool hasNamedOperand(uint64_t Opcode, OpName NamedIdx)
unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST)
VOPD::InstInfo getVOPDInstInfo(const MCInstrDesc &OpX, const MCInstrDesc &OpY)
bool hasVOPD(const MCSubtargetInfo &STI)
void apply(Opt *O, const Mod &M, const Mods &... Ms)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
std::unique_ptr< ScheduleDAGMutation > createVOPDPairingMutation()
bool checkVOPDRegConstraints(const SIInstrInfo &TII, const MachineInstr &FirstMI, const MachineInstr &SecondMI, bool IsVOPD3)
LLVM_ABI bool fuseInstructionPair(ScheduleDAGInstrs &DAG, SUnit &FirstSU, SUnit &SecondSU)
Create an artificial edge between FirstSU and SecondSU.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
DWARFExpression::Operation Op
bool(*)(const TargetInstrInfo &TII, const TargetSubtargetInfo &STI, const MachineInstr *FirstMI, const MachineInstr &SecondMI) MacroFusionPredTy
Check if the instr pair, FirstMI and SecondMI, should be fused together.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI bool hasLessThanNumFused(const SUnit &SU, unsigned FuseLimit)
Checks if the number of cluster edges between SU and its predecessors is less than FuseLimit.