72#include "llvm/Config/llvm-config.h"
101#define DEBUG_TYPE "pipeliner"
103STATISTIC(NumTrytoPipeline,
"Number of loops that we attempt to pipeline");
104STATISTIC(NumPipelined,
"Number of loops software pipelined");
105STATISTIC(NumNodeOrderIssues,
"Number of node order issues found");
106STATISTIC(NumFailBranch,
"Pipeliner abort due to unknown branch");
107STATISTIC(NumFailLoop,
"Pipeliner abort due to unsupported loop");
108STATISTIC(NumFailPreheader,
"Pipeliner abort due to missing preheader");
109STATISTIC(NumFailLargeMaxMII,
"Pipeliner abort due to MaxMII too large");
110STATISTIC(NumFailZeroMII,
"Pipeliner abort due to zero MII");
111STATISTIC(NumFailNoSchedule,
"Pipeliner abort due to no schedule found");
112STATISTIC(NumFailZeroStage,
"Pipeliner abort due to zero stage");
113STATISTIC(NumFailLargeMaxStage,
"Pipeliner abort due to too many stages");
114STATISTIC(NumFailTooManyStores,
"Pipeliner abort due to too many stores");
118 cl::desc(
"Enable Software Pipelining"));
127 cl::desc(
"Size limit for the MII."),
133 cl::desc(
"Force pipeliner to use specified II."),
139 cl::desc(
"Maximum stages allowed in the generated scheduled."),
146 cl::desc(
"Prune dependences between unrelated Phi nodes."),
153 cl::desc(
"Prune loop carried order dependences."),
171 cl::desc(
"Instead of emitting the pipelined code, annotate instructions "
172 "with the generated schedule for feeding into the "
173 "-modulo-schedule-test pass"));
178 "Use the experimental peeling code generator for software pipelining"));
186 cl::desc(
"Limit register pressure of scheduled loop"));
191 cl::desc(
"Margin representing the unused percentage of "
192 "the register pressure limit"));
196 cl::desc(
"Use the MVE code generator for software pipelining"));
201 "pipeliner-max-num-stores",
209 cl::desc(
"Enable CopyToPhi DAG Mutation"));
214 "pipeliner-force-issue-width",
221 cl::desc(
"Set how to use window scheduling algorithm."),
223 "Turn off window algorithm."),
225 "Use window algorithm after SMS algorithm fails."),
227 "Use window algorithm instead of SMS algorithm.")));
229unsigned SwingSchedulerDAG::Circuits::MaxPaths = 5;
237 "Modulo Software Pipelining",
false,
false)
280 enum class InstrTag {
289 TaggedSUnit(
SUnit *SU, InstrTag Tag)
292 InstrTag
getTag()
const {
return InstrTag(getInt()); }
297 struct NoBarrierInstsChunk {
302 void append(
SUnit *SU);
307 std::vector<SUnit> &SUnits;
313 std::vector<BitVector> LoopCarried;
326 std::vector<TaggedSUnit> TaggedSUnits;
340 return LoopCarried[Idx];
345 std::optional<InstrTag> getInstrTag(
SUnit *SU)
const;
347 void addLoopCarriedDepenenciesForChunks(
const NoBarrierInstsChunk &From,
348 const NoBarrierInstsChunk &To);
355 void computeDependenciesAux();
357 void setLoopCarriedDep(
const SUnit *Src,
const SUnit *Dst) {
358 LoopCarried[Src->NodeNum].set(Dst->NodeNum);
391 TII =
MF->getSubtarget().getInstrInfo();
393 for (
const auto &L : *
MLI)
403bool MachinePipeliner::scheduleLoop(
MachineLoop &L) {
405 for (
const auto &InnerLoop : L)
406 Changed |= scheduleLoop(*InnerLoop);
418 setPragmaPipelineOptions(L);
419 if (!canPipelineLoop(L)) {
423 L.getStartLoc(), L.getHeader())
424 <<
"Failed to pipeline loop";
427 LI.LoopPipelinerInfo.reset();
432 if (useSwingModuloScheduler())
433 Changed = swingModuloScheduler(L);
435 if (useWindowScheduler(
Changed))
436 Changed = runWindowScheduler(L);
438 LI.LoopPipelinerInfo.reset();
442void MachinePipeliner::setPragmaPipelineOptions(
MachineLoop &L) {
447 MachineBasicBlock *LBLK =
L.getTopBlock();
460 MDNode *LoopID = TI->
getMetadata(LLVMContext::MD_loop);
461 if (LoopID ==
nullptr)
478 if (S->
getString() ==
"llvm.loop.pipeline.initiationinterval") {
480 "Pipeline initiation interval hint metadata should have two operands.");
484 }
else if (S->
getString() ==
"llvm.loop.pipeline.disable") {
497 auto It = PhiDeps.find(
Reg);
498 if (It == PhiDeps.end())
509 for (
unsigned Dep : It->second) {
524 unsigned DefReg =
MI.getOperand(0).getReg();
528 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2)
529 Ins->second.push_back(
MI.getOperand(
I).getReg());
536 for (
const auto &KV : PhiDeps) {
537 unsigned Reg = KV.first;
548bool MachinePipeliner::canPipelineLoop(
MachineLoop &L) {
549 if (
L.getNumBlocks() != 1) {
551 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
552 L.getStartLoc(),
L.getHeader())
553 <<
"Not a single basic block: "
554 <<
ore::NV(
"NumBlocks",
L.getNumBlocks());
566 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
567 L.getStartLoc(),
L.getHeader())
568 <<
"Disabled by Pragma.";
578 if (
TII->analyzeBranch(*
L.getHeader(),
LI.TBB,
LI.FBB,
LI.BrCond)) {
579 LLVM_DEBUG(
dbgs() <<
"Unable to analyzeBranch, can NOT pipeline Loop\n");
582 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
583 L.getStartLoc(),
L.getHeader())
584 <<
"The branch can't be understood";
589 LI.LoopInductionVar =
nullptr;
590 LI.LoopCompare =
nullptr;
591 LI.LoopPipelinerInfo =
TII->analyzeLoopForPipelining(
L.getTopBlock());
592 if (!
LI.LoopPipelinerInfo) {
593 LLVM_DEBUG(
dbgs() <<
"Unable to analyzeLoop, can NOT pipeline Loop\n");
596 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
597 L.getStartLoc(),
L.getHeader())
598 <<
"The loop structure is not supported";
603 if (!
L.getLoopPreheader()) {
604 LLVM_DEBUG(
dbgs() <<
"Preheader not found, can NOT pipeline Loop\n");
607 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
608 L.getStartLoc(),
L.getHeader())
609 <<
"No loop preheader found";
614 unsigned NumStores = 0;
615 for (MachineInstr &
MI : *
L.getHeader())
620 NumFailTooManyStores++;
622 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
623 L.getStartLoc(),
L.getHeader())
624 <<
"Too many store instructions in the loop: "
625 <<
ore::NV(
"NumStores", NumStores) <<
" > "
632 preprocessPhiNodes(*
L.getHeader());
637 MachineRegisterInfo &MRI =
MF->getRegInfo();
641 for (MachineInstr &PI :
B.phis()) {
642 MachineOperand &DefOp = PI.getOperand(0);
646 for (
unsigned i = 1, n = PI.getNumOperands(); i != n; i += 2) {
647 MachineOperand &RegOp = PI.getOperand(i);
654 MachineBasicBlock &PredB = *PI.getOperand(i+1).getMBB();
671bool MachinePipeliner::swingModuloScheduler(
MachineLoop &L) {
672 assert(
L.getBlocks().size() == 1 &&
"SMS works on single blocks only.");
675 SwingSchedulerDAG SMS(
679 MachineBasicBlock *
MBB =
L.getHeader();
697 return SMS.hasNewSchedule();
713bool MachinePipeliner::runWindowScheduler(
MachineLoop &L) {
721 Context.RegClassInfo =
727bool MachinePipeliner::useSwingModuloScheduler() {
732bool MachinePipeliner::useWindowScheduler(
bool Changed) {
739 "llvm.loop.pipeline.initiationinterval is set.\n");
747void SwingSchedulerDAG::setMII(
unsigned ResMII,
unsigned RecMII) {
750 else if (II_setByPragma > 0)
751 MII = II_setByPragma;
753 MII = std::max(ResMII, RecMII);
756void SwingSchedulerDAG::setMAX_II() {
759 else if (II_setByPragma > 0)
760 MAX_II = II_setByPragma;
770 updatePhiDependences();
771 Topo.InitDAGTopologicalSorting();
777 dbgs() <<
"===== Loop Carried Edges Begin =====\n";
780 dbgs() <<
"===== Loop Carried Edges End =====\n";
783 NodeSetType NodeSets;
784 findCircuits(NodeSets);
785 NodeSetType Circuits = NodeSets;
788 unsigned ResMII = calculateResMII();
789 unsigned RecMII = calculateRecMII(NodeSets);
797 setMII(ResMII, RecMII);
801 <<
" (rec=" << RecMII <<
", res=" << ResMII <<
")\n");
807 Pass.ORE->emit([&]() {
809 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
810 <<
"Invalid Minimal Initiation Interval: 0";
818 <<
", we don't pipeline large loops\n");
819 NumFailLargeMaxMII++;
820 Pass.ORE->emit([&]() {
822 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
823 <<
"Minimal Initiation Interval too large: "
824 <<
ore::NV(
"MII", (
int)MII) <<
" > "
826 <<
"Refer to -pipeliner-max-mii.";
831 computeNodeFunctions(NodeSets);
833 registerPressureFilter(NodeSets);
835 colocateNodeSets(NodeSets);
837 checkNodeSets(NodeSets);
840 for (
auto &
I : NodeSets) {
841 dbgs() <<
" Rec NodeSet ";
848 groupRemainingNodes(NodeSets);
850 removeDuplicateNodes(NodeSets);
853 for (
auto &
I : NodeSets) {
854 dbgs() <<
" NodeSet ";
859 computeNodeOrder(NodeSets);
862 checkValidNodeOrder(Circuits);
865 Scheduled = schedulePipeline(Schedule);
870 Pass.ORE->emit([&]() {
872 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
873 <<
"Unable to find schedule";
880 if (numStages == 0) {
883 Pass.ORE->emit([&]() {
885 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
886 <<
"No need to pipeline - no overlapped iterations in schedule.";
893 <<
" : too many stages, abort\n");
894 NumFailLargeMaxStage++;
895 Pass.ORE->emit([&]() {
897 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
898 <<
"Too many stages in schedule: "
899 <<
ore::NV(
"numStages", (
int)numStages) <<
" > "
901 <<
". Refer to -pipeliner-max-stages.";
906 Pass.ORE->emit([&]() {
909 <<
"Pipelined succesfully!";
914 std::vector<MachineInstr *> OrderedInsts;
918 OrderedInsts.push_back(SU->getInstr());
919 Cycles[SU->getInstr()] = Cycle;
924 for (
auto &KV : NewMIs) {
925 Cycles[KV.first] = Cycles[KV.second];
926 Stages[KV.first] = Stages[KV.second];
927 NewInstrChanges[KV.first] = InstrChanges[
getSUnit(KV.first)];
934 "Cannot serialize a schedule with InstrChanges!");
944 LoopPipelinerInfo->isMVEExpanderSupported() &&
958 for (
auto &KV : NewMIs)
959 MF.deleteMachineInstr(KV.second);
970 assert(Phi.isPHI() &&
"Expecting a Phi.");
974 for (
unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
975 if (Phi.getOperand(i + 1).getMBB() !=
Loop)
976 InitVal = Phi.getOperand(i).getReg();
978 LoopVal = Phi.getOperand(i).getReg();
980 assert(InitVal && LoopVal &&
"Unexpected Phi structure.");
986 for (
unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
987 if (Phi.getOperand(i + 1).getMBB() == LoopBB)
988 return Phi.getOperand(i).getReg();
997 while (!Worklist.
empty()) {
999 for (
const auto &
SI : SU->
Succs) {
1000 SUnit *SuccSU =
SI.getSUnit();
1002 if (Visited.
count(SuccSU))
1015 if (!getUnderlyingObjects())
1040bool SUnitWithMemInfo::getUnderlyingObjects() {
1042 if (!
MI->hasOneMemOperand())
1060 const SUnitWithMemInfo &Dst,
1065 if (Src.isTriviallyDisjoint(Dst))
1079 if (Src.isUnknown() || Dst.isUnknown())
1081 if (Src.MemOpValue == Dst.MemOpValue && Src.MemOpOffset <= Dst.MemOpOffset)
1092 for (
const Value *SrcObj : Src.UnderlyingObjs)
1093 for (
const Value *DstObj : Dst.UnderlyingObjs)
1101void LoopCarriedOrderDepsTracker::NoBarrierInstsChunk::append(SUnit *SU) {
1104 Stores.emplace_back(SU);
1105 else if (
MI->mayLoad())
1106 Loads.emplace_back(SU);
1107 else if (
MI->mayRaiseFPException())
1108 FPExceptions.emplace_back(SU);
1116 : DAG(SSD), BAA(BAA), SUnits(DAG->SUnits), N(SUnits.
size()),
1117 LoopCarried(N,
BitVector(N)), TII(TII), TRI(TRI) {}
1121 for (
auto &SU : SUnits) {
1122 auto Tagged = getInstrTag(&SU);
1127 TaggedSUnits.emplace_back(&SU, *Tagged);
1130 computeDependenciesAux();
1133std::optional<LoopCarriedOrderDepsTracker::InstrTag>
1134LoopCarriedOrderDepsTracker::getInstrTag(
SUnit *SU)
const {
1136 if (
TII->isGlobalMemoryObject(
MI))
1137 return InstrTag::Barrier;
1139 if (
MI->mayStore() ||
1140 (
MI->mayLoad() && !
MI->isDereferenceableInvariantLoad()))
1141 return InstrTag::LoadOrStore;
1143 if (
MI->mayRaiseFPException())
1144 return InstrTag::FPExceptions;
1146 return std::nullopt;
1149void LoopCarriedOrderDepsTracker::addDependenciesBetweenSUs(
1150 const SUnitWithMemInfo &Src,
const SUnitWithMemInfo &Dst) {
1152 if (Src.SU == Dst.SU)
1156 setLoopCarriedDep(Src.SU, Dst.SU);
1159void LoopCarriedOrderDepsTracker::addLoopCarriedDepenenciesForChunks(
1160 const NoBarrierInstsChunk &From,
const NoBarrierInstsChunk &To) {
1162 for (
const SUnitWithMemInfo &Src : From.Loads)
1163 for (
const SUnitWithMemInfo &Dst : To.Stores)
1164 addDependenciesBetweenSUs(Src, Dst);
1167 for (
const SUnitWithMemInfo &Src : From.Stores)
1168 for (
const SUnitWithMemInfo &Dst : To.Loads)
1169 addDependenciesBetweenSUs(Src, Dst);
1172 for (
const SUnitWithMemInfo &Src : From.Stores)
1173 for (
const SUnitWithMemInfo &Dst : To.Stores)
1174 addDependenciesBetweenSUs(Src, Dst);
1177void LoopCarriedOrderDepsTracker::computeDependenciesAux() {
1179 SUnit *FirstBarrier =
nullptr;
1180 SUnit *LastBarrier =
nullptr;
1181 for (
const auto &TSU : TaggedSUnits) {
1182 InstrTag
Tag = TSU.getTag();
1183 SUnit *SU = TSU.getPointer();
1185 case InstrTag::Barrier:
1189 Chunks.emplace_back();
1191 case InstrTag::LoadOrStore:
1192 case InstrTag::FPExceptions:
1193 Chunks.back().append(SU);
1201 for (
const NoBarrierInstsChunk &Chunk : Chunks)
1202 addLoopCarriedDepenenciesForChunks(Chunk, Chunk);
1231 assert(LastBarrier &&
"Both barriers should be set.");
1234 for (
const SUnitWithMemInfo &Dst : Chunks.front().Loads)
1235 setLoopCarriedDep(LastBarrier, Dst.SU);
1236 for (
const SUnitWithMemInfo &Dst : Chunks.front().Stores)
1237 setLoopCarriedDep(LastBarrier, Dst.SU);
1238 for (
const SUnitWithMemInfo &Dst : Chunks.front().FPExceptions)
1239 setLoopCarriedDep(LastBarrier, Dst.SU);
1242 for (
const SUnitWithMemInfo &Src : Chunks.back().Loads)
1243 setLoopCarriedDep(Src.SU, FirstBarrier);
1244 for (
const SUnitWithMemInfo &Src : Chunks.back().Stores)
1245 setLoopCarriedDep(Src.SU, FirstBarrier);
1246 for (
const SUnitWithMemInfo &Src : Chunks.back().FPExceptions)
1247 setLoopCarriedDep(Src.SU, FirstBarrier);
1250 if (FirstBarrier != LastBarrier)
1251 setLoopCarriedDep(LastBarrier, FirstBarrier);
1260LoopCarriedEdges SwingSchedulerDAG::addLoopCarriedDependences() {
1261 LoopCarriedEdges LCE;
1265 LCODTracker.computeDependencies();
1266 for (
unsigned I = 0;
I != SUnits.size();
I++)
1267 for (
const int Succ : LCODTracker.getLoopCarried(
I).set_bits())
1280void SwingSchedulerDAG::updatePhiDependences() {
1282 const TargetSubtargetInfo &
ST = MF.getSubtarget<TargetSubtargetInfo>();
1285 for (SUnit &
I : SUnits) {
1290 MachineInstr *
MI =
I.getInstr();
1292 for (
const MachineOperand &MO :
MI->operands()) {
1302 MachineInstr *
UseMI = &*UI;
1303 SUnit *SU = getSUnit(
UseMI);
1329 }
else if (MO.isUse()) {
1332 if (
DefMI ==
nullptr)
1334 SUnit *SU = getSUnit(
DefMI);
1339 ST.adjustSchedDependency(SU, 0, &
I, MO.getOperandNo(), Dep,
1346 if (SU->
NodeNum <
I.NodeNum && !
I.isPred(SU))
1355 for (
auto &PI :
I.Preds) {
1356 MachineInstr *PMI = PI.getSUnit()->getInstr();
1358 if (
I.getInstr()->isPHI()) {
1367 for (
const SDep &
D : RemoveDeps)
1374void SwingSchedulerDAG::changeDependences() {
1378 for (SUnit &
I : SUnits) {
1379 unsigned BasePos = 0, OffsetPos = 0;
1381 int64_t NewOffset = 0;
1382 if (!canUseLastOffsetValue(
I.getInstr(), BasePos, OffsetPos, NewBase,
1387 Register OrigBase =
I.getInstr()->getOperand(BasePos).getReg();
1391 SUnit *DefSU = getSUnit(
DefMI);
1398 SUnit *LastSU = getSUnit(LastMI);
1402 if (Topo.IsReachable(&
I, LastSU))
1407 for (
const SDep &
P :
I.Preds)
1408 if (
P.getSUnit() == DefSU)
1410 for (
const SDep &
D : Deps) {
1411 Topo.RemovePred(&
I,
D.getSUnit());
1416 for (
auto &
P : LastSU->
Preds)
1419 for (
const SDep &
D : Deps) {
1420 Topo.RemovePred(LastSU,
D.getSUnit());
1427 Topo.AddPred(LastSU, &
I);
1432 InstrChanges[&
I] = std::make_pair(NewBase, NewOffset);
1443 std::vector<MachineInstr *> &OrderedInsts,
1451 Stage <= LastStage; ++Stage) {
1454 Instrs[Cycle].push_front(SU);
1461 std::deque<SUnit *> &CycleInstrs = Instrs[Cycle];
1463 for (
SUnit *SU : CycleInstrs) {
1465 OrderedInsts.push_back(
MI);
1475struct FuncUnitSorter {
1476 const InstrItineraryData *InstrItins;
1477 const MCSubtargetInfo *STI;
1478 DenseMap<InstrStage::FuncUnits, unsigned>
Resources;
1480 FuncUnitSorter(
const TargetSubtargetInfo &TSI)
1481 : InstrItins(TSI.getInstrItineraryData()), STI(&TSI) {}
1486 unsigned minFuncUnits(
const MachineInstr *Inst,
1489 unsigned min = UINT_MAX;
1490 if (InstrItins && !InstrItins->
isEmpty()) {
1491 for (
const InstrStage &IS :
1493 InstrItins->
endStage(SchedClass))) {
1496 if (numAlternatives <
min) {
1497 min = numAlternatives;
1504 const MCSchedClassDesc *SCDesc =
1511 for (
const MCWriteProcResEntry &PRE :
1514 if (!PRE.ReleaseAtCycle)
1516 const MCProcResourceDesc *ProcResource =
1518 unsigned NumUnits = ProcResource->
NumUnits;
1519 if (NumUnits <
min) {
1521 F = PRE.ProcResourceIdx;
1526 llvm_unreachable(
"Should have non-empty InstrItins or hasInstrSchedModel!");
1534 void calcCriticalResources(MachineInstr &
MI) {
1535 unsigned SchedClass =
MI.getDesc().getSchedClass();
1536 if (InstrItins && !InstrItins->
isEmpty()) {
1537 for (
const InstrStage &IS :
1539 InstrItins->
endStage(SchedClass))) {
1547 const MCSchedClassDesc *SCDesc =
1554 for (
const MCWriteProcResEntry &PRE :
1557 if (!PRE.ReleaseAtCycle)
1563 llvm_unreachable(
"Should have non-empty InstrItins or hasInstrSchedModel!");
1567 bool operator()(
const MachineInstr *IS1,
const MachineInstr *IS2)
const {
1569 unsigned MFUs1 = minFuncUnits(IS1, F1);
1570 unsigned MFUs2 = minFuncUnits(IS2, F2);
1573 return MFUs1 > MFUs2;
1578class HighRegisterPressureDetector {
1579 MachineBasicBlock *OrigMBB;
1580 const MachineRegisterInfo &MRI;
1581 const TargetRegisterInfo *
TRI;
1583 const unsigned PSetNum;
1589 std::vector<unsigned> InitSetPressure;
1593 std::vector<unsigned> PressureSetLimit;
1595 DenseMap<MachineInstr *, RegisterOperands> ROMap;
1597 using Instr2LastUsesTy = DenseMap<MachineInstr *, SmallDenseSet<Register, 4>>;
1600 using OrderedInstsTy = std::vector<MachineInstr *>;
1601 using Instr2StageTy = DenseMap<MachineInstr *, unsigned>;
1604 static void dumpRegisterPressures(
const std::vector<unsigned> &Pressures) {
1605 if (Pressures.size() == 0) {
1609 for (
unsigned P : Pressures) {
1620 VirtRegOrUnit VRegOrUnit =
1622 : VirtRegOrUnit(static_cast<MCRegUnit>(
Reg.id()));
1625 dbgs() << *PSetIter <<
' ';
1630 void increaseRegisterPressure(std::vector<unsigned> &Pressure,
1633 VirtRegOrUnit VRegOrUnit =
1635 : VirtRegOrUnit(static_cast<MCRegUnit>(
Reg.id()));
1638 for (; PSetIter.isValid(); ++PSetIter)
1639 Pressure[*PSetIter] += Weight;
1642 void decreaseRegisterPressure(std::vector<unsigned> &Pressure,
1645 unsigned Weight = PSetIter.getWeight();
1646 for (; PSetIter.isValid(); ++PSetIter) {
1647 auto &
P = Pressure[*PSetIter];
1649 "register pressure must be greater than or equal weight");
1671 void computeLiveIn() {
1672 DenseSet<Register>
Used;
1673 for (
auto &
MI : *OrigMBB) {
1674 if (
MI.isDebugInstr())
1676 for (
auto &Use : ROMap[&
MI].
Uses) {
1679 Use.VRegOrUnit.isVirtualReg()
1680 ?
Use.VRegOrUnit.asVirtualReg()
1681 :
Register(
static_cast<unsigned>(
Use.VRegOrUnit.asMCRegUnit()));
1686 if (isReservedRegister(
Reg))
1688 if (isDefinedInThisLoop(
Reg))
1694 for (
auto LiveIn : Used)
1695 increaseRegisterPressure(InitSetPressure, LiveIn);
1699 void computePressureSetLimit(
const RegisterClassInfo &RCI) {
1700 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1715 Instr2LastUsesTy computeLastUses(
const OrderedInstsTy &OrderedInsts,
1716 Instr2StageTy &Stages)
const {
1721 DenseSet<Register> TargetRegs;
1722 const auto UpdateTargetRegs = [
this, &TargetRegs](
Register Reg) {
1723 if (isDefinedInThisLoop(
Reg))
1726 for (MachineInstr *
MI : OrderedInsts) {
1729 UpdateTargetRegs(
Reg);
1731 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses) {
1734 ?
Use.VRegOrUnit.asVirtualReg()
1736 Use.VRegOrUnit.asMCRegUnit()));
1737 UpdateTargetRegs(
Reg);
1742 const auto InstrScore = [&Stages](MachineInstr *
MI) {
1743 return Stages[
MI] +
MI->isPHI();
1746 DenseMap<Register, MachineInstr *> LastUseMI;
1748 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses) {
1751 Use.VRegOrUnit.isVirtualReg()
1752 ?
Use.VRegOrUnit.asVirtualReg()
1753 :
Register(
static_cast<unsigned>(
Use.VRegOrUnit.asMCRegUnit()));
1758 MachineInstr *Orig = Ite->second;
1759 MachineInstr *
New =
MI;
1760 if (InstrScore(Orig) < InstrScore(New))
1766 Instr2LastUsesTy LastUses;
1767 for (
auto [
Reg,
MI] : LastUseMI)
1768 LastUses[
MI].insert(
Reg);
1784 std::vector<unsigned>
1785 computeMaxSetPressure(
const OrderedInstsTy &OrderedInsts,
1786 Instr2StageTy &Stages,
1787 const unsigned StageCount)
const {
1788 using RegSetTy = SmallDenseSet<Register, 16>;
1794 auto CurSetPressure = InitSetPressure;
1795 auto MaxSetPressure = InitSetPressure;
1796 auto LastUses = computeLastUses(OrderedInsts, Stages);
1799 dbgs() <<
"Ordered instructions:\n";
1800 for (MachineInstr *
MI : OrderedInsts) {
1801 dbgs() <<
"Stage " << Stages[
MI] <<
": ";
1806 const auto InsertReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1807 VirtRegOrUnit VRegOrUnit) {
1821 increaseRegisterPressure(CurSetPressure,
Reg);
1825 const auto EraseReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1831 if (!RegSet.contains(
Reg))
1836 decreaseRegisterPressure(CurSetPressure,
Reg);
1840 for (
unsigned I = 0;
I < StageCount;
I++) {
1841 for (MachineInstr *
MI : OrderedInsts) {
1842 const auto Stage = Stages[
MI];
1846 const unsigned Iter =
I - Stage;
1848 for (
auto &Def : ROMap.
find(
MI)->getSecond().Defs)
1849 InsertReg(LiveRegSets[Iter],
Def.VRegOrUnit);
1851 for (
auto LastUse : LastUses[
MI]) {
1854 EraseReg(LiveRegSets[Iter - 1], LastUse);
1856 EraseReg(LiveRegSets[Iter], LastUse);
1860 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1861 MaxSetPressure[PSet] =
1862 std::max(MaxSetPressure[PSet], CurSetPressure[PSet]);
1865 dbgs() <<
"CurSetPressure=";
1866 dumpRegisterPressures(CurSetPressure);
1867 dbgs() <<
" iter=" << Iter <<
" stage=" << Stage <<
":";
1873 return MaxSetPressure;
1877 HighRegisterPressureDetector(MachineBasicBlock *OrigMBB,
1878 const MachineFunction &MF)
1879 : OrigMBB(OrigMBB), MRI(MF.getRegInfo()),
1880 TRI(MF.getSubtarget().getRegisterInfo()),
1881 PSetNum(
TRI->getNumRegPressureSets()), InitSetPressure(PSetNum, 0),
1882 PressureSetLimit(PSetNum, 0) {}
1886 void init(
const RegisterClassInfo &RCI) {
1887 for (MachineInstr &
MI : *OrigMBB) {
1888 if (
MI.isDebugInstr())
1890 ROMap[&
MI].collect(
MI, *
TRI, MRI,
false,
true);
1894 computePressureSetLimit(RCI);
1899 bool detect(
const SwingSchedulerDAG *SSD, SMSchedule &Schedule,
1900 const unsigned MaxStage)
const {
1902 "the percentage of the margin must be between 0 to 100");
1904 OrderedInstsTy OrderedInsts;
1905 Instr2StageTy Stages;
1907 const auto MaxSetPressure =
1908 computeMaxSetPressure(OrderedInsts, Stages, MaxStage + 1);
1911 dbgs() <<
"Dump MaxSetPressure:\n";
1912 for (
unsigned I = 0;
I < MaxSetPressure.size();
I++) {
1913 dbgs() <<
format(
"MaxSetPressure[%d]=%d\n",
I, MaxSetPressure[
I]);
1918 for (
unsigned PSet = 0; PSet < PSetNum; PSet++) {
1919 unsigned Limit = PressureSetLimit[PSet];
1922 <<
" Margin=" << Margin <<
"\n");
1923 if (Limit < MaxSetPressure[PSet] + Margin) {
1926 <<
"Rejected the schedule because of too high register pressure\n");
1942unsigned SwingSchedulerDAG::calculateResMII() {
1944 ResourceManager
RM(&MF.getSubtarget(),
this);
1945 return RM.calculateResMII();
1954unsigned SwingSchedulerDAG::calculateRecMII(NodeSetType &NodeSets) {
1955 unsigned RecMII = 0;
1957 for (NodeSet &Nodes : NodeSets) {
1961 unsigned Delay = Nodes.getLatency();
1962 unsigned Distance = 1;
1965 unsigned CurMII = (Delay + Distance - 1) / Distance;
1966 Nodes.setRecMII(CurMII);
1967 if (CurMII > RecMII)
1975void SwingSchedulerDAG::Circuits::createAdjacencyStructure(
1976 SwingSchedulerDDG *DDG) {
1977 BitVector
Added(SUnits.size());
1978 DenseMap<int, int> OutputDeps;
1979 for (
int i = 0, e = SUnits.size(); i != e; ++i) {
1985 if (OE.isOutputDep()) {
1986 int N = OE.getDst()->NodeNum;
1988 auto Dep = OutputDeps.
find(BackEdge);
1989 if (Dep != OutputDeps.
end()) {
1990 BackEdge = Dep->second;
1991 OutputDeps.
erase(Dep);
1993 OutputDeps[
N] = BackEdge;
1996 if (OE.getDst()->isBoundaryNode() || OE.isArtificial())
2008 int N = OE.getDst()->NodeNum;
2010 AdjK[i].push_back(
N);
2017 int N = Dst->NodeNum;
2019 AdjK[i].push_back(
N);
2026 for (
auto &OD : OutputDeps)
2027 if (!
Added.test(OD.second)) {
2028 AdjK[OD.first].push_back(OD.second);
2029 Added.set(OD.second);
2035bool SwingSchedulerDAG::Circuits::circuit(
int V,
int S, NodeSetType &NodeSets,
2036 const SwingSchedulerDAG *DAG,
2038 SUnit *SV = &SUnits[
V];
2043 for (
auto W : AdjK[V]) {
2044 if (NumPaths > MaxPaths)
2055 if (!Blocked.test(W)) {
2056 if (circuit(W, S, NodeSets, DAG,
2057 Node2Idx->at(W) < Node2Idx->at(V) ?
true : HasBackedge))
2065 for (
auto W : AdjK[V]) {
2076void SwingSchedulerDAG::Circuits::unblock(
int U) {
2078 SmallPtrSet<SUnit *, 4> &BU =
B[
U];
2079 while (!BU.
empty()) {
2080 SmallPtrSet<SUnit *, 4>::iterator
SI = BU.
begin();
2081 assert(SI != BU.
end() &&
"Invalid B set.");
2084 if (Blocked.test(
W->NodeNum))
2085 unblock(
W->NodeNum);
2091void SwingSchedulerDAG::findCircuits(NodeSetType &NodeSets) {
2092 Circuits Cir(SUnits, Topo);
2094 Cir.createAdjacencyStructure(&*DDG);
2095 for (
int I = 0,
E = SUnits.size();
I !=
E; ++
I) {
2097 Cir.circuit(
I,
I, NodeSets,
this);
2119void SwingSchedulerDAG::CopyToPhiMutation::apply(ScheduleDAGInstrs *DAG) {
2120 for (SUnit &SU : DAG->
SUnits) {
2130 for (
auto &Dep : SU.
Preds) {
2131 SUnit *TmpSU = Dep.getSUnit();
2132 MachineInstr *TmpMI = TmpSU->
getInstr();
2143 if (PHISUs.
size() == 0 || SrcSUs.
size() == 0)
2151 for (
auto &Dep : PHISUs[Index]->Succs) {
2155 SUnit *TmpSU = Dep.getSUnit();
2156 MachineInstr *TmpMI = TmpSU->
getInstr();
2165 if (UseSUs.
size() == 0)
2170 for (
auto *
I : UseSUs) {
2171 for (
auto *Src : SrcSUs) {
2187void SwingSchedulerDAG::computeNodeFunctions(NodeSetType &NodeSets) {
2188 ScheduleInfo.resize(SUnits.size());
2191 for (
int I : Topo) {
2192 const SUnit &SU = SUnits[
I];
2199 for (
int I : Topo) {
2201 int zeroLatencyDepth = 0;
2202 SUnit *SU = &SUnits[
I];
2204 SUnit *Pred =
IE.getSrc();
2205 if (
IE.getLatency() == 0)
2207 std::max(zeroLatencyDepth, getZeroLatencyDepth(Pred) + 1);
2208 if (
IE.ignoreDependence(
true))
2210 asap = std::max(asap, (
int)(getASAP(Pred) +
IE.getLatency() -
2211 IE.getDistance() * MII));
2213 maxASAP = std::max(maxASAP, asap);
2214 ScheduleInfo[
I].ASAP = asap;
2215 ScheduleInfo[
I].ZeroLatencyDepth = zeroLatencyDepth;
2221 int zeroLatencyHeight = 0;
2222 SUnit *SU = &SUnits[
I];
2224 SUnit *Succ = OE.getDst();
2227 if (OE.getLatency() == 0)
2229 std::max(zeroLatencyHeight, getZeroLatencyHeight(Succ) + 1);
2230 if (OE.ignoreDependence(
true))
2232 alap = std::min(alap, (
int)(getALAP(Succ) - OE.getLatency() +
2233 OE.getDistance() * MII));
2236 ScheduleInfo[
I].ALAP = alap;
2237 ScheduleInfo[
I].ZeroLatencyHeight = zeroLatencyHeight;
2241 for (NodeSet &
I : NodeSets)
2242 I.computeNodeSetInfo(
this);
2245 for (
unsigned i = 0; i < SUnits.size(); i++) {
2246 dbgs() <<
"\tNode " << i <<
":\n";
2247 dbgs() <<
"\t ASAP = " << getASAP(&SUnits[i]) <<
"\n";
2248 dbgs() <<
"\t ALAP = " << getALAP(&SUnits[i]) <<
"\n";
2249 dbgs() <<
"\t MOV = " << getMOV(&SUnits[i]) <<
"\n";
2250 dbgs() <<
"\t D = " << getDepth(&SUnits[i]) <<
"\n";
2251 dbgs() <<
"\t H = " << getHeight(&SUnits[i]) <<
"\n";
2252 dbgs() <<
"\t ZLD = " << getZeroLatencyDepth(&SUnits[i]) <<
"\n";
2253 dbgs() <<
"\t ZLH = " << getZeroLatencyHeight(&SUnits[i]) <<
"\n";
2268 SUnit *PredSU = IE.getSrc();
2269 if (S && S->count(PredSU) == 0)
2271 if (IE.ignoreDependence(
true))
2282 SUnit *SuccSU = OE.getDst();
2283 if (!OE.isAntiDep())
2285 if (S && S->count(SuccSU) == 0)
2291 return !Preds.
empty();
2304 SUnit *SuccSU = OE.getDst();
2305 if (S && S->count(SuccSU) == 0)
2307 if (OE.ignoreDependence(
false))
2318 SUnit *PredSU = IE.getSrc();
2319 if (!IE.isAntiDep())
2321 if (S && S->count(PredSU) == 0)
2327 return !Succs.
empty();
2343 if (!Visited.
insert(Cur).second)
2344 return Path.contains(Cur);
2345 bool FoundPath =
false;
2347 if (!OE.ignoreDependence(
false))
2349 computePath(OE.getDst(), Path, DestNodes, Exclude, Visited, DDG);
2351 if (IE.isAntiDep() && IE.getDistance() == 0)
2353 computePath(IE.getSrc(), Path, DestNodes, Exclude, Visited, DDG);
2368 for (
SUnit *SU : NS) {
2374 if (
Reg.isVirtual())
2377 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2381 for (
SUnit *SU : NS)
2385 if (
Reg.isVirtual()) {
2390 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2401void SwingSchedulerDAG::registerPressureFilter(NodeSetType &NodeSets) {
2402 for (
auto &NS : NodeSets) {
2406 IntervalPressure RecRegPressure;
2407 RegPressureTracker RecRPTracker(RecRegPressure);
2408 RecRPTracker.init(&MF, &RegClassInfo, &LIS, BB, BB->end(),
false,
true);
2410 RecRPTracker.closeBottom();
2412 std::vector<SUnit *> SUnits(NS.begin(), NS.end());
2413 llvm::sort(SUnits, [](
const SUnit *
A,
const SUnit *
B) {
2414 return A->NodeNum >
B->NodeNum;
2417 for (
auto &SU : SUnits) {
2423 RecRPTracker.setPos(std::next(CurInstI));
2425 RegPressureDelta RPDelta;
2427 RecRPTracker.getMaxUpwardPressureDelta(SU->
getInstr(),
nullptr, RPDelta,
2432 dbgs() <<
"Excess register pressure: SU(" << SU->
NodeNum <<
") "
2435 NS.setExceedPressure(SU);
2438 RecRPTracker.recede();
2445void SwingSchedulerDAG::colocateNodeSets(NodeSetType &NodeSets) {
2446 unsigned Colocate = 0;
2447 for (
int i = 0, e = NodeSets.size(); i < e; ++i) {
2449 SmallSetVector<SUnit *, 8>
S1;
2452 for (
int j = i + 1;
j <
e; ++
j) {
2456 SmallSetVector<SUnit *, 8> S2;
2473void SwingSchedulerDAG::checkNodeSets(NodeSetType &NodeSets) {
2478 for (
auto &NS : NodeSets) {
2479 if (NS.getRecMII() > 2)
2481 if (NS.getMaxDepth() > MII)
2490void SwingSchedulerDAG::groupRemainingNodes(NodeSetType &NodeSets) {
2491 SetVector<SUnit *> NodesAdded;
2492 SmallPtrSet<SUnit *, 8> Visited;
2495 for (NodeSet &
I : NodeSets) {
2496 SmallSetVector<SUnit *, 8>
N;
2499 SetVector<SUnit *>
Path;
2500 for (SUnit *NI :
N) {
2502 computePath(NI, Path, NodesAdded,
I, Visited, DDG.get());
2509 if (
succ_L(NodesAdded,
N, DDG.get())) {
2510 SetVector<SUnit *>
Path;
2511 for (SUnit *NI :
N) {
2513 computePath(NI, Path,
I, NodesAdded, Visited, DDG.get());
2524 SmallSetVector<SUnit *, 8>
N;
2525 if (
succ_L(NodesAdded,
N, DDG.get()))
2527 addConnectedNodes(
I, NewSet, NodesAdded);
2528 if (!NewSet.
empty())
2529 NodeSets.push_back(NewSet);
2534 if (
pred_L(NodesAdded,
N, DDG.get()))
2536 addConnectedNodes(
I, NewSet, NodesAdded);
2537 if (!NewSet.
empty())
2538 NodeSets.push_back(NewSet);
2542 for (SUnit &SU : SUnits) {
2543 if (NodesAdded.
count(&SU) == 0) {
2545 addConnectedNodes(&SU, NewSet, NodesAdded);
2546 if (!NewSet.
empty())
2547 NodeSets.push_back(NewSet);
2553void SwingSchedulerDAG::addConnectedNodes(SUnit *SU, NodeSet &NewSet,
2554 SetVector<SUnit *> &NodesAdded) {
2559 if (!OE.isArtificial() && !
Successor->isBoundaryNode() &&
2561 addConnectedNodes(
Successor, NewSet, NodesAdded);
2564 SUnit *Predecessor =
IE.getSrc();
2565 if (!
IE.isArtificial() && NodesAdded.
count(Predecessor) == 0)
2566 addConnectedNodes(Predecessor, NewSet, NodesAdded);
2575 for (
SUnit *SU : Set1) {
2576 if (Set2.
count(SU) != 0)
2579 return !Result.empty();
2583void SwingSchedulerDAG::fuseRecs(NodeSetType &NodeSets) {
2584 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2587 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2592 for (SUnit *SU : *J)
2604void SwingSchedulerDAG::removeDuplicateNodes(NodeSetType &NodeSets) {
2605 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2607 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2608 J->remove_if([&](SUnit *SUJ) {
return I->count(SUJ); });
2623void SwingSchedulerDAG::computeNodeOrder(NodeSetType &NodeSets) {
2624 SmallSetVector<SUnit *, 8>
R;
2627 for (
auto &Nodes : NodeSets) {
2630 SmallSetVector<SUnit *, 8>
N;
2645 }
else if (NodeSets.size() == 1) {
2646 for (
const auto &
N : Nodes)
2647 if (
N->Succs.size() == 0)
2653 SUnit *maxASAP =
nullptr;
2654 for (SUnit *SU : Nodes) {
2655 if (maxASAP ==
nullptr || getASAP(SU) > getASAP(maxASAP) ||
2656 (getASAP(SU) == getASAP(maxASAP) && SU->
NodeNum > maxASAP->
NodeNum))
2664 while (!
R.empty()) {
2665 if (Order == TopDown) {
2669 while (!
R.empty()) {
2670 SUnit *maxHeight =
nullptr;
2671 for (SUnit *
I : R) {
2672 if (maxHeight ==
nullptr || getHeight(
I) > getHeight(maxHeight))
2674 else if (getHeight(
I) == getHeight(maxHeight) &&
2675 getZeroLatencyHeight(
I) > getZeroLatencyHeight(maxHeight))
2677 else if (getHeight(
I) == getHeight(maxHeight) &&
2678 getZeroLatencyHeight(
I) ==
2679 getZeroLatencyHeight(maxHeight) &&
2680 getMOV(
I) < getMOV(maxHeight))
2685 R.remove(maxHeight);
2686 for (
const auto &OE : DDG->
getOutEdges(maxHeight)) {
2687 SUnit *SU = OE.getDst();
2688 if (Nodes.count(SU) == 0)
2692 if (OE.ignoreDependence(
false))
2701 for (
const auto &IE : DDG->
getInEdges(maxHeight)) {
2702 SUnit *SU =
IE.getSrc();
2703 if (!
IE.isAntiDep())
2705 if (Nodes.count(SU) == 0)
2714 SmallSetVector<SUnit *, 8>
N;
2721 while (!
R.empty()) {
2722 SUnit *maxDepth =
nullptr;
2723 for (SUnit *
I : R) {
2724 if (maxDepth ==
nullptr || getDepth(
I) > getDepth(maxDepth))
2726 else if (getDepth(
I) == getDepth(maxDepth) &&
2727 getZeroLatencyDepth(
I) > getZeroLatencyDepth(maxDepth))
2729 else if (getDepth(
I) == getDepth(maxDepth) &&
2730 getZeroLatencyDepth(
I) == getZeroLatencyDepth(maxDepth) &&
2731 getMOV(
I) < getMOV(maxDepth))
2737 if (Nodes.isExceedSU(maxDepth)) {
2740 R.insert(Nodes.getNode(0));
2743 for (
const auto &IE : DDG->
getInEdges(maxDepth)) {
2744 SUnit *SU =
IE.getSrc();
2745 if (Nodes.count(SU) == 0)
2756 for (
const auto &OE : DDG->
getOutEdges(maxDepth)) {
2757 SUnit *SU = OE.getDst();
2758 if (!OE.isAntiDep())
2760 if (Nodes.count(SU) == 0)
2769 SmallSetVector<SUnit *, 8>
N;
2778 dbgs() <<
"Node order: ";
2780 dbgs() <<
" " <<
I->NodeNum <<
" ";
2787bool SwingSchedulerDAG::schedulePipeline(SMSchedule &Schedule) {
2794 bool scheduleFound =
false;
2795 std::unique_ptr<HighRegisterPressureDetector> HRPDetector;
2798 std::make_unique<HighRegisterPressureDetector>(Loop.getHeader(), MF);
2799 HRPDetector->init(RegClassInfo);
2802 for (
unsigned II = MII;
II <= MAX_II && !scheduleFound; ++
II) {
2814 int EarlyStart = INT_MIN;
2815 int LateStart = INT_MAX;
2824 dbgs() <<
format(
"\tes: %8x ls: %8x\n", EarlyStart, LateStart));
2826 if (EarlyStart > LateStart)
2827 scheduleFound =
false;
2828 else if (EarlyStart != INT_MIN && LateStart == INT_MAX)
2830 Schedule.
insert(SU, EarlyStart, EarlyStart + (
int)
II - 1,
II);
2831 else if (EarlyStart == INT_MIN && LateStart != INT_MAX)
2833 Schedule.
insert(SU, LateStart, LateStart - (
int)
II + 1,
II);
2834 else if (EarlyStart != INT_MIN && LateStart != INT_MAX) {
2835 LateStart = std::min(LateStart, EarlyStart + (
int)
II - 1);
2844 scheduleFound = Schedule.
insert(SU, LateStart, EarlyStart,
II);
2846 scheduleFound = Schedule.
insert(SU, EarlyStart, LateStart,
II);
2849 scheduleFound = Schedule.
insert(SU, FirstCycle + getASAP(SU),
2850 FirstCycle + getASAP(SU) +
II - 1,
II);
2858 scheduleFound =
false;
2862 dbgs() <<
"\tCan't schedule\n";
2864 }
while (++NI != NE && scheduleFound);
2891 if (scheduleFound) {
2892 scheduleFound = LoopPipelinerInfo->shouldUseSchedule(*
this, Schedule);
2897 if (scheduleFound) {
2899 Pass.ORE->emit([&]() {
2900 return MachineOptimizationRemarkAnalysis(
2901 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
2902 <<
"Schedule found with Initiation Interval: "
2904 <<
", MaxStageCount: "
2918 if (!
Reg.isVirtual())
2932 if (!
Op.isReg() || !
Op.getReg().isVirtual())
2960 if (Def->getParent() != LoopBB)
2963 if (Def->isCopy()) {
2965 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
2967 CurReg = Def->getOperand(1).getReg();
2968 }
else if (Def->isPHI()) {
2974 }
else if (
TII->getIncrementValue(*Def,
Value)) {
2982 bool OffsetIsScalable;
2983 if (
TII->getMemOperandWithOffset(*Def, BaseOp,
Offset, OffsetIsScalable,
2986 CurReg = BaseOp->
getReg();
2998 if (CurReg == OrgReg)
3010bool SwingSchedulerDAG::computeDelta(
const MachineInstr &
MI,
int &Delta)
const {
3011 const TargetRegisterInfo *
TRI = MF.getSubtarget().getRegisterInfo();
3012 const MachineOperand *BaseOp;
3014 bool OffsetIsScalable;
3015 if (!
TII->getMemOperandWithOffset(
MI, BaseOp,
Offset, OffsetIsScalable,
TRI))
3019 if (OffsetIsScalable)
3022 if (!BaseOp->
isReg())
3035bool SwingSchedulerDAG::canUseLastOffsetValue(MachineInstr *
MI,
3037 unsigned &OffsetPos,
3043 unsigned BasePosLd, OffsetPosLd;
3049 MachineRegisterInfo &MRI =
MI->getMF()->getRegInfo();
3051 if (!Phi || !
Phi->isPHI())
3059 MachineInstr *PrevDef = MRI.
getVRegDef(PrevReg);
3060 if (!PrevDef || PrevDef ==
MI)
3066 unsigned BasePos1 = 0, OffsetPos1 = 0;
3072 int64_t LoadOffset =
MI->getOperand(OffsetPosLd).getImm();
3074 MachineInstr *NewMI = MF.CloneMachineInstr(
MI);
3077 MF.deleteMachineInstr(NewMI);
3082 BasePos = BasePosLd;
3083 OffsetPos = OffsetPosLd;
3095 InstrChanges.find(SU);
3096 if (It != InstrChanges.
end()) {
3097 std::pair<Register, int64_t> RegAndOffset = It->second;
3098 unsigned BasePos, OffsetPos;
3099 if (!
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3101 Register BaseReg =
MI->getOperand(BasePos).getReg();
3107 if (BaseStageNum < DefStageNum) {
3109 int OffsetDiff = DefStageNum - BaseStageNum;
3110 if (DefCycleNum < BaseCycleNum) {
3116 MI->getOperand(OffsetPos).getImm() + RegAndOffset.second * OffsetDiff;
3131 while (Def->isPHI()) {
3132 if (!Visited.
insert(Def).second)
3134 for (
unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2)
3135 if (Def->getOperand(i + 1).getMBB() == BB) {
3136 Def = MRI.
getVRegDef(Def->getOperand(i).getReg());
3147 int DeltaB, DeltaO, Delta;
3154 int64_t OffsetB, OffsetO;
3155 bool OffsetBIsScalable, OffsetOIsScalable;
3157 if (!
TII->getMemOperandWithOffset(*BaseMI, BaseOpB, OffsetB,
3158 OffsetBIsScalable,
TRI) ||
3159 !
TII->getMemOperandWithOffset(*OtherMI, BaseOpO, OffsetO,
3160 OffsetOIsScalable,
TRI))
3163 if (OffsetBIsScalable || OffsetOIsScalable)
3173 if (!RegB.
isVirtual() || !RegO.isVirtual())
3178 if (!DefB || !DefO || !DefB->
isPHI() || !DefO->
isPHI())
3203 dbgs() <<
"Overlap check:\n";
3204 dbgs() <<
" BaseMI: ";
3206 dbgs() <<
" Base + " << OffsetB <<
" + I * " << Delta
3207 <<
", Len: " << AccessSizeB.
getValue() <<
"\n";
3208 dbgs() <<
" OtherMI: ";
3210 dbgs() <<
" Base + " << OffsetO <<
" + I * " << Delta
3211 <<
", Len: " << AccessSizeO.
getValue() <<
"\n";
3219 int64_t BaseMinAddr = OffsetB;
3220 int64_t OhterNextIterMaxAddr = OffsetO + Delta + AccessSizeO.
getValue() - 1;
3221 if (BaseMinAddr > OhterNextIterMaxAddr) {
3226 int64_t BaseMaxAddr = OffsetB + AccessSizeB.
getValue() - 1;
3227 int64_t OtherNextIterMinAddr = OffsetO + Delta;
3228 if (BaseMaxAddr < OtherNextIterMinAddr) {
3237void SwingSchedulerDAG::postProcessDAG() {
3238 for (
auto &M : Mutations)
3248 bool forward =
true;
3250 dbgs() <<
"Trying to insert node between " << StartCycle <<
" and "
3251 << EndCycle <<
" II: " <<
II <<
"\n";
3253 if (StartCycle > EndCycle)
3257 int termCycle = forward ? EndCycle + 1 : EndCycle - 1;
3258 for (
int curCycle = StartCycle; curCycle != termCycle;
3259 forward ? ++curCycle : --curCycle) {
3262 ProcItinResources.canReserveResources(*SU, curCycle)) {
3264 dbgs() <<
"\tinsert at cycle " << curCycle <<
" ";
3269 ProcItinResources.reserveResources(*SU, curCycle);
3270 ScheduledInstrs[curCycle].push_back(SU);
3271 InstrToCycle.insert(std::make_pair(SU, curCycle));
3272 if (curCycle > LastCycle)
3273 LastCycle = curCycle;
3274 if (curCycle < FirstCycle)
3275 FirstCycle = curCycle;
3279 dbgs() <<
"\tfailed to insert at cycle " << curCycle <<
" ";
3290 for (
auto &
P : SU->
Preds)
3291 if (
P.getKind() ==
SDep::Anti &&
P.getSUnit()->getInstr()->isPHI())
3292 for (
auto &S :
P.getSUnit()->Succs)
3293 if (S.getKind() ==
SDep::Data && S.getSUnit()->getInstr()->isPHI())
3294 return P.getSUnit();
3307 for (
int cycle =
getFirstCycle(); cycle <= LastCycle; ++cycle) {
3310 if (IE.getSrc() ==
I) {
3311 int EarlyStart = cycle + IE.getLatency() - IE.getDistance() *
II;
3312 *MaxEarlyStart = std::max(*MaxEarlyStart, EarlyStart);
3317 if (OE.getDst() ==
I) {
3318 int LateStart = cycle - OE.getLatency() + OE.getDistance() *
II;
3319 *MinLateStart = std::min(*MinLateStart, LateStart);
3324 for (
const auto &Dep : SU->
Preds) {
3327 if (BE && Dep.getSUnit() == BE && !SU->
getInstr()->
isPHI() &&
3329 *MinLateStart = std::min(*MinLateStart, cycle);
3339 std::deque<SUnit *> &Insts)
const {
3341 bool OrderBeforeUse =
false;
3342 bool OrderAfterDef =
false;
3343 bool OrderBeforeDef =
false;
3344 unsigned MoveDef = 0;
3345 unsigned MoveUse = 0;
3350 for (std::deque<SUnit *>::iterator
I = Insts.begin(), E = Insts.end();
I != E;
3353 if (!MO.isReg() || !MO.getReg().isVirtual())
3357 unsigned BasePos, OffsetPos;
3358 if (ST.getInstrInfo()->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3359 if (
MI->getOperand(BasePos).getReg() == Reg)
3363 std::tie(Reads, Writes) =
3364 (*I)->getInstr()->readsWritesVirtualRegister(Reg);
3366 OrderBeforeUse =
true;
3371 OrderAfterDef =
true;
3373 }
else if (MO.isUse() && Writes &&
stageScheduled(*
I) == StageInst1) {
3375 OrderBeforeUse =
true;
3379 OrderAfterDef =
true;
3383 OrderBeforeUse =
true;
3387 OrderAfterDef =
true;
3392 OrderBeforeUse =
true;
3398 OrderBeforeDef =
true;
3406 if (OE.getDst() != *
I)
3409 OrderBeforeUse =
true;
3416 else if ((OE.isAntiDep() || OE.isOutputDep()) &&
3418 OrderBeforeUse =
true;
3419 if ((MoveUse == 0) || (Pos < MoveUse))
3424 if (IE.getSrc() != *
I)
3426 if ((IE.isAntiDep() || IE.isOutputDep() || IE.isOrderDep()) &&
3428 OrderAfterDef =
true;
3435 if (OrderAfterDef && OrderBeforeUse && MoveUse == MoveDef)
3436 OrderBeforeUse =
false;
3441 OrderBeforeUse = !OrderAfterDef || (MoveUse > MoveDef);
3445 if (OrderBeforeUse && OrderAfterDef) {
3446 SUnit *UseSU = Insts.at(MoveUse);
3447 SUnit *DefSU = Insts.at(MoveDef);
3448 if (MoveUse > MoveDef) {
3449 Insts.erase(Insts.begin() + MoveUse);
3450 Insts.erase(Insts.begin() + MoveDef);
3452 Insts.erase(Insts.begin() + MoveDef);
3453 Insts.erase(Insts.begin() + MoveUse);
3463 Insts.push_front(SU);
3465 Insts.push_back(SU);
3473 assert(Phi.isPHI() &&
"Expecting a Phi.");
3480 getPhiRegs(Phi, Phi.getParent(), InitVal, LoopVal);
3488 return (LoopCycle > DefCycle) || (LoopStage <= DefStage);
3506 if (!Phi || !Phi->isPHI() || Phi->getParent() != Def->getParent())
3512 if (DMO.getReg() == LoopReg)
3523 if (InstrToCycle.count(IE.getSrc()))
3534 for (
auto &SU : SSD->
SUnits)
3539 while (!Worklist.
empty()) {
3541 if (DoNotPipeline.
count(SU))
3544 DoNotPipeline.
insert(SU);
3551 if (OE.getDistance() == 1)
3554 return DoNotPipeline;
3563 int NewLastCycle = INT_MIN;
3568 NewLastCycle = std::max(NewLastCycle, InstrToCycle[&SU]);
3575 if (IE.getDistance() == 0)
3576 NewCycle = std::max(InstrToCycle[IE.getSrc()], NewCycle);
3581 if (OE.getDistance() == 1)
3582 NewCycle = std::max(InstrToCycle[OE.getDst()], NewCycle);
3584 int OldCycle = InstrToCycle[&SU];
3585 if (OldCycle != NewCycle) {
3586 InstrToCycle[&SU] = NewCycle;
3591 <<
") is not pipelined; moving from cycle " << OldCycle
3592 <<
" to " << NewCycle <<
" Instr:" << *SU.
getInstr());
3617 if (FirstCycle + InitiationInterval <= NewCycle)
3620 NewLastCycle = std::max(NewLastCycle, NewCycle);
3622 LastCycle = NewLastCycle;
3639 int CycleDef = InstrToCycle[&SU];
3640 assert(StageDef != -1 &&
"Instruction should have been scheduled.");
3642 SUnit *Dst = OE.getDst();
3643 if (OE.isAssignedRegDep() && !Dst->isBoundaryNode())
3644 if (OE.getReg().isPhysical()) {
3647 if (InstrToCycle[Dst] <= CycleDef)
3665void SwingSchedulerDAG::checkValidNodeOrder(
const NodeSetType &Circuits)
const {
3668 typedef std::pair<SUnit *, unsigned> UnitIndex;
3669 std::vector<UnitIndex> Indices(
NodeOrder.size(), std::make_pair(
nullptr, 0));
3671 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i)
3672 Indices.push_back(std::make_pair(
NodeOrder[i], i));
3674 auto CompareKey = [](UnitIndex i1, UnitIndex i2) {
3675 return std::get<0>(i1) < std::get<0>(i2);
3688 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i) {
3692 bool PredBefore =
false;
3693 bool SuccBefore =
false;
3701 SUnit *PredSU = IE.getSrc();
3702 unsigned PredIndex = std::get<1>(
3712 SUnit *SuccSU = OE.getDst();
3718 unsigned SuccIndex = std::get<1>(
3731 Circuits, [SU](
const NodeSet &Circuit) {
return Circuit.
count(SU); });
3736 NumNodeOrderIssues++;
3740 <<
" are scheduled before node " << SU->
NodeNum
3747 dbgs() <<
"Invalid node order found!\n";
3760 for (
SUnit *SU : Instrs) {
3762 for (
unsigned i = 0, e =
MI->getNumOperands(); i < e; ++i) {
3770 InstrChanges.find(SU);
3771 if (It != InstrChanges.
end()) {
3772 unsigned BasePos, OffsetPos;
3774 if (
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos)) {
3778 MI->getOperand(OffsetPos).getImm() - It->second.second;
3791 unsigned TiedUseIdx = 0;
3792 if (
MI->isRegTiedToUseOperand(i, &TiedUseIdx)) {
3794 OverlapReg =
MI->getOperand(TiedUseIdx).getReg();
3796 NewBaseReg =
MI->getOperand(i).getReg();
3805 const std::deque<SUnit *> &Instrs)
const {
3806 std::deque<SUnit *> NewOrderPhi;
3807 for (
SUnit *SU : Instrs) {
3809 NewOrderPhi.push_back(SU);
3811 std::deque<SUnit *> NewOrderI;
3812 for (
SUnit *SU : Instrs) {
3828 std::deque<SUnit *> &cycleInstrs =
3829 ScheduledInstrs[cycle + (stage * InitiationInterval)];
3831 ScheduledInstrs[cycle].push_front(SU);
3837 for (
int cycle =
getFinalCycle() + 1; cycle <= LastCycle; ++cycle)
3838 ScheduledInstrs.erase(cycle);
3848 std::deque<SUnit *> &cycleInstrs = ScheduledInstrs[Cycle];
3857 os <<
"Num nodes " <<
size() <<
" rec " << RecMII <<
" mov " << MaxMOV
3858 <<
" depth " << MaxDepth <<
" col " << Colocate <<
"\n";
3859 for (
const auto &
I : Nodes)
3860 os <<
" SU(" <<
I->NodeNum <<
") " << *(
I->getInstr());
3864#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3871 for (
SUnit *CI : cycleInstrs->second) {
3873 os <<
"(" << CI->
NodeNum <<
") ";
3884void ResourceManager::dumpMRT()
const {
3888 std::stringstream SS;
3890 SS << std::setw(4) <<
"Slot";
3891 for (
unsigned I = 1, E =
SM.getNumProcResourceKinds();
I < E; ++
I)
3892 SS << std::setw(3) <<
I;
3893 SS << std::setw(7) <<
"#Mops"
3895 for (
int Slot = 0; Slot < InitiationInterval; ++Slot) {
3896 SS << std::setw(4) << Slot;
3897 for (
unsigned I = 1, E =
SM.getNumProcResourceKinds();
I < E; ++
I)
3898 SS << std::setw(3) << MRT[Slot][
I];
3899 SS << std::setw(7) << NumScheduledMops[Slot] <<
"\n";
3908 unsigned ProcResourceID = 0;
3912 assert(SM.getNumProcResourceKinds() < 64 &&
3913 "Too many kinds of resources, unsupported");
3916 Masks.
resize(SM.getNumProcResourceKinds());
3917 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
3919 if (
Desc.SubUnitsIdxBegin)
3921 Masks[
I] = 1ULL << ProcResourceID;
3925 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
3927 if (!
Desc.SubUnitsIdxBegin)
3929 Masks[
I] = 1ULL << ProcResourceID;
3930 for (
unsigned U = 0; U <
Desc.NumUnits; ++U)
3931 Masks[
I] |= Masks[
Desc.SubUnitsIdxBegin[U]];
3936 dbgs() <<
"ProcResourceDesc:\n";
3937 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
3939 dbgs() <<
format(
" %16s(%2d): Mask: 0x%08x, NumUnits:%2d\n",
3940 ProcResource->
Name,
I, Masks[
I],
3943 dbgs() <<
" -----------------\n";
3951 dbgs() <<
"canReserveResources:\n";
3954 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
3960 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
3966 reserveResources(SCDesc, Cycle);
3967 bool Result = !isOverbooked();
3968 unreserveResources(SCDesc, Cycle);
3974void ResourceManager::reserveResources(
SUnit &SU,
int Cycle) {
3977 dbgs() <<
"reserveResources:\n";
3980 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
3986 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
3992 reserveResources(SCDesc, Cycle);
3997 dbgs() <<
"reserveResources: done!\n\n";
4007 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4008 ++MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4011 ++NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4019 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4020 --MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4023 --NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4026bool ResourceManager::isOverbooked()
const {
4028 for (
int Slot = 0;
Slot < InitiationInterval; ++
Slot) {
4029 for (
unsigned I = 1,
E =
SM.getNumProcResourceKinds();
I <
E; ++
I) {
4030 const MCProcResourceDesc *
Desc =
SM.getProcResource(
I);
4031 if (MRT[Slot][
I] >
Desc->NumUnits)
4034 if (NumScheduledMops[Slot] > IssueWidth)
4040int ResourceManager::calculateResMIIDFA()
const {
4045 FuncUnitSorter FUS = FuncUnitSorter(*ST);
4046 for (SUnit &SU : DAG->
SUnits)
4047 FUS.calcCriticalResources(*SU.
getInstr());
4048 PriorityQueue<MachineInstr *, std::vector<MachineInstr *>, FuncUnitSorter>
4051 for (SUnit &SU : DAG->
SUnits)
4058 while (!FuncUnitOrder.empty()) {
4059 MachineInstr *
MI = FuncUnitOrder.top();
4060 FuncUnitOrder.pop();
4061 if (
TII->isZeroCost(
MI->getOpcode()))
4067 unsigned ReservedCycles = 0;
4071 dbgs() <<
"Trying to reserve resource for " << NumCycles
4072 <<
" cycles for \n";
4075 for (
unsigned C = 0;
C < NumCycles; ++
C)
4077 if ((*RI)->canReserveResources(*
MI)) {
4078 (*RI)->reserveResources(*
MI);
4085 <<
", NumCycles:" << NumCycles <<
"\n");
4087 for (
unsigned C = ReservedCycles;
C < NumCycles; ++
C) {
4089 <<
"NewResource created to reserve resources"
4092 assert(NewResource->canReserveResources(*
MI) &&
"Reserve error.");
4093 NewResource->reserveResources(*
MI);
4094 Resources.push_back(std::unique_ptr<DFAPacketizer>(NewResource));
4105 return calculateResMIIDFA();
4112 for (
SUnit &SU : DAG->SUnits) {
4124 <<
" WriteProcRes: ";
4129 make_range(STI->getWriteProcResBegin(SCDesc),
4130 STI->getWriteProcResEnd(SCDesc))) {
4134 SM.getProcResource(PRE.ProcResourceIdx);
4135 dbgs() <<
Desc->Name <<
": " << PRE.ReleaseAtCycle <<
", ";
4138 ResourceCount[PRE.ProcResourceIdx] += PRE.ReleaseAtCycle;
4143 int Result = (NumMops + IssueWidth - 1) / IssueWidth;
4146 dbgs() <<
"#Mops: " << NumMops <<
", "
4147 <<
"IssueWidth: " << IssueWidth <<
", "
4148 <<
"Cycles: " << Result <<
"\n";
4153 std::stringstream SS;
4154 SS << std::setw(2) <<
"ID" << std::setw(16) <<
"Name" << std::setw(10)
4155 <<
"Units" << std::setw(10) <<
"Consumed" << std::setw(10) <<
"Cycles"
4160 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4162 int Cycles = (ResourceCount[
I] +
Desc->NumUnits - 1) /
Desc->NumUnits;
4165 std::stringstream SS;
4166 SS << std::setw(2) <<
I << std::setw(16) <<
Desc->Name << std::setw(10)
4167 <<
Desc->NumUnits << std::setw(10) << ResourceCount[
I]
4168 << std::setw(10) << Cycles <<
"\n";
4172 if (Cycles > Result)
4179 InitiationInterval =
II;
4180 DFAResources.clear();
4181 DFAResources.resize(
II);
4182 for (
auto &
I : DFAResources)
4183 I.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST));
4186 NumScheduledMops.clear();
4187 NumScheduledMops.resize(
II);
4191 if (Pred.isArtificial() || Dst->isBoundaryNode())
4196 return IgnoreAnti && (Pred.getKind() ==
SDep::Kind::Anti || Distance != 0);
4199SwingSchedulerDDG::SwingSchedulerDDGEdges &
4200SwingSchedulerDDG::getEdges(
const SUnit *SU) {
4202 return EntrySUEdges;
4208const SwingSchedulerDDG::SwingSchedulerDDGEdges &
4209SwingSchedulerDDG::getEdges(
const SUnit *SU)
const {
4211 return EntrySUEdges;
4217void SwingSchedulerDDG::addEdge(
const SUnit *SU,
4218 const SwingSchedulerDDGEdge &
Edge) {
4220 "Validation-only edges are not expected here.");
4222 auto &Edges = getEdges(SU);
4223 if (
Edge.getSrc() == SU)
4224 Edges.Succs.push_back(
Edge);
4226 Edges.Preds.push_back(
Edge);
4229void SwingSchedulerDDG::initEdges(SUnit *SU) {
4230 for (
const auto &PI : SU->
Preds) {
4231 SwingSchedulerDDGEdge
Edge(SU, PI,
false,
4236 for (
const auto &SI : SU->
Succs) {
4237 SwingSchedulerDDGEdge
Edge(SU, SI,
true,
4245 : EntrySU(EntrySU), ExitSU(ExitSU) {
4246 EdgesVec.resize(SUnits.size());
4251 for (
auto &SU : SUnits)
4255 for (
SUnit &SU : SUnits) {
4260 for (
SUnit *Dst : *OD) {
4263 Edge.setDistance(1);
4264 ValidationOnlyEdges.push_back(Edge);
4276 bool UseAsExtraEdge = [&]() {
4277 if (Edge.getDistance() == 0 || !Edge.isOrderDep())
4280 SUnit *Src = Edge.getSrc();
4281 SUnit *Dst = Edge.getDst();
4282 if (Src->NodeNum < Dst->NodeNum)
4290 getEdges(Edge.getSrc()).ExtraSuccs.push_back(Edge.getDst());
4296const SwingSchedulerDDG::EdgesType &
4298 return getEdges(SU).Preds;
4301const SwingSchedulerDDG::EdgesType &
4303 return getEdges(SU).Succs;
4307 return getEdges(SU).ExtraSuccs;
4314 auto ExpandCycle = [&](
SUnit *SU) {
4317 return Cycle + (Stage *
II);
4321 SUnit *Src = Edge.getSrc();
4322 SUnit *Dst = Edge.getDst();
4323 if (!Src->isInstr() || !Dst->isInstr())
4325 int CycleSrc = ExpandCycle(Src);
4326 int CycleDst = ExpandCycle(Dst);
4327 int MaxLateStart = CycleDst + Edge.getDistance() *
II - Edge.getLatency();
4328 if (CycleSrc > MaxLateStart) {
4330 dbgs() <<
"Validation failed for edge from " << Src->NodeNum <<
" to "
4331 << Dst->NodeNum <<
"\n";
4341 for (
SUnit &SU : SUnits) {
4370 !
TII->isGlobalMemoryObject(FromMI) &&
4388 const auto DumpSU = [](
const SUnit *SU) {
4389 std::ostringstream OSS;
4390 OSS <<
"SU(" << SU->
NodeNum <<
")";
4394 dbgs() <<
" Loop carried edges from " << DumpSU(SU) <<
"\n"
4396 for (
SUnit *Dst : *Order)
4397 dbgs() <<
" " << DumpSU(Dst) <<
"\n";
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static std::optional< unsigned > getTag(const TargetRegisterInfo *TRI, const MachineInstr &MI, const LoadInfo &LI)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
This file contains the simple types necessary to represent the attributes associated with functions a...
This file implements the BitVector class.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
DXIL Remove Unused Resources
This file defines the DenseMap class.
const HexagonInstrInfo * TII
A common definition of LaneBitmask for use in TableGen and CodeGen.
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
print mir2vec MIR2Vec Vocabulary Printer Pass
static cl::opt< int > SwpForceII("pipeliner-force-ii", cl::desc("Force pipeliner to use specified II."), cl::Hidden, cl::init(-1))
A command line argument to force pipeliner to use specified initial interval.
static cl::opt< bool > ExperimentalCodeGen("pipeliner-experimental-cg", cl::Hidden, cl::init(false), cl::desc("Use the experimental peeling code generator for software pipelining"))
static bool hasPHICycleDFS(unsigned Reg, const DenseMap< unsigned, SmallVector< unsigned, 2 > > &PhiDeps, SmallSet< unsigned, 8 > &Visited, SmallSet< unsigned, 8 > &RecStack)
Depth-first search to detect cycles among PHI dependencies.
static cl::opt< bool > MVECodeGen("pipeliner-mve-cg", cl::Hidden, cl::init(false), cl::desc("Use the MVE code generator for software pipelining"))
static cl::opt< int > RegPressureMargin("pipeliner-register-pressure-margin", cl::Hidden, cl::init(5), cl::desc("Margin representing the unused percentage of " "the register pressure limit"))
static void getPhiRegs(MachineInstr &Phi, MachineBasicBlock *Loop, Register &InitVal, Register &LoopVal)
Return the register values for the operands of a Phi instruction.
static cl::opt< bool > SwpDebugResource("pipeliner-dbg-res", cl::Hidden, cl::init(false))
static void computeLiveOuts(MachineFunction &MF, RegPressureTracker &RPTracker, NodeSet &NS)
Compute the live-out registers for the instructions in a node-set.
static void computeScheduledInsts(const SwingSchedulerDAG *SSD, SMSchedule &Schedule, std::vector< MachineInstr * > &OrderedInsts, DenseMap< MachineInstr *, unsigned > &Stages)
Create an instruction stream that represents a single iteration and stage of each instruction.
static cl::opt< bool > EmitTestAnnotations("pipeliner-annotate-for-testing", cl::Hidden, cl::init(false), cl::desc("Instead of emitting the pipelined code, annotate instructions " "with the generated schedule for feeding into the " "-modulo-schedule-test pass"))
static Register getLoopPhiReg(const MachineInstr &Phi, const MachineBasicBlock *LoopBB)
Return the Phi register value that comes the loop block.
static bool isIntersect(SmallSetVector< SUnit *, 8 > &Set1, const NodeSet &Set2, SmallSetVector< SUnit *, 8 > &Result)
Return true if Set1 contains elements in Set2.
static bool findLoopIncrementValue(const MachineOperand &Op, int &Value)
When Op is a value that is incremented recursively in a loop and there is a unique instruction that i...
static cl::opt< bool > SwpIgnoreRecMII("pipeliner-ignore-recmii", cl::ReallyHidden, cl::desc("Ignore RecMII"))
static cl::opt< int > SwpLoopLimit("pipeliner-max", cl::Hidden, cl::init(-1))
static cl::opt< bool > SwpPruneLoopCarried("pipeliner-prune-loop-carried", cl::desc("Prune loop carried order dependences."), cl::Hidden, cl::init(true))
A command line option to disable the pruning of loop carried order dependences.
static cl::opt< unsigned > SwpMaxNumStores("pipeliner-max-num-stores", cl::desc("Maximum number of stores allwed in the target loop."), cl::Hidden, cl::init(200))
A command line argument to limit the number of store instructions in the target basic block.
static cl::opt< int > SwpMaxMii("pipeliner-max-mii", cl::desc("Size limit for the MII."), cl::Hidden, cl::init(27))
A command line argument to limit minimum initial interval for pipelining.
static bool isSuccOrder(SUnit *SUa, SUnit *SUb)
Return true if SUb can be reached from SUa following the chain edges.
static cl::opt< int > SwpMaxStages("pipeliner-max-stages", cl::desc("Maximum stages allowed in the generated scheduled."), cl::Hidden, cl::init(3))
A command line argument to limit the number of stages in the pipeline.
static cl::opt< bool > EnableSWPOptSize("enable-pipeliner-opt-size", cl::desc("Enable SWP at Os."), cl::Hidden, cl::init(false))
A command line option to enable SWP at -Os.
static bool hasPHICycle(const MachineBasicBlock *LoopHeader, const MachineRegisterInfo &MRI)
static cl::opt< WindowSchedulingFlag > WindowSchedulingOption("window-sched", cl::Hidden, cl::init(WindowSchedulingFlag::WS_On), cl::desc("Set how to use window scheduling algorithm."), cl::values(clEnumValN(WindowSchedulingFlag::WS_Off, "off", "Turn off window algorithm."), clEnumValN(WindowSchedulingFlag::WS_On, "on", "Use window algorithm after SMS algorithm fails."), clEnumValN(WindowSchedulingFlag::WS_Force, "force", "Use window algorithm instead of SMS algorithm.")))
A command line argument to set the window scheduling option.
static bool pred_L(SetVector< SUnit * > &NodeOrder, SmallSetVector< SUnit *, 8 > &Preds, SwingSchedulerDDG *DDG, const NodeSet *S=nullptr)
Compute the Pred_L(O) set, as defined in the paper.
static cl::opt< bool > SwpShowResMask("pipeliner-show-mask", cl::Hidden, cl::init(false))
static cl::opt< int > SwpIISearchRange("pipeliner-ii-search-range", cl::desc("Range to search for II"), cl::Hidden, cl::init(10))
static bool computePath(SUnit *Cur, SetVector< SUnit * > &Path, SetVector< SUnit * > &DestNodes, SetVector< SUnit * > &Exclude, SmallPtrSet< SUnit *, 8 > &Visited, SwingSchedulerDDG *DDG)
Return true if there is a path from the specified node to any of the nodes in DestNodes.
static bool succ_L(SetVector< SUnit * > &NodeOrder, SmallSetVector< SUnit *, 8 > &Succs, SwingSchedulerDDG *DDG, const NodeSet *S=nullptr)
Compute the Succ_L(O) set, as defined in the paper.
static cl::opt< bool > LimitRegPressure("pipeliner-register-pressure", cl::Hidden, cl::init(false), cl::desc("Limit register pressure of scheduled loop"))
static cl::opt< bool > EnableSWP("enable-pipeliner", cl::Hidden, cl::init(true), cl::desc("Enable Software Pipelining"))
A command line option to turn software pipelining on or off.
static bool hasLoopCarriedMemDep(const SUnitWithMemInfo &Src, const SUnitWithMemInfo &Dst, BatchAAResults &BAA, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI, const SwingSchedulerDAG *SSD)
Returns true if there is a loop-carried order dependency from Src to Dst.
static cl::opt< bool > SwpPruneDeps("pipeliner-prune-deps", cl::desc("Prune dependences between unrelated Phi nodes."), cl::Hidden, cl::init(true))
A command line option to disable the pruning of chain dependences due to an unrelated Phi.
static SUnit * multipleIterations(SUnit *SU, SwingSchedulerDAG *DAG)
If an instruction has a use that spans multiple iterations, then return true.
static Register findUniqueOperandDefinedInLoop(const MachineInstr &MI)
Register const TargetRegisterInfo * TRI
Promote Memory to Register
This file provides utility analysis objects describing memory locations.
static constexpr unsigned SM(unsigned Version)
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the PriorityQueue class.
Remove Loads Into Fake Uses
std::pair< BasicBlock *, BasicBlock * > Edge
This file defines generic set operations that may be used on set's of different types,...
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Target-Independent Code Generator Pass Configuration Options pass.
Add loop-carried chain dependencies.
void computeDependencies()
The main function to compute loop-carried order-dependencies.
const BitVector & getLoopCarried(unsigned Idx) const
LoopCarriedOrderDepsTracker(SwingSchedulerDAG *SSD, BatchAAResults *BAA, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
bool erase(const KeyT &Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
AttributeList getAttributes() const
Return the attribute list for this Function.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
bool isPostIncrement(const MachineInstr &MI) const override
Return true for post-incremented instructions.
DFAPacketizer * CreateTargetScheduleState(const TargetSubtargetInfo &STI) const override
Create machine specific model for scheduling.
bool getBaseAndOffsetPosition(const MachineInstr &MI, unsigned &BasePos, unsigned &OffsetPos) const override
For instructions with a base and offset, return the position of the base register and offset operands...
const InstrStage * beginStage(unsigned ItinClassIndx) const
Return the first stage of the itinerary.
const InstrStage * endStage(unsigned ItinClassIndx) const
Return the last+1 stage of the itinerary.
bool isEmpty() const
Returns true if there are no itineraries.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
TypeSize getValue() const
Represents a single loop in the control flow graph.
unsigned getSchedClass() const
Return the scheduling class for this instruction.
const MCWriteProcResEntry * getWriteProcResEnd(const MCSchedClassDesc *SC) const
const MCWriteProcResEntry * getWriteProcResBegin(const MCSchedClassDesc *SC) const
Return an iterator at the first process resource consumed by the given scheduling class.
const MCSchedModel & getSchedModel() const
Get the machine model for this subtarget's CPU.
const MDOperand & getOperand(unsigned I) const
ArrayRef< MDOperand > operands() const
unsigned getNumOperands() const
Return number of MDNode operands.
LLVM_ABI StringRef getString() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
iterator_range< iterator > phis()
Returns a range that iterates over the phis in the basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
instr_iterator instr_end()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
filtered_mop_range all_defs()
Returns an iterator range over all operands that are (explicit or implicit) register defs.
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.
bool isRegSequence() const
mmo_iterator memoperands_begin() const
Access to memory operands of the instruction.
LLVM_ABI bool isIdenticalTo(const MachineInstr &Other, MICheckType Check=CheckDefs) const
Return true if this instruction is identical to Other.
LLVM_ABI void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
bool mayStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly modify memory.
bool isPseudo(QueryType Type=IgnoreBundle) const
Return true if this is a pseudo instruction that doesn't correspond to a real machine instruction.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
AAMDNodes getAAInfo() const
Return the AA tags for the memory reference.
const Value * getValue() const
Return the base address of the memory access.
int64_t getOffset() const
For normal values, this is a byte offset added to the base address.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
The main class in the implementation of the target independent software pipeliner pass.
bool runOnMachineFunction(MachineFunction &MF) override
The "main" function for implementing Swing Modulo Scheduling.
const TargetInstrInfo * TII
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const MachineDominatorTree * MDT
const MachineLoopInfo * MLI
const RegisterClassInfo * RegClassInfo
MachineOptimizationRemarkEmitter * ORE
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
defusechain_instr_iterator< true, false, false, true > use_instr_iterator
use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the specified register,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
use_instr_iterator use_instr_begin(Register RegNo) const
PSetIterator getPressureSets(VirtRegOrUnit VRegOrUnit) const
Get an iterator over the pressure sets affected by the virtual register or register unit.
bool isReserved(MCRegister PhysReg) const
isReserved - Returns true when PhysReg is a reserved register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
static use_instr_iterator use_instr_end()
bool isAllocatable(MCRegister PhysReg) const
isAllocatable - Returns true when PhysReg belongs to an allocatable register class and it hasn't been...
LLVM_ABI MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())
Return a location that may access any location before or after Ptr, while remaining within the underl...
Expand the kernel using modulo variable expansion algorithm (MVE).
static LLVM_ABI bool canApply(MachineLoop &L)
Check if ModuloScheduleExpanderMVE can be applied to L.
The ModuloScheduleExpander takes a ModuloSchedule and expands it in-place, rewriting the old loop and...
LLVM_ABI void cleanup()
Performs final cleanup after expansion.
LLVM_ABI void expand()
Performs the actual expansion.
Expander that simply annotates each scheduled instruction with a post-instr symbol that can be consum...
LLVM_ABI void annotate()
Performs the annotation.
Represents a schedule for a single-block loop.
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
SUnit * getNode(unsigned i) const
LLVM_ABI void print(raw_ostream &os) const
void setRecMII(unsigned mii)
unsigned count(SUnit *SU) const
void setColocate(unsigned c)
int compareRecMII(NodeSet &RHS)
LLVM_DUMP_METHOD void dump() const
unsigned getWeight() const
AnalysisType & getAnalysis() const
getAnalysis<AnalysisType>() - This function is used by subclasses to get to the analysis information ...
A reimplementation of ModuloScheduleExpander.
PointerIntPair - This class implements a pair of a pointer and small integer.
Track the current register pressure at some position in the instruction stream, and remember the high...
LLVM_ABI void addLiveRegs(ArrayRef< VRegMaskOrUnit > Regs)
Force liveness of virtual registers or physical register units.
unsigned getRegPressureSetLimit(unsigned Idx) const
Get the register unit limit for the given pressure set index.
Wrapper class representing virtual and physical registers.
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
LLVM_ABI int calculateResMII() const
LLVM_ABI void initProcResourceVectors(const MCSchedModel &SM, SmallVectorImpl< uint64_t > &Masks)
LLVM_ABI void init(int II)
Initialize resources with the initiation interval II.
LLVM_ABI bool canReserveResources(SUnit &SU, int Cycle)
Check if the resources occupied by a machine instruction are available in the current state.
Kind
These are the different kinds of scheduling dependencies.
@ Order
Any other ordering dependency.
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
void setLatency(unsigned Lat)
Sets the latency for this edge.
@ Barrier
An unknown scheduling barrier.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
This class represents the scheduled code.
LLVM_ABI std::deque< SUnit * > reorderInstructions(const SwingSchedulerDAG *SSD, const std::deque< SUnit * > &Instrs) const
void setInitiationInterval(int ii)
Set the initiation interval for this schedule.
LLVM_ABI void dump() const
Utility function used for debugging to print the schedule.
LLVM_ABI bool insert(SUnit *SU, int StartCycle, int EndCycle, int II)
Try to schedule the node at the specified StartCycle and continue until the node is schedule or the E...
unsigned getMaxStageCount()
Return the maximum stage count needed for this schedule.
LLVM_ABI void print(raw_ostream &os) const
Print the schedule information to the given output.
LLVM_ABI bool onlyHasLoopCarriedOutputOrOrderPreds(SUnit *SU, const SwingSchedulerDDG *DDG) const
Return true if all scheduled predecessors are loop-carried output/order dependencies.
int stageScheduled(SUnit *SU) const
Return the stage for a scheduled instruction.
LLVM_ABI void orderDependence(const SwingSchedulerDAG *SSD, SUnit *SU, std::deque< SUnit * > &Insts) const
Order the instructions within a cycle so that the definitions occur before the uses.
LLVM_ABI bool isValidSchedule(SwingSchedulerDAG *SSD)
int getInitiationInterval() const
Return the initiation interval for this schedule.
std::deque< SUnit * > & getInstructions(int cycle)
Return the instructions that are scheduled at the specified cycle.
int getFirstCycle() const
Return the first cycle in the completed schedule.
DenseMap< int, std::deque< SUnit * > >::const_iterator const_sched_iterator
LLVM_ABI bool isLoopCarriedDefOfUse(const SwingSchedulerDAG *SSD, MachineInstr *Def, MachineOperand &MO) const
Return true if the instruction is a definition that is loop carried and defines the use on the next i...
unsigned cycleScheduled(SUnit *SU) const
Return the cycle for a scheduled instruction.
LLVM_ABI SmallPtrSet< SUnit *, 8 > computeUnpipelineableNodes(SwingSchedulerDAG *SSD, TargetInstrInfo::PipelinerLoopInfo *PLI)
Determine transitive dependences of unpipelineable instructions.
LLVM_ABI void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart, int II, SwingSchedulerDAG *DAG)
Compute the scheduling start slot for the instruction.
LLVM_ABI bool normalizeNonPipelinedInstructions(SwingSchedulerDAG *SSD, TargetInstrInfo::PipelinerLoopInfo *PLI)
LLVM_ABI bool isLoopCarried(const SwingSchedulerDAG *SSD, MachineInstr &Phi) const
Return true if the scheduled Phi has a loop carried operand.
int getFinalCycle() const
Return the last cycle in the finalized schedule.
LLVM_ABI void finalizeSchedule(SwingSchedulerDAG *SSD)
After the schedule has been formed, call this function to combine the instructions from the different...
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.
void setInstr(MachineInstr *MI)
Assigns the instruction for the SUnit.
LLVM_ABI void removePred(const SDep &D)
Removes the specified edge as a pred of the current node if it exists.
bool isPred(const SUnit *N) const
Tests if node N is a predecessor of this node.
unsigned short Latency
Node latency.
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
bool hasPhysRegDefs
Has physreg defs that are being used.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
LLVM_ABI bool addPred(const SDep &D, bool Required=true)
Adds the specified edge as a pred of the current node if not already.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
DenseMap< MachineInstr *, SUnit * > MISUnitMap
After calling BuildSchedGraph, each machine instruction in the current scheduling region is mapped to...
virtual void finishBlock()
Cleans up after scheduling in the given block.
MachineBasicBlock * BB
The block in which to insert instructions.
void buildSchedGraph(AAResults *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
SUnit * getSUnit(MachineInstr *MI) const
Returns an existing SUnit for this MI, or nullptr.
void dump() const override
LLVM_ABI void AddPred(SUnit *Y, SUnit *X)
Updates the topological ordering to accommodate an edge to be added from SUnit X to SUnit Y.
LLVM_ABI bool IsReachable(const SUnit *SU, const SUnit *TargetSU)
Checks if SU is reachable from TargetSU.
MachineRegisterInfo & MRI
Virtual/real register map.
const TargetInstrInfo * TII
Target instruction information.
std::vector< SUnit > SUnits
The scheduling units.
const TargetRegisterInfo * TRI
Target processor register info.
SUnit EntrySU
Special node for the region entry.
MachineFunction & MF
Machine function.
SUnit ExitSU
Special node for the region exit.
A vector that has set insertion semantics.
size_type size() const
Determine the number of elements in the SetVector.
void insert_range(Range &&R)
size_type count(const_arg_type key) const
Count the number of elements of a given key in the SetVector.
typename vector_type::const_iterator iterator
bool contains(const_arg_type key) const
Check if the SetVector contains the given key.
void clear()
Completely clear the SetVector.
bool empty() const
Determine if the SetVector is empty or not.
bool insert(const value_type &X)
Insert a new element into the SetVector.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
bool erase(PtrType Ptr)
Remove pointer from the set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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.
A SetVector that performs no allocations if smaller than a certain size.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
size_type count(const T &V) const
count - Return 1 if the element is in the set, 0 otherwise.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class builds the dependence graph for the instructions in a loop, and attempts to schedule the i...
void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule)
Apply changes to the instruction if needed.
const SwingSchedulerDDG * getDDG() const
void finishBlock() override
Clean up after the software pipeliner runs.
void fixupRegisterOverlaps(std::deque< SUnit * > &Instrs)
Attempt to fix the degenerate cases when the instruction serialization causes the register lifetimes ...
void schedule() override
We override the schedule function in ScheduleDAGInstrs to implement the scheduling part of the Swing ...
bool mayOverlapInLaterIter(const MachineInstr *BaseMI, const MachineInstr *OtherMI) const
Return false if there is no overlap between the region accessed by BaseMI in an iteration and the reg...
Register getInstrBaseReg(SUnit *SU) const
Return the new base register that was stored away for the changed instruction.
Represents a dependence between two instruction.
LLVM_ABI bool ignoreDependence(bool IgnoreAnti) const
Returns true for DDG nodes that we ignore when computing the cost functions.
This class provides APIs to retrieve edges from/to an SUnit node, with a particular focus on loop-car...
LLVM_ABI SwingSchedulerDDG(std::vector< SUnit > &SUnits, SUnit *EntrySU, SUnit *ExitSU, const LoopCarriedEdges &LCE)
LLVM_ABI ArrayRef< SUnit * > getExtraOutEdges(const SUnit *SU) const
LLVM_ABI const EdgesType & getInEdges(const SUnit *SU) const
LLVM_ABI bool isValidSchedule(const SMSchedule &Schedule) const
Check if Schedule doesn't violate the validation-only dependencies.
LLVM_ABI const EdgesType & getOutEdges(const SUnit *SU) const
Object returned by analyzeLoopForPipelining.
virtual bool shouldIgnoreForPipelining(const MachineInstr *MI) const =0
Return true if the given instruction should not be pipelined and should be ignored.
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
Target-Independent Code Generator Pass Configuration Options.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual bool enableMachinePipeliner() const
True if the subtarget should run MachinePipeliner.
virtual bool useDFAforSMS() const
Default to DFA for resource management, return false when target will use ProcResource in InstrSchedM...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
virtual const InstrItineraryData * getInstrItineraryData() const
getInstrItineraryData - Returns instruction itinerary data for the target or specific subtarget.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Wrapper class representing a virtual register or register unit.
constexpr bool isVirtualReg() const
constexpr MCRegUnit asMCRegUnit() const
constexpr Register asVirtualReg() const
The main class in the implementation of the target independent window scheduler.
std::pair< iterator, bool > insert(const ValueT &V)
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
This class implements an extremely fast bulk output stream that can only output to a stream.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
@ BasicBlock
Various leaf nodes.
@ Valid
The data is already valid.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
std::set< NodeId > NodeSet
friend class Instruction
Iterator for Instructions in a `BasicBlock.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
void stable_sort(R &&Range)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
constexpr NextUseDistance min(NextUseDistance A, NextUseDistance B)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
static int64_t computeDelta(SectionEntry *A, SectionEntry *B)
@ WS_Force
Use window algorithm after SMS algorithm fails.
@ WS_On
Turn off window algorithm.
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
RegState getRegState(const MachineOperand &RegOp)
Get all register state flags from machine operand RegOp.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ABI cl::opt< bool > SwpEnableCopyToPhi
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
LLVM_ABI char & MachinePipelinerID
This pass performs software pipelining on machine instructions.
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LLVM_ABI cl::opt< int > SwpForceIssueWidth
A command line argument to force pipeliner to use specified issue width.
@ Increment
Incrementally increasing token ID.
AAResults AliasAnalysis
Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.
LLVM_ABI void getUnderlyingObjects(const Value *V, SmallVectorImpl< const Value * > &Objects, const LoopInfo *LI=nullptr, unsigned MaxLookup=MaxLookupSearchDepth)
This method is similar to getUnderlyingObject except that it can look through phi and select instruct...
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This class holds an SUnit corresponding to a memory operation and other information related to the in...
const Value * MemOpValue
The value of a memory operand.
SmallVector< const Value *, 2 > UnderlyingObjs
bool isTriviallyDisjoint(const SUnitWithMemInfo &Other) const
int64_t MemOpOffset
The offset of a memory operand.
bool IsAllIdentified
True if all the underlying objects are identified.
SUnitWithMemInfo(SUnit *SU)
A collection of metadata nodes that might be associated with a memory access used by the alias-analys...
uint64_t FuncUnits
Bitmask representing a set of functional units.
static constexpr LaneBitmask getNone()
Represents loop-carried dependencies.
SmallSetVector< SUnit *, 8 > OrderDep
const OrderDep * getOrderDepOrNull(SUnit *Key) const
LLVM_ABI void modifySUnits(std::vector< SUnit > &SUnits, const TargetInstrInfo *TII)
Adds some edges to the original DAG that correspond to loop-carried dependencies.
LLVM_ABI void dump(SUnit *SU, const TargetRegisterInfo *TRI, const MachineRegisterInfo *MRI) const
Define a kind of processor resource that will be modeled by the scheduler.
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Machine model for scheduling, bundling, and heuristics.
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
bool hasInstrSchedModel() const
Does this machine model include instruction-level scheduling.
const MCProcResourceDesc * getProcResource(unsigned ProcResourceIdx) const
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
std::vector< unsigned > MaxSetPressure
Map of max reg pressure indexed by pressure set ID, not class ID.