LLVM 24.0.0git
GCNVOPDUtils.cpp
Go to the documentation of this file.
1//===- GCNVOPDUtils.cpp - GCN VOPD Utils ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9/// \file This file contains the AMDGPU DAG scheduling
10/// mutation to pair VOPD instructions back to back. It also contains
11// subroutines useful in the creation of VOPD instructions
12//
13//===----------------------------------------------------------------------===//
14
15#include "GCNVOPDUtils.h"
16#include "AMDGPUSubtarget.h"
17#include "GCNSubtarget.h"
18#include "SIInstrInfo.h"
29#include "llvm/MC/MCInst.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "gcn-vopd-utils"
34
35// Check if physical register from src<SrcIdx> operand of MI<CompIdx> matches
36// register class constraints in corresponding VOPDOpc operand with name
37// src/vsrc<SrcIdx><CompIdx>.
38static bool isValidVOPDSrc(const SIInstrInfo &TII, int VOPDOpc,
39 unsigned CompIdx, unsigned SrcIdx,
40 Register PhysSrcReg) {
41 using namespace AMDGPU;
42 int OpIdx = -1;
43 const bool IsX = CompIdx == VOPD::X;
44 switch (SrcIdx) {
45 case 0:
46 OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::src0X : OpName::src0Y);
47 break;
48 case 1:
49 OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::vsrc1X : OpName::vsrc1Y);
50 break;
51 case 2:
52 OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::vsrc2X : OpName::vsrc2Y);
53 if (OpIdx == -1)
54 OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::src2X : OpName::src2Y);
55 break;
56 default:
57 llvm_unreachable("unexpected VOPD source index");
58 }
59
60 assert(OpIdx != -1);
61 return TII.getRegClass(TII.get(VOPDOpc), OpIdx)->contains(PhysSrcReg);
62}
63
65 AMDGPU::OpName Name) {
66 return MI.getOperand(getNamedOperandIdx(MI.getOpcode(), Name));
67}
68
69// Check if MI is a VOP3P instruction with operands that satisfy the constraints
70// for mapping it to a VOP2/VOPD opcode: no modifiers, no clamp, src1 and src2
71// are registers (src0 can be register or literal), and src2 is same as dst.
72static bool canMapVOP3PToVOPD(const MachineInstr &MI) {
73 unsigned Opc = MI.getOpcode();
74 if (Opc != AMDGPU::V_DOT2_F32_F16 && Opc != AMDGPU::V_DOT2_F32_BF16)
75 return false;
76 // src0 can be register or literal
77 if (getNamedOp(MI, AMDGPU::OpName::src0_modifiers).getImm() !=
79 return false;
80 if (getNamedOp(MI, AMDGPU::OpName::src1_modifiers).getImm() !=
82 return false;
83 if (!getNamedOp(MI, AMDGPU::OpName::src1).isReg())
84 return false;
85 if (getNamedOp(MI, AMDGPU::OpName::src2_modifiers).getImm() !=
87 return false;
88 if (!getNamedOp(MI, AMDGPU::OpName::src2).isReg())
89 return false;
90 if (getNamedOp(MI, AMDGPU::OpName::clamp).getImm() != 0)
91 return false;
92 return getNamedOp(MI, AMDGPU::OpName::vdst).getReg() ==
93 getNamedOp(MI, AMDGPU::OpName::src2).getReg();
94}
95
97 const MachineInstr &MIX,
98 const MachineInstr &MIY, bool IsVOPD3,
99 bool AllowSameVGPR) {
100 namespace VOPD = AMDGPU::VOPD;
101
102 const MachineFunction *MF = MIX.getMF();
103 const GCNSubtarget &ST = MF->getSubtarget<GCNSubtarget>();
104
105 if (IsVOPD3 && !ST.hasVOPD3())
106 return false;
107 if (!IsVOPD3 && ((TII.isVOP3(MIX) && !canMapVOP3PToVOPD(MIX)) ||
108 (TII.isVOP3(MIY) && !canMapVOP3PToVOPD(MIY))))
109 return false;
110 if (TII.isDPP(MIX) || TII.isDPP(MIY))
111 return false;
112
113 const SIRegisterInfo *TRI = ST.getRegisterInfo();
114 const MachineRegisterInfo &MRI = MF->getRegInfo();
115 // Literals also count against scalar bus limit
117 auto addLiteral = [&](const MachineOperand &Op) {
118 for (auto &Literal : UniqueLiterals) {
119 if (Literal->isIdenticalTo(Op))
120 return;
121 }
122 UniqueLiterals.push_back(&Op);
123 };
124 SmallSet<Register, 4> UniqueScalarRegs;
125
126 unsigned EncodingFamily = AMDGPU::getVOPDEncodingFamily(ST);
127 unsigned XOpc = AMDGPU::getVOPDOpcode(MIX.getOpcode(), IsVOPD3);
128 unsigned YOpc = AMDGPU::getVOPDOpcode(MIY.getOpcode(), IsVOPD3);
129 int VOPDOpc = AMDGPU::getVOPDFull(XOpc, YOpc, EncodingFamily, IsVOPD3);
130 assert(VOPDOpc != -1);
131
132 auto InstInfo = AMDGPU::getVOPDInstInfo(MIX.getDesc(), MIY.getDesc());
133
134 for (auto CompIdx : VOPD::COMPONENTS) {
135 const MachineInstr &MI = (CompIdx == VOPD::X) ? MIX : MIY;
136
137 const MachineOperand &Src0 = *TII.getNamedOperand(MI, AMDGPU::OpName::src0);
138 if (Src0.isReg()) {
139 if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 0, Src0.getReg()))
140 return false;
141 if (!TRI->isVectorRegister(MRI, Src0.getReg()))
142 UniqueScalarRegs.insert(Src0.getReg());
143 } else if (!TII.isInlineConstant(Src0)) {
144 if (IsVOPD3)
145 return false;
146 addLiteral(Src0);
147 }
148
149 // V_FMAMK_F32 (src1) and V_FMAAK_F32 (src2) have a mandatory literal.
150 // VOPD3 instructions don't set MandatoryLiteralIdx.
151 if (InstInfo[CompIdx].hasMandatoryLiteral()) {
152 auto CompOprIdx = InstInfo[CompIdx].getMandatoryLiteralCompOperandIndex();
153 addLiteral(MI.getOperand(CompOprIdx));
154 }
155
156 // VOPD only. Affects V_CNDMASK_B32_e32.
157 if (MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))
158 UniqueScalarRegs.insert(AMDGPU::VCC_LO);
159
160 if (const MachineOperand *Src1 =
161 TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
162 if (Src1->isReg()) {
163 if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 1, Src1->getReg()))
164 return false;
165 assert(TRI->isVectorRegister(MRI, Src1->getReg()));
166 } else if (IsVOPD3) {
167 return false;
168 }
169 }
170
171 if (IsVOPD3) {
172 if (const MachineOperand *Src2 =
173 TII.getNamedOperand(MI, AMDGPU::OpName::src2)) {
174 if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::bitop3)) {
175 // BITOP3 can be converted to DUAL_BITOP2 when src2 is zero.
176 if (!Src2->isImm() || Src2->getImm())
177 return false;
178 } else {
179 if (!Src2->isReg())
180 return false;
181 if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 2, Src2->getReg()))
182 return false;
183 if (!TRI->isVectorRegister(MRI, Src2->getReg())) {
184 assert(MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64);
185 UniqueScalarRegs.insert(Src2->getReg());
186 }
187 }
188 }
189 for (auto OpName : {AMDGPU::OpName::clamp, AMDGPU::OpName::omod,
190 AMDGPU::OpName::op_sel}) {
191 if (TII.hasModifiersSet(MI, OpName))
192 return false;
193 }
194
195 // Neg is allowed, other modifiers are not. NB: even though sext has the
196 // same value as neg, there are no combinable instructions with sext.
197 for (auto OpName :
198 {AMDGPU::OpName::src0_modifiers, AMDGPU::OpName::src1_modifiers,
199 AMDGPU::OpName::src2_modifiers}) {
200 const MachineOperand *Mods = TII.getNamedOperand(MI, OpName);
201 if (Mods && (Mods->getImm() & ~SISrcMods::NEG))
202 return false;
203 }
204 }
205 }
206
207 if (UniqueLiterals.size() > 1)
208 return false;
209 if ((UniqueLiterals.size() + UniqueScalarRegs.size()) > 2)
210 return false;
211
212 auto getVRegIdx = [&](unsigned OpcodeIdx, unsigned OperandIdx) {
213 const MachineInstr &MI = (OpcodeIdx == VOPD::X) ? MIX : MIY;
214 const MachineOperand &Operand = MI.getOperand(OperandIdx);
215 if (Operand.isReg() && TRI->isVectorRegister(MRI, Operand.getReg()))
216 return Operand.getReg();
217 return Register();
218 };
219
220 // On GFX1170+ if both OpX and OpY are V_MOV_B32 then OPY uses SRC2
221 // source-cache.
222 bool SkipSrc = (ST.hasGFX11_7Insts() || ST.hasGFX12Insts()) &&
223 MIX.getOpcode() == AMDGPU::V_MOV_B32_e32 &&
224 MIY.getOpcode() == AMDGPU::V_MOV_B32_e32;
225
226 // Check VGPR bank constraints for operand registers across both instructions.
227 if (InstInfo.hasInvalidOperand(getVRegIdx, *TRI, SkipSrc, AllowSameVGPR,
228 IsVOPD3))
229 return false;
230
231 LLVM_DEBUG(dbgs() << "VOPD Reg Constraints Passed\n\tX: " << MIX
232 << "\n\tY: " << MIY << "\n");
233 return true;
234}
235
236/// Core pair-eligibility check for a single VOPD encoding variant (VOPD or
237/// VOPD3). Returns the X/Y assignment on success, or std::nullopt otherwise.
238static std::optional<VOPDMatchInfo>
239tryMatchVOPDPairVariant(const SIInstrInfo &TII, unsigned EncodingFamily,
240 MachineInstr &FirstMI, MachineInstr &SecondMI,
241 bool IsVOPD3) {
242 unsigned Opc = FirstMI.getOpcode();
243 unsigned Opc2 = SecondMI.getOpcode();
244 AMDGPU::CanBeVOPD FirstCanBeVOPD =
245 AMDGPU::getCanBeVOPD(Opc, EncodingFamily, IsVOPD3);
246 AMDGPU::CanBeVOPD SecondCanBeVOPD =
247 AMDGPU::getCanBeVOPD(Opc2, EncodingFamily, IsVOPD3);
248
249 if (!(FirstCanBeVOPD.X && SecondCanBeVOPD.Y) &&
250 !(FirstCanBeVOPD.Y && SecondCanBeVOPD.X))
251 return std::nullopt;
252
253 // If SecondMI depends on FirstMI they cannot execute at the same time.
254 if (TII.hasRAWDependency(FirstMI, SecondMI))
255 return std::nullopt;
256
257 const GCNSubtarget &ST = TII.getSubtarget();
258 bool AllowSameVGPR = ST.hasGFX12Insts();
259
260 if (FirstCanBeVOPD.X && SecondCanBeVOPD.Y) {
261 if (checkVOPDRegConstraints(TII, FirstMI, SecondMI, IsVOPD3, AllowSameVGPR))
262 return VOPDMatchInfo{&FirstMI, &SecondMI, IsVOPD3};
263 }
264
265 if (FirstCanBeVOPD.Y && SecondCanBeVOPD.X) {
266 // AllowSameVGPR relaxes the VGPR bank overlap check for source operands.
267 // Only enable it when there is no antidependency.
268 bool IsAntiDep = TII.hasRAWDependency(SecondMI, FirstMI);
269 AllowSameVGPR &= !IsAntiDep;
270 if (IsAntiDep && !TII.isVOPDAntidependencyAllowed(SecondMI))
271 return std::nullopt;
272 if (checkVOPDRegConstraints(TII, SecondMI, FirstMI, IsVOPD3, AllowSameVGPR))
273 return VOPDMatchInfo{&SecondMI, &FirstMI, IsVOPD3};
274 }
275
276 return std::nullopt;
277}
278
279std::optional<VOPDMatchInfo> llvm::tryMatchVOPDPair(const SIInstrInfo &TII,
280 MachineInstr &FirstMI,
281 MachineInstr &SecondMI) {
282 const GCNSubtarget &ST = TII.getSubtarget();
283 unsigned EncodingFamily = AMDGPU::getVOPDEncodingFamily(ST);
284 if (auto Match = tryMatchVOPDPairVariant(TII, EncodingFamily, FirstMI,
285 SecondMI, /*IsVOPD3=*/false))
286 return Match;
287 if (ST.hasVOPD3())
288 return tryMatchVOPDPairVariant(TII, EncodingFamily, FirstMI, SecondMI,
289 /*IsVOPD3=*/true);
290 return std::nullopt;
291}
292
293/// Check if the instr pair, FirstMI and SecondMI, should be scheduled
294/// together. Given SecondMI, when FirstMI is unspecified, then check if
295/// SecondMI may be part of a fused pair at all.
297 const TargetSubtargetInfo &TSI,
298 const MachineInstr *FirstMI,
299 const MachineInstr &SecondMI,
300 const SDep *) {
301 const SIInstrInfo &STII = static_cast<const SIInstrInfo &>(TII);
302 const GCNSubtarget &ST = STII.getSubtarget();
303
304 // One instruction case: just check whether SecondMI is eligible at all.
305 if (!FirstMI) {
306 unsigned EncodingFamily = AMDGPU::getVOPDEncodingFamily(ST);
307 unsigned Opc2 = SecondMI.getOpcode();
308 auto checkCanBeVOPD = [&](bool VOPD3) {
309 AMDGPU::CanBeVOPD CanBeVOPD =
310 AMDGPU::getCanBeVOPD(Opc2, EncodingFamily, VOPD3);
311 return CanBeVOPD.Y || CanBeVOPD.X;
312 };
313 return checkCanBeVOPD(false) || (ST.hasVOPD3() && checkCanBeVOPD(true));
314 }
315
316#ifdef EXPENSIVE_CHECKS
317 assert([&]() -> bool {
318 for (auto MII = MachineBasicBlock::const_iterator(FirstMI);
319 MII != FirstMI->getParent()->instr_end(); ++MII) {
320 if (&*MII == &SecondMI)
321 return true;
322 }
323 return false;
324 }() && "Expected FirstMI to precede SecondMI");
325#endif
326
327 return tryMatchVOPDPair(STII, *const_cast<MachineInstr *>(FirstMI),
328 const_cast<MachineInstr &>(SecondMI))
329 .has_value();
330}
331
332/// Collect all load (dependents if \p Forward else dependencies) that connect
333/// to the \p Head SU.
334/// \p Visited should allocate enough bits for the number of SUnits, but its
335/// value can otherwise be uninitialized.
336static void collectLoads(SmallPtrSet<SUnit *, 8> &Loads, BitVector &Visited,
337 SUnit &Head, bool Forward, bool StopAtLoads) {
338 if (Head.isBoundaryNode())
339 return;
340
341 Visited.reset();
342
344 Stack.push_back(&Head);
345 while (!Stack.empty()) {
346 SUnit *SU = Stack.pop_back_val();
347 const SmallVector<SDep, 4> &Deps = Forward ? SU->Succs : SU->Preds;
348 for (const SDep &Edge : Deps) {
349 if (StopAtLoads && Edge.getKind() != SDep::Data)
350 continue;
351 SUnit *Dep = Edge.getSUnit();
352 if (Dep->isBoundaryNode() || Visited.test(Dep->NodeNum))
353 continue;
354 Visited.set(Dep->NodeNum);
355
356 if (Dep->isInstr() && Dep->getInstr()->mayLoad()) {
357 Loads.insert(Dep);
358 if (StopAtLoads)
359 continue;
360 }
361 Stack.push_back(Dep);
362 }
363 }
364}
365
366/// Checks whether fusing SU \p I with SU \p J would force the loads preceding
367/// \p J to complete before loads depending on \p I.
368///
369/// \p ILoadSuccs should hold all first load successors of \p I (via
370/// collectLoads with StopAtLoads=true). For set bits in \p LoadPredsComputed,
371/// the corresponding set in \p LoadPredsCache should hold all transitive load
372/// dependencies (via collectLoads with StopAtLoads=false). The \p Scratch
373/// bitvector should allocate enough bits for the number of SUnits.
374static bool loadsMayOverlap(
375 [[maybe_unused]] SUnit &I, const SmallPtrSet<SUnit *, 8> &ILoadSuccs,
376 SUnit &J, BitVector &LoadPredsComputed,
377 SmallVector<SmallPtrSet<SUnit *, 8>> &LoadPredsCache, BitVector &Scratch) {
378
379 if (ILoadSuccs.empty())
380 return false;
381
382 SmallPtrSet<SUnit *, 8> &JLoadPreds = LoadPredsCache[J.NodeNum];
383 if (!LoadPredsComputed.test(J.NodeNum)) {
384 collectLoads(JLoadPreds, Scratch, J, /*Forward=*/false,
385 /*StopAtLoads=*/true);
386 LoadPredsComputed.set(J.NodeNum);
387 }
388 if (JLoadPreds.empty())
389 return false;
390
391 for (SUnit *ILoad : ILoadSuccs) {
392 SmallPtrSet<SUnit *, 8> &ILoadDeps = LoadPredsCache[ILoad->NodeNum];
393 if (!LoadPredsComputed.test(ILoad->NodeNum)) {
394 collectLoads(ILoadDeps, Scratch, *ILoad, /*Forward=*/false,
395 /*StopAtLoads=*/false);
396 LoadPredsComputed.set(ILoad->NodeNum);
397 }
398
399 for (SUnit *JLoad : JLoadPreds) {
400 if (ILoad == JLoad) {
402 dbgs() << "Will not pair SU(" << I.NodeNum << ") with SU("
403 << J.NodeNum << ")\n"
404 << " Fusion would introduce a cyclic dependency with SU("
405 << ILoad->NodeNum << ")\n");
406 return true;
407 }
408
409 if (!ILoadDeps.contains(JLoad)) {
410 LLVM_DEBUG(dbgs() << "Will not pair SU(" << I.NodeNum << ") with SU("
411 << J.NodeNum << ")\n"
412 << " Fusion may force SU(" << JLoad->NodeNum
413 << ") to complete its load before dispatching SU("
414 << ILoad->NodeNum << ")\n");
415 return true;
416 }
417 }
418 }
419 return false;
420}
421
422namespace {
423/// Adapts design from MacroFusion
424/// Puts valid candidate instructions back-to-back so they can easily
425/// be turned into VOPD instructions
426/// Greedily pairs instruction candidates. O(n^2) algorithm.
427struct VOPDPairingMutation : ScheduleDAGMutation {
428 MacroFusionPredTy shouldScheduleAdjacent; // NOLINT: function pointer
429
430 VOPDPairingMutation(
431 MacroFusionPredTy shouldScheduleAdjacent) // NOLINT: function pointer
433
434 void apply(ScheduleDAGInstrs *DAG) override {
435 const TargetInstrInfo &TII = *DAG->TII;
436 const GCNSubtarget &ST = DAG->MF.getSubtarget<GCNSubtarget>();
437 if (!AMDGPU::hasVOPD(ST) || !ST.isWave32()) {
438 LLVM_DEBUG(dbgs() << "Target does not support VOPDPairingMutation\n");
439 return;
440 }
441
442 BitVector VOPDCapable(DAG->SUnits.size());
443 unsigned IIdx = 0;
444 // Pre-compute whether each individual instruction can be VOPD
445 for (auto ISUI = DAG->SUnits.begin(), E = DAG->SUnits.end(); ISUI != E;
446 ++ISUI, ++IIdx) {
447 const MachineInstr *IMI = ISUI->getInstr();
448 if (shouldScheduleAdjacent(TII, ST, nullptr, *IMI, nullptr) &&
449 hasLessThanNumFused(*ISUI, 2))
450 VOPDCapable[IIdx] = true;
451 }
452
453 IIdx = 0;
454 SmallPtrSet<SUnit *, 8> ILoadSuccs;
455
456 // Cache collected load predecessors.
457 // For VOPDCapable nodes, this caches collectLoads with StopAtLoads=true
458 // For loads, this caches collectLoads with StopAtLoads=false
459 BitVector LoadPredsComputed(DAG->SUnits.size());
460 SmallVector<SmallPtrSet<SUnit *, 8>> LoadPredsCache(DAG->SUnits.size());
461
462 BitVector Scratch(DAG->SUnits.size());
463 for (auto ISUI = DAG->SUnits.begin(), E = DAG->SUnits.end(); ISUI != E;
464 ++ISUI, ++IIdx) {
465 if (!VOPDCapable[IIdx])
466 continue;
467 const MachineInstr *IMI = ISUI->getInstr();
468
469 ILoadSuccs.clear();
470 collectLoads(ILoadSuccs, Scratch, *ISUI, /*Forward=*/true,
471 /*StopAtLoads=*/true);
472
473 unsigned JIdx = IIdx + 1;
474 for (auto JSUI = ISUI + 1; JSUI != E; ++JSUI, ++JIdx) {
475 if (!VOPDCapable[JIdx] || JSUI->isBoundaryNode())
476 continue;
477 const MachineInstr *JMI = JSUI->getInstr();
478 if (!hasLessThanNumFused(*JSUI, 2) ||
479 !shouldScheduleAdjacent(TII, ST, IMI, *JMI, nullptr))
480 continue;
481
482 if (loadsMayOverlap(*ISUI, ILoadSuccs, *JSUI, LoadPredsComputed,
483 LoadPredsCache, Scratch))
484 continue;
485
486 if (fuseInstructionPair(*DAG, *ISUI, *JSUI)) {
487 // Clear to prevent future checks/fusing
488 VOPDCapable[JIdx] = false;
489 break;
490 }
491 }
492 }
493 LLVM_DEBUG(dbgs() << "Completed VOPDPairingMutation\n");
494 }
495};
496} // namespace
497
498std::unique_ptr<ScheduleDAGMutation> llvm::createVOPDPairingMutation() {
499 return std::make_unique<VOPDPairingMutation>(shouldScheduleVOPDAdjacent);
500}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI, const SDep *Dep)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
Base class for AMDGPU specific classes of TargetSubtarget.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
AMD GCN specific subclass of TargetSubtarget.
static const MachineOperand & getNamedOp(const MachineInstr &MI, AMDGPU::OpName Name)
static void collectLoads(SmallPtrSet< SUnit *, 8 > &Loads, BitVector &Visited, SUnit &Head, bool Forward, bool StopAtLoads)
Collect all load (dependents if Forward else dependencies) that connect to the Head SU.
static bool canMapVOP3PToVOPD(const MachineInstr &MI)
static std::optional< VOPDMatchInfo > tryMatchVOPDPairVariant(const SIInstrInfo &TII, unsigned EncodingFamily, MachineInstr &FirstMI, MachineInstr &SecondMI, bool IsVOPD3)
Core pair-eligibility check for a single VOPD encoding variant (VOPD or VOPD3).
static bool loadsMayOverlap(SUnit &I, const SmallPtrSet< SUnit *, 8 > &ILoadSuccs, SUnit &J, BitVector &LoadPredsComputed, SmallVector< SmallPtrSet< SUnit *, 8 > > &LoadPredsCache, BitVector &Scratch)
Checks whether fusing SU I with SU J would force the loads preceding J to complete before loads depen...
static bool shouldScheduleVOPDAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI, const SDep *)
Check if the instr pair, FirstMI and SecondMI, should be scheduled together.
static bool isValidVOPDSrc(const SIInstrInfo &TII, int VOPDOpc, unsigned CompIdx, unsigned SrcIdx, Register PhysSrcReg)
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool isReg(const MCInst &MI, unsigned OpNo)
Interface definition for SIInstrInfo.
This file defines the SmallVector class.
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool test(unsigned Idx) const
Returns true if bit Idx is set.
Definition BitVector.h:482
BitVector & reset()
Reset all bits in the bitvector.
Definition BitVector.h:409
BitVector & set()
Set all bits in the bitvector.
Definition BitVector.h:366
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 mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
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.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Scheduling dependency.
Definition ScheduleDAG.h:52
@ Data
Regular data dependence (aka true-dependence).
Definition ScheduleDAG.h:56
const GCNSubtarget & getSubtarget() const
Scheduling unit. This is a node in the scheduling DAG.
bool isInstr() const
Returns true if this SUnit refers to a machine instruction as opposed to an SDNode.
unsigned NodeNum
Entry # of node in the node vector.
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
const TargetInstrInfo * TII
Target instruction information.
std::vector< SUnit > SUnits
The scheduling units.
MachineFunction & MF
Machine function.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
size_type size() const
Definition SmallSet.h:171
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned getVOPDOpcode(unsigned Opc, bool VOPD3)
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)
int getVOPDFull(unsigned OpX, unsigned OpY, unsigned EncodingFamily, bool VOPD3)
void apply(Opt *O, const Mod &M, const Mods &... Ms)
This is an optimization pass for GlobalISel generic memory operations.
std::unique_ptr< ScheduleDAGMutation > createVOPDPairingMutation()
LLVM_ABI bool fuseInstructionPair(ScheduleDAGInstrs &DAG, SUnit &FirstSU, SUnit &SecondSU)
Create an artificial edge between FirstSU and SecondSU.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool checkVOPDRegConstraints(const SIInstrInfo &TII, const MachineInstr &FirstMI, const MachineInstr &SecondMI, bool IsVOPD3, bool AllowSameVGPR)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DWARFExpression::Operation Op
std::optional< VOPDMatchInfo > tryMatchVOPDPair(const SIInstrInfo &TII, MachineInstr &FirstMI, MachineInstr &SecondMI)
Check whether FirstMI and SecondMI can be combined into a VOPD instruction.
bool(*)(const TargetInstrInfo &TII, const TargetSubtargetInfo &STI, const MachineInstr *FirstMI, const MachineInstr &SecondMI, const SDep *Dep) MacroFusionPredTy
Check if the instr pair, FirstMI and SecondMI, should be fused together, based on the dependency betw...
Definition MacroFusion.h:35
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.
Describes a matched VOPD pair: which instruction is the X component and which is the Y component,...