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.

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

const HexagonInstrInfo * TII

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.