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