LLVM: lib/Target/AMDGPU/GCNVOPDUtils.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

32

33using namespace llvm;

34

35#define DEBUG_TYPE "gcn-vopd-utils"

36

41

44

45 if (IsVOPD3 && !ST.hasVOPD3())

46 return false;

47 if (!IsVOPD3 && (TII.isVOP3(FirstMI) || TII.isVOP3(SecondMI)))

48 return false;

49 if (TII.isDPP(FirstMI) || TII.isDPP(SecondMI))

50 return false;

51

54

57 for (auto &Literal : UniqueLiterals) {

59 return;

60 }

61 UniqueLiterals.push_back(&Op);

62 };

64 assert([&]() -> bool {

66 MII != FirstMI.getParent()->instr_end(); ++MII) {

67 if (&*MII == &SecondMI)

68 return true;

69 }

70 return false;

71 }() && "Expected FirstMI to precede SecondMI");

72

73 for (const auto &Use : SecondMI.uses())

75 return false;

76

77 auto getVRegIdx = [&](unsigned OpcodeIdx, unsigned OperandIdx) {

78 const MachineInstr &MI = (OpcodeIdx == VOPD::X) ? FirstMI : SecondMI;

80 if (Operand.isReg() && TRI->isVectorRegister(MRI, Operand.getReg()))

81 return Operand.getReg();

83 };

84

85 auto InstInfo =

87

88 for (auto CompIdx : VOPD::COMPONENTS) {

89 const MachineInstr &MI = (CompIdx == VOPD::X) ? FirstMI : SecondMI;

90

91 const MachineOperand &Src0 = *TII.getNamedOperand(MI, AMDGPU::OpName::src0);

92 if (Src0.isReg()) {

93 if (TRI->isVectorRegister(MRI, Src0.getReg())) {

96 }

97 } else if (TII.isInlineConstant(Src0)) {

98 if (IsVOPD3)

99 return false;

100 addLiteral(Src0);

101 }

102

103 if (InstInfo[CompIdx].hasMandatoryLiteral()) {

104 if (IsVOPD3)

105 return false;

106

107 auto CompOprIdx = InstInfo[CompIdx].getMandatoryLiteralCompOperandIndex();

108 addLiteral(MI.getOperand(CompOprIdx));

109 }

110 if (MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))

111 UniqueScalarRegs.push_back(AMDGPU::VCC_LO);

112

113 if (IsVOPD3) {

114 for (auto OpName : {AMDGPU::OpName::src1, AMDGPU::OpName::src2}) {

116 if (!Src)

117 continue;

118 if (OpName == AMDGPU::OpName::src2) {

120 continue;

121 if (MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64) {

122 UniqueScalarRegs.push_back(Src->getReg());

123 continue;

124 }

125 }

126 if (!Src->isReg() || TRI->isVGPR(MRI, Src->getReg()))

127 return false;

128 }

129

130 for (auto OpName : {AMDGPU::OpName::clamp, AMDGPU::OpName::omod,

131 AMDGPU::OpName::op_sel}) {

133 return false;

134 }

135

136

137

139 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,

140 AMDGPU::OpName::src2_modifiers}) {

143 return false;

144 }

145 }

146 }

147

148 if (UniqueLiterals.size() > 1)

149 return false;

150 if ((UniqueLiterals.size() + UniqueScalarRegs.size()) > 2)

151 return false;

152

153

154

156 FirstMI.getOpcode() == AMDGPU::V_MOV_B32_e32 &&

157 SecondMI.getOpcode() == AMDGPU::V_MOV_B32_e32;

158 bool AllowSameVGPR = ST.hasGFX1250Insts();

159

160 if (InstInfo.hasInvalidOperand(getVRegIdx, *TRI, SkipSrc, AllowSameVGPR,

161 IsVOPD3))

162 return false;

163

164 if (IsVOPD3) {

165

168 *TII.getNamedOperand(SecondMI, AMDGPU::OpName::src2);

170 return false;

171 }

174 *TII.getNamedOperand(FirstMI, AMDGPU::OpName::src2);

176 return false;

177 }

178 }

179

180 LLVM_DEBUG(dbgs() << "VOPD Reg Constraints Passed\n\tX: " << FirstMI

181 << "\n\tY: " << SecondMI << "\n");

182 return true;

183}

184

185

186

187

195 unsigned Opc2 = SecondMI.getOpcode();

196

197 const auto checkVOPD = [&](bool VOPD3) -> bool {

199

200

201 if (!FirstMI)

202 return SecondCanBeVOPD.Y || SecondCanBeVOPD.X;

203

206

207 if (!((FirstCanBeVOPD.X && SecondCanBeVOPD.Y) ||

208 (FirstCanBeVOPD.Y && SecondCanBeVOPD.X)))

209 return false;

210

212 };

213

214 return checkVOPD(false) || (ST.hasVOPD3() && checkVOPD(true));

215}

216

217namespace {

218

219

220

221

222struct VOPDPairingMutation : ScheduleDAGMutation {

224

225 VOPDPairingMutation(

228

229 void apply(ScheduleDAGInstrs *DAG) override {

230 const TargetInstrInfo &TII = *DAG->TII;

231 const GCNSubtarget &ST = DAG->MF.getSubtarget();

233 LLVM_DEBUG(dbgs() << "Target does not support VOPDPairingMutation\n");

234 return;

235 }

236

237 std::vector::iterator ISUI, JSUI;

238 for (ISUI = DAG->SUnits.begin(); ISUI != DAG->SUnits.end(); ++ISUI) {

239 const MachineInstr *IMI = ISUI->getInstr();

241 continue;

243 continue;

244

245 for (JSUI = ISUI + 1; JSUI != DAG->SUnits.end(); ++JSUI) {

246 if (JSUI->isBoundaryNode())

247 continue;

248 const MachineInstr *JMI = JSUI->getInstr();

251 continue;

253 break;

254 }

255 }

256 LLVM_DEBUG(dbgs() << "Completed VOPDPairingMutation\n");

257 }

258};

259}

260

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.

Definition GCNVOPDUtils.cpp:188

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 - Return the argument parameter cast to the specified type.

std::unique_ptr< ScheduleDAGMutation > createVOPDPairingMutation()

Definition GCNVOPDUtils.cpp:261

bool checkVOPDRegConstraints(const SIInstrInfo &TII, const MachineInstr &FirstMI, const MachineInstr &SecondMI, bool IsVOPD3)

Definition GCNVOPDUtils.cpp:37

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.