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;
234 "Modulo Software Pipelining",
false,
false)
276 enum class InstrTag {
285 TaggedSUnit(
SUnit *SU, InstrTag Tag)
288 InstrTag
getTag()
const {
return InstrTag(getInt()); }
293 struct NoBarrierInstsChunk {
298 void append(
SUnit *SU);
303 std::vector<SUnit> &SUnits;
309 std::vector<BitVector> LoopCarried;
322 std::vector<TaggedSUnit> TaggedSUnits;
336 return LoopCarried[Idx];
341 std::optional<InstrTag> getInstrTag(
SUnit *SU)
const;
343 void addLoopCarriedDepenenciesForChunks(
const NoBarrierInstsChunk &From,
344 const NoBarrierInstsChunk &To);
351 void computeDependenciesAux();
353 void setLoopCarriedDep(
const SUnit *Src,
const SUnit *Dst) {
354 LoopCarried[Src->NodeNum].set(Dst->NodeNum);
405 bool useSwingModuloScheduler();
406 bool useWindowScheduler(
bool Changed);
412int MachinePipelinerImpl::NumTries = 0;
425 for (
const auto &L : *
MLI)
453 MachinePipelinerImpl MP(MF, GetMLI(), GetLIS(), GetAA(), GetORE(), GetRCI());
514bool MachinePipelinerImpl::scheduleLoop(
MachineLoop &L) {
516 for (
const auto &InnerLoop : L)
517 Changed |= scheduleLoop(*InnerLoop);
529 setPragmaPipelineOptions(L);
530 if (!canPipelineLoop(L)) {
534 L.getStartLoc(), L.getHeader())
535 <<
"Failed to pipeline loop";
538 LI.LoopPipelinerInfo.reset();
543 if (useSwingModuloScheduler())
544 Changed = swingModuloScheduler(L);
546 if (useWindowScheduler(
Changed))
547 Changed = runWindowScheduler(L);
549 LI.LoopPipelinerInfo.reset();
553void MachinePipelinerImpl::setPragmaPipelineOptions(MachineLoop &L) {
558 MachineBasicBlock *LBLK =
L.getTopBlock();
571 MDNode *LoopID = TI->
getMetadata(LLVMContext::MD_loop);
572 if (LoopID ==
nullptr)
589 if (S->
getString() ==
"llvm.loop.pipeline.initiationinterval") {
591 "Pipeline initiation interval hint metadata should have two operands.");
595 }
else if (S->
getString() ==
"llvm.loop.pipeline.disable") {
608 auto It = PhiDeps.find(
Reg);
609 if (It == PhiDeps.end())
620 for (
unsigned Dep : It->second) {
635 unsigned DefReg =
MI.getOperand(0).getReg();
639 for (
unsigned I = 1;
I <
MI.getNumOperands();
I += 2)
640 Ins->second.push_back(
MI.getOperand(
I).getReg());
647 for (
const auto &KV : PhiDeps) {
648 unsigned Reg = KV.first;
659bool MachinePipelinerImpl::canPipelineLoop(MachineLoop &L) {
660 if (
L.getNumBlocks() != 1) {
662 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
663 L.getStartLoc(),
L.getHeader())
664 <<
"Not a single basic block: "
665 <<
ore::NV(
"NumBlocks",
L.getNumBlocks());
677 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
678 L.getStartLoc(),
L.getHeader())
679 <<
"Disabled by Pragma.";
689 if (
TII->analyzeBranch(*
L.getHeader(),
LI.TBB,
LI.FBB,
LI.BrCond)) {
690 LLVM_DEBUG(
dbgs() <<
"Unable to analyzeBranch, can NOT pipeline Loop\n");
693 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
694 L.getStartLoc(),
L.getHeader())
695 <<
"The branch can't be understood";
700 LI.LoopInductionVar =
nullptr;
701 LI.LoopCompare =
nullptr;
702 LI.LoopPipelinerInfo =
TII->analyzeLoopForPipelining(
L.getTopBlock());
703 if (!
LI.LoopPipelinerInfo) {
704 LLVM_DEBUG(
dbgs() <<
"Unable to analyzeLoop, can NOT pipeline Loop\n");
707 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
708 L.getStartLoc(),
L.getHeader())
709 <<
"The loop structure is not supported";
714 if (!
L.getLoopPreheader()) {
715 LLVM_DEBUG(
dbgs() <<
"Preheader not found, can NOT pipeline Loop\n");
718 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
719 L.getStartLoc(),
L.getHeader())
720 <<
"No loop preheader found";
725 unsigned NumStores = 0;
726 for (MachineInstr &
MI : *
L.getHeader())
731 NumFailTooManyStores++;
733 return MachineOptimizationRemarkAnalysis(
DEBUG_TYPE,
"canPipelineLoop",
734 L.getStartLoc(),
L.getHeader())
735 <<
"Too many store instructions in the loop: "
736 <<
ore::NV(
"NumStores", NumStores) <<
" > "
743 preprocessPhiNodes(*
L.getHeader());
747void MachinePipelinerImpl::preprocessPhiNodes(MachineBasicBlock &
B) {
748 MachineRegisterInfo &MRI =
MF->getRegInfo();
749 SlotIndexes &Slots = *
LIS->getSlotIndexes();
751 for (MachineInstr &PI :
B.phis()) {
752 MachineOperand &DefOp = PI.getOperand(0);
756 for (
unsigned i = 1, n = PI.getNumOperands(); i != n; i += 2) {
757 MachineOperand &RegOp = PI.getOperand(i);
764 MachineBasicBlock &PredB = *PI.getOperand(i+1).getMBB();
781bool MachinePipelinerImpl::swingModuloScheduler(MachineLoop &L) {
782 assert(
L.getBlocks().size() == 1 &&
"SMS works on single blocks only.");
785 LI.LoopPipelinerInfo.get(),
AA);
787 MachineBasicBlock *
MBB =
L.getHeader();
805 return SMS.hasNewSchedule();
820bool MachinePipelinerImpl::runWindowScheduler(
MachineLoop &L) {
832bool MachinePipelinerImpl::useSwingModuloScheduler() {
837bool MachinePipelinerImpl::useWindowScheduler(
bool Changed) {
844 "llvm.loop.pipeline.initiationinterval is set.\n");
852void SwingSchedulerDAG::setMII(
unsigned ResMII,
unsigned RecMII) {
855 else if (II_setByPragma > 0)
856 MII = II_setByPragma;
858 MII = std::max(ResMII, RecMII);
861void SwingSchedulerDAG::setMAX_II() {
864 else if (II_setByPragma > 0)
865 MAX_II = II_setByPragma;
875 updatePhiDependences();
876 Topo.InitDAGTopologicalSorting();
882 dbgs() <<
"===== Loop Carried Edges Begin =====\n";
885 dbgs() <<
"===== Loop Carried Edges End =====\n";
888 NodeSetType NodeSets;
889 findCircuits(NodeSets);
890 NodeSetType Circuits = NodeSets;
893 unsigned ResMII = calculateResMII();
894 unsigned RecMII = calculateRecMII(NodeSets);
902 setMII(ResMII, RecMII);
906 <<
" (rec=" << RecMII <<
", res=" << ResMII <<
")\n");
914 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
915 <<
"Invalid Minimal Initiation Interval: 0";
923 <<
", we don't pipeline large loops\n");
924 NumFailLargeMaxMII++;
927 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
928 <<
"Minimal Initiation Interval too large: "
929 <<
ore::NV(
"MII", (
int)MII) <<
" > "
931 <<
"Refer to -pipeliner-max-mii.";
936 computeNodeFunctions(NodeSets);
938 registerPressureFilter(NodeSets);
940 colocateNodeSets(NodeSets);
942 checkNodeSets(NodeSets);
945 for (
auto &
I : NodeSets) {
946 dbgs() <<
" Rec NodeSet ";
953 groupRemainingNodes(NodeSets);
955 removeDuplicateNodes(NodeSets);
958 for (
auto &
I : NodeSets) {
959 dbgs() <<
" NodeSet ";
964 computeNodeOrder(NodeSets);
967 checkValidNodeOrder(Circuits);
970 Scheduled = schedulePipeline(Schedule);
977 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
978 <<
"Unable to find schedule";
985 if (numStages == 0) {
990 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
991 <<
"No need to pipeline - no overlapped iterations in schedule.";
998 <<
" : too many stages, abort\n");
999 NumFailLargeMaxStage++;
1002 DEBUG_TYPE,
"schedule", Loop.getStartLoc(), Loop.getHeader())
1003 <<
"Too many stages in schedule: "
1004 <<
ore::NV(
"numStages", (
int)numStages) <<
" > "
1006 <<
". Refer to -pipeliner-max-stages.";
1014 <<
"Pipelined succesfully!";
1019 std::vector<MachineInstr *> OrderedInsts;
1023 OrderedInsts.push_back(SU->getInstr());
1024 Cycles[SU->getInstr()] = Cycle;
1029 for (
auto &KV : NewMIs) {
1030 Cycles[KV.first] = Cycles[KV.second];
1031 Stages[KV.first] = Stages[KV.second];
1032 NewInstrChanges[KV.first] = InstrChanges[
getSUnit(KV.first)];
1039 "Cannot serialize a schedule with InstrChanges!");
1049 LoopPipelinerInfo->isMVEExpanderSupported() &&
1063 for (
auto &KV : NewMIs)
1064 MF.deleteMachineInstr(KV.second);
1075 assert(Phi.isPHI() &&
"Expecting a Phi.");
1079 for (
unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
1080 if (Phi.getOperand(i + 1).getMBB() !=
Loop)
1081 InitVal = Phi.getOperand(i).getReg();
1083 LoopVal = Phi.getOperand(i).getReg();
1085 assert(InitVal && LoopVal &&
"Unexpected Phi structure.");
1091 for (
unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
1092 if (Phi.getOperand(i + 1).getMBB() == LoopBB)
1093 return Phi.getOperand(i).getReg();
1102 while (!Worklist.
empty()) {
1104 for (
const auto &
SI : SU->
Succs) {
1105 SUnit *SuccSU =
SI.getSUnit();
1107 if (Visited.
count(SuccSU))
1120 if (!getUnderlyingObjects())
1145bool SUnitWithMemInfo::getUnderlyingObjects() {
1147 if (!
MI->hasOneMemOperand())
1165 const SUnitWithMemInfo &Dst,
1170 if (Src.isTriviallyDisjoint(Dst))
1184 if (Src.isUnknown() || Dst.isUnknown())
1186 if (Src.MemOpValue == Dst.MemOpValue && Src.MemOpOffset <= Dst.MemOpOffset)
1197 for (
const Value *SrcObj : Src.UnderlyingObjs)
1198 for (
const Value *DstObj : Dst.UnderlyingObjs)
1206void LoopCarriedOrderDepsTracker::NoBarrierInstsChunk::append(SUnit *SU) {
1209 Stores.emplace_back(SU);
1210 else if (
MI->mayLoad())
1211 Loads.emplace_back(SU);
1212 else if (
MI->mayRaiseFPException())
1213 FPExceptions.emplace_back(SU);
1221 : DAG(SSD), BAA(BAA), SUnits(DAG->SUnits), N(SUnits.
size()),
1222 LoopCarried(N,
BitVector(N)), TII(TII), TRI(TRI) {}
1226 for (
auto &SU : SUnits) {
1227 auto Tagged = getInstrTag(&SU);
1232 TaggedSUnits.emplace_back(&SU, *Tagged);
1235 computeDependenciesAux();
1238std::optional<LoopCarriedOrderDepsTracker::InstrTag>
1239LoopCarriedOrderDepsTracker::getInstrTag(
SUnit *SU)
const {
1241 if (
TII->isGlobalMemoryObject(
MI))
1242 return InstrTag::Barrier;
1244 if (
MI->mayStore() ||
1245 (
MI->mayLoad() && !
MI->isDereferenceableInvariantLoad()))
1246 return InstrTag::LoadOrStore;
1248 if (
MI->mayRaiseFPException())
1249 return InstrTag::FPExceptions;
1251 return std::nullopt;
1254void LoopCarriedOrderDepsTracker::addDependenciesBetweenSUs(
1255 const SUnitWithMemInfo &Src,
const SUnitWithMemInfo &Dst) {
1257 if (Src.SU == Dst.SU)
1261 setLoopCarriedDep(Src.SU, Dst.SU);
1264void LoopCarriedOrderDepsTracker::addLoopCarriedDepenenciesForChunks(
1265 const NoBarrierInstsChunk &From,
const NoBarrierInstsChunk &To) {
1267 for (
const SUnitWithMemInfo &Src : From.Loads)
1268 for (
const SUnitWithMemInfo &Dst : To.Stores)
1269 addDependenciesBetweenSUs(Src, Dst);
1272 for (
const SUnitWithMemInfo &Src : From.Stores)
1273 for (
const SUnitWithMemInfo &Dst : To.Loads)
1274 addDependenciesBetweenSUs(Src, Dst);
1277 for (
const SUnitWithMemInfo &Src : From.Stores)
1278 for (
const SUnitWithMemInfo &Dst : To.Stores)
1279 addDependenciesBetweenSUs(Src, Dst);
1282void LoopCarriedOrderDepsTracker::computeDependenciesAux() {
1284 SUnit *FirstBarrier =
nullptr;
1285 SUnit *LastBarrier =
nullptr;
1286 for (
const auto &TSU : TaggedSUnits) {
1287 InstrTag
Tag = TSU.getTag();
1288 SUnit *SU = TSU.getPointer();
1290 case InstrTag::Barrier:
1294 Chunks.emplace_back();
1296 case InstrTag::LoadOrStore:
1297 case InstrTag::FPExceptions:
1298 Chunks.back().append(SU);
1306 for (
const NoBarrierInstsChunk &Chunk : Chunks)
1307 addLoopCarriedDepenenciesForChunks(Chunk, Chunk);
1336 assert(LastBarrier &&
"Both barriers should be set.");
1339 for (
const SUnitWithMemInfo &Dst : Chunks.front().Loads)
1340 setLoopCarriedDep(LastBarrier, Dst.SU);
1341 for (
const SUnitWithMemInfo &Dst : Chunks.front().Stores)
1342 setLoopCarriedDep(LastBarrier, Dst.SU);
1343 for (
const SUnitWithMemInfo &Dst : Chunks.front().FPExceptions)
1344 setLoopCarriedDep(LastBarrier, Dst.SU);
1347 for (
const SUnitWithMemInfo &Src : Chunks.back().Loads)
1348 setLoopCarriedDep(Src.SU, FirstBarrier);
1349 for (
const SUnitWithMemInfo &Src : Chunks.back().Stores)
1350 setLoopCarriedDep(Src.SU, FirstBarrier);
1351 for (
const SUnitWithMemInfo &Src : Chunks.back().FPExceptions)
1352 setLoopCarriedDep(Src.SU, FirstBarrier);
1355 if (FirstBarrier != LastBarrier)
1356 setLoopCarriedDep(LastBarrier, FirstBarrier);
1365LoopCarriedEdges SwingSchedulerDAG::addLoopCarriedDependences() {
1366 LoopCarriedEdges LCE;
1370 LCODTracker.computeDependencies();
1371 for (
unsigned I = 0;
I != SUnits.size();
I++)
1372 for (
const int Succ : LCODTracker.getLoopCarried(
I).set_bits())
1385void SwingSchedulerDAG::updatePhiDependences() {
1387 const TargetSubtargetInfo &
ST = MF.
getSubtarget<TargetSubtargetInfo>();
1390 for (SUnit &
I : SUnits) {
1395 MachineInstr *
MI =
I.getInstr();
1397 for (
const MachineOperand &MO :
MI->operands()) {
1410 MachineInstr *
UseMI = &*UI;
1411 SUnit *SU = getSUnit(
UseMI);
1437 }
else if (MO.isUse()) {
1440 if (
DefMI ==
nullptr)
1442 SUnit *SU = getSUnit(
DefMI);
1447 ST.adjustSchedDependency(SU, 0, &
I, MO.getOperandNo(), Dep,
1454 if (SU->
NodeNum <
I.NodeNum && !
I.isPred(SU))
1463 for (
auto &PI :
I.Preds) {
1464 MachineInstr *PMI = PI.getSUnit()->getInstr();
1466 if (
I.getInstr()->isPHI()) {
1475 for (
const SDep &
D : RemoveDeps)
1482void SwingSchedulerDAG::changeDependences() {
1486 for (SUnit &
I : SUnits) {
1487 unsigned BasePos = 0, OffsetPos = 0;
1489 int64_t NewOffset = 0;
1490 if (!canUseLastOffsetValue(
I.getInstr(), BasePos, OffsetPos, NewBase,
1495 Register OrigBase =
I.getInstr()->getOperand(BasePos).getReg();
1499 SUnit *DefSU = getSUnit(
DefMI);
1506 SUnit *LastSU = getSUnit(LastMI);
1510 if (Topo.IsReachable(&
I, LastSU))
1515 for (
const SDep &
P :
I.Preds)
1516 if (
P.getSUnit() == DefSU)
1518 for (
const SDep &
D : Deps) {
1519 Topo.RemovePred(&
I,
D.getSUnit());
1524 for (
auto &
P : LastSU->
Preds)
1527 for (
const SDep &
D : Deps) {
1528 Topo.RemovePred(LastSU,
D.getSUnit());
1535 Topo.AddPred(LastSU, &
I);
1540 InstrChanges[&
I] = std::make_pair(NewBase, NewOffset);
1551 std::vector<MachineInstr *> &OrderedInsts,
1559 Stage <= LastStage; ++Stage) {
1562 Instrs[Cycle].push_front(SU);
1569 std::deque<SUnit *> &CycleInstrs = Instrs[Cycle];
1571 for (
SUnit *SU : CycleInstrs) {
1573 OrderedInsts.push_back(
MI);
1583struct FuncUnitSorter {
1584 const InstrItineraryData *InstrItins;
1585 const MCSubtargetInfo *STI;
1586 DenseMap<InstrStage::FuncUnits, unsigned>
Resources;
1588 FuncUnitSorter(
const TargetSubtargetInfo &TSI)
1589 : InstrItins(TSI.getInstrItineraryData()), STI(&TSI) {}
1594 unsigned minFuncUnits(
const MachineInstr *Inst,
1597 unsigned min = UINT_MAX;
1598 if (InstrItins && !InstrItins->
isEmpty()) {
1599 for (
const InstrStage &IS :
1601 InstrItins->
endStage(SchedClass))) {
1604 if (numAlternatives <
min) {
1605 min = numAlternatives;
1612 const MCSchedClassDesc *SCDesc =
1619 for (
const MCWriteProcResEntry &PRE :
1622 if (!PRE.ReleaseAtCycle)
1624 const MCProcResourceDesc *ProcResource =
1626 unsigned NumUnits = ProcResource->
NumUnits;
1627 if (NumUnits <
min) {
1629 F = PRE.ProcResourceIdx;
1634 llvm_unreachable(
"Should have non-empty InstrItins or hasInstrSchedModel!");
1642 void calcCriticalResources(MachineInstr &
MI) {
1643 unsigned SchedClass =
MI.getDesc().getSchedClass();
1644 if (InstrItins && !InstrItins->
isEmpty()) {
1645 for (
const InstrStage &IS :
1647 InstrItins->
endStage(SchedClass))) {
1655 const MCSchedClassDesc *SCDesc =
1662 for (
const MCWriteProcResEntry &PRE :
1665 if (!PRE.ReleaseAtCycle)
1671 llvm_unreachable(
"Should have non-empty InstrItins or hasInstrSchedModel!");
1675 bool operator()(
const MachineInstr *IS1,
const MachineInstr *IS2)
const {
1677 unsigned MFUs1 = minFuncUnits(IS1, F1);
1678 unsigned MFUs2 = minFuncUnits(IS2, F2);
1681 return MFUs1 > MFUs2;
1686class HighRegisterPressureDetector {
1687 MachineBasicBlock *OrigMBB;
1688 const MachineRegisterInfo &MRI;
1689 const TargetRegisterInfo *
TRI;
1691 const unsigned PSetNum;
1697 std::vector<unsigned> InitSetPressure;
1701 std::vector<unsigned> PressureSetLimit;
1703 DenseMap<MachineInstr *, RegisterOperands> ROMap;
1705 using Instr2LastUsesTy = DenseMap<MachineInstr *, SmallDenseSet<Register, 4>>;
1708 using OrderedInstsTy = std::vector<MachineInstr *>;
1709 using Instr2StageTy = DenseMap<MachineInstr *, unsigned>;
1712 static void dumpRegisterPressures(
const std::vector<unsigned> &Pressures) {
1713 if (Pressures.size() == 0) {
1717 for (
unsigned P : Pressures) {
1728 VirtRegOrUnit VRegOrUnit =
1730 : VirtRegOrUnit(static_cast<MCRegUnit>(
Reg.id()));
1733 dbgs() << *PSetIter <<
' ';
1738 void increaseRegisterPressure(std::vector<unsigned> &Pressure,
1741 VirtRegOrUnit VRegOrUnit =
1743 : VirtRegOrUnit(static_cast<MCRegUnit>(
Reg.id()));
1746 for (; PSetIter.isValid(); ++PSetIter)
1747 Pressure[*PSetIter] += Weight;
1750 void decreaseRegisterPressure(std::vector<unsigned> &Pressure,
1753 unsigned Weight = PSetIter.getWeight();
1754 for (; PSetIter.isValid(); ++PSetIter) {
1755 auto &
P = Pressure[*PSetIter];
1757 "register pressure must be greater than or equal weight");
1779 void computeLiveIn() {
1780 DenseSet<Register>
Used;
1781 for (
auto &
MI : *OrigMBB) {
1782 if (
MI.isDebugInstr())
1784 for (
auto &Use : ROMap[&
MI].
Uses) {
1787 Use.VRegOrUnit.isVirtualReg()
1788 ?
Use.VRegOrUnit.asVirtualReg()
1789 :
Register(
static_cast<unsigned>(
Use.VRegOrUnit.asMCRegUnit()));
1794 if (isReservedRegister(
Reg))
1796 if (isDefinedInThisLoop(
Reg))
1802 for (
auto LiveIn : Used)
1803 increaseRegisterPressure(InitSetPressure, LiveIn);
1807 void computePressureSetLimit(
const RegisterClassInfo &RCI) {
1808 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1823 Instr2LastUsesTy computeLastUses(
const OrderedInstsTy &OrderedInsts,
1824 Instr2StageTy &Stages)
const {
1829 DenseSet<Register> TargetRegs;
1830 const auto UpdateTargetRegs = [
this, &TargetRegs](
Register Reg) {
1831 if (isDefinedInThisLoop(
Reg))
1834 for (MachineInstr *
MI : OrderedInsts) {
1837 UpdateTargetRegs(
Reg);
1839 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses) {
1842 ?
Use.VRegOrUnit.asVirtualReg()
1844 Use.VRegOrUnit.asMCRegUnit()));
1845 UpdateTargetRegs(
Reg);
1850 const auto InstrScore = [&Stages](MachineInstr *
MI) {
1851 return Stages[
MI] +
MI->isPHI();
1854 DenseMap<Register, MachineInstr *> LastUseMI;
1856 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses) {
1859 Use.VRegOrUnit.isVirtualReg()
1860 ?
Use.VRegOrUnit.asVirtualReg()
1861 :
Register(
static_cast<unsigned>(
Use.VRegOrUnit.asMCRegUnit()));
1866 MachineInstr *Orig = Ite->second;
1867 MachineInstr *
New =
MI;
1868 if (InstrScore(Orig) < InstrScore(New))
1874 Instr2LastUsesTy LastUses;
1875 for (
auto [
Reg,
MI] : LastUseMI)
1876 LastUses[
MI].insert(
Reg);
1892 std::vector<unsigned>
1893 computeMaxSetPressure(
const OrderedInstsTy &OrderedInsts,
1894 Instr2StageTy &Stages,
1895 const unsigned StageCount)
const {
1896 using RegSetTy = SmallDenseSet<Register, 16>;
1902 auto CurSetPressure = InitSetPressure;
1903 auto MaxSetPressure = InitSetPressure;
1904 auto LastUses = computeLastUses(OrderedInsts, Stages);
1907 dbgs() <<
"Ordered instructions:\n";
1908 for (MachineInstr *
MI : OrderedInsts) {
1909 dbgs() <<
"Stage " << Stages[
MI] <<
": ";
1914 const auto InsertReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1915 VirtRegOrUnit VRegOrUnit) {
1929 increaseRegisterPressure(CurSetPressure,
Reg);
1933 const auto EraseReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1939 if (!RegSet.contains(
Reg))
1944 decreaseRegisterPressure(CurSetPressure,
Reg);
1948 for (
unsigned I = 0;
I < StageCount;
I++) {
1949 for (MachineInstr *
MI : OrderedInsts) {
1950 const auto Stage = Stages[
MI];
1954 const unsigned Iter =
I - Stage;
1956 for (
auto &Def : ROMap.
find(
MI)->getSecond().Defs)
1957 InsertReg(LiveRegSets[Iter],
Def.VRegOrUnit);
1959 for (
auto LastUse : LastUses[
MI]) {
1962 EraseReg(LiveRegSets[Iter - 1], LastUse);
1964 EraseReg(LiveRegSets[Iter], LastUse);
1968 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1969 MaxSetPressure[PSet] =
1970 std::max(MaxSetPressure[PSet], CurSetPressure[PSet]);
1973 dbgs() <<
"CurSetPressure=";
1974 dumpRegisterPressures(CurSetPressure);
1975 dbgs() <<
" iter=" << Iter <<
" stage=" << Stage <<
":";
1981 return MaxSetPressure;
1985 HighRegisterPressureDetector(MachineBasicBlock *OrigMBB,
1987 : OrigMBB(OrigMBB), MRI(MF.getRegInfo()),
1988 TRI(MF.getSubtarget().getRegisterInfo()),
1989 PSetNum(
TRI->getNumRegPressureSets()), InitSetPressure(PSetNum, 0),
1990 PressureSetLimit(PSetNum, 0) {}
1994 void init(
const RegisterClassInfo &RCI) {
1995 for (MachineInstr &
MI : *OrigMBB) {
1996 if (
MI.isDebugInstr())
1998 ROMap[&
MI].collect(
MI, *
TRI, MRI,
false,
true);
2002 computePressureSetLimit(RCI);
2007 bool detect(
const SwingSchedulerDAG *SSD, SMSchedule &Schedule,
2008 const unsigned MaxStage)
const {
2010 "the percentage of the margin must be between 0 to 100");
2012 OrderedInstsTy OrderedInsts;
2013 Instr2StageTy Stages;
2015 const auto MaxSetPressure =
2016 computeMaxSetPressure(OrderedInsts, Stages, MaxStage + 1);
2019 dbgs() <<
"Dump MaxSetPressure:\n";
2020 for (
unsigned I = 0;
I < MaxSetPressure.size();
I++) {
2021 dbgs() <<
format(
"MaxSetPressure[%d]=%d\n",
I, MaxSetPressure[
I]);
2026 for (
unsigned PSet = 0; PSet < PSetNum; PSet++) {
2027 unsigned Limit = PressureSetLimit[PSet];
2030 <<
" Margin=" << Margin <<
"\n");
2031 if (Limit < MaxSetPressure[PSet] + Margin) {
2034 <<
"Rejected the schedule because of too high register pressure\n");
2050unsigned SwingSchedulerDAG::calculateResMII() {
2053 return RM.calculateResMII();
2062unsigned SwingSchedulerDAG::calculateRecMII(NodeSetType &NodeSets) {
2063 unsigned RecMII = 0;
2065 for (NodeSet &Nodes : NodeSets) {
2069 unsigned Delay = Nodes.getLatency();
2070 unsigned Distance = 1;
2073 unsigned CurMII = (Delay + Distance - 1) / Distance;
2074 Nodes.setRecMII(CurMII);
2075 if (CurMII > RecMII)
2083void SwingSchedulerDAG::Circuits::createAdjacencyStructure(
2084 SwingSchedulerDDG *DDG) {
2085 BitVector
Added(SUnits.size());
2086 DenseMap<int, int> OutputDeps;
2087 for (
int i = 0, e = SUnits.size(); i != e; ++i) {
2093 if (OE.isOutputDep()) {
2094 int N = OE.getDst()->NodeNum;
2096 auto Dep = OutputDeps.
find(BackEdge);
2097 if (Dep != OutputDeps.
end()) {
2098 BackEdge = Dep->second;
2099 OutputDeps.
erase(Dep);
2101 OutputDeps[
N] = BackEdge;
2104 if (OE.getDst()->isBoundaryNode() || OE.isArtificial())
2116 int N = OE.getDst()->NodeNum;
2118 AdjK[i].push_back(
N);
2125 int N = Dst->NodeNum;
2127 AdjK[i].push_back(
N);
2134 for (
auto &OD : OutputDeps)
2135 if (!
Added.test(OD.second)) {
2136 AdjK[OD.first].push_back(OD.second);
2137 Added.set(OD.second);
2143bool SwingSchedulerDAG::Circuits::circuit(
int V,
int S, NodeSetType &NodeSets,
2144 const SwingSchedulerDAG *DAG,
2146 SUnit *
SV = &SUnits[
V];
2151 for (
auto W : AdjK[V]) {
2152 if (NumPaths > MaxPaths)
2163 if (!Blocked.test(W)) {
2164 if (circuit(W, S, NodeSets, DAG,
2165 Node2Idx->at(W) < Node2Idx->at(V) ?
true : HasBackedge))
2173 for (
auto W : AdjK[V]) {
2184void SwingSchedulerDAG::Circuits::unblock(
int U) {
2186 SmallPtrSet<SUnit *, 4> &BU =
B[
U];
2187 while (!BU.
empty()) {
2188 SmallPtrSet<SUnit *, 4>::iterator
SI = BU.
begin();
2189 assert(SI != BU.
end() &&
"Invalid B set.");
2192 if (Blocked.test(
W->NodeNum))
2193 unblock(
W->NodeNum);
2199void SwingSchedulerDAG::findCircuits(NodeSetType &NodeSets) {
2200 Circuits Cir(SUnits, Topo);
2202 Cir.createAdjacencyStructure(&*DDG);
2203 for (
int I = 0,
E = SUnits.size();
I !=
E; ++
I) {
2205 Cir.circuit(
I,
I, NodeSets,
this);
2227void SwingSchedulerDAG::CopyToPhiMutation::apply(ScheduleDAGInstrs *DAG) {
2228 for (SUnit &SU : DAG->
SUnits) {
2238 for (
auto &Dep : SU.
Preds) {
2239 SUnit *TmpSU = Dep.getSUnit();
2240 MachineInstr *TmpMI = TmpSU->
getInstr();
2251 if (PHISUs.
size() == 0 || SrcSUs.
size() == 0)
2259 for (
auto &Dep : PHISUs[Index]->Succs) {
2263 SUnit *TmpSU = Dep.getSUnit();
2264 MachineInstr *TmpMI = TmpSU->
getInstr();
2273 if (UseSUs.
size() == 0)
2278 for (
auto *
I : UseSUs) {
2279 for (
auto *Src : SrcSUs) {
2295void SwingSchedulerDAG::computeNodeFunctions(NodeSetType &NodeSets) {
2296 ScheduleInfo.resize(SUnits.size());
2299 for (
int I : Topo) {
2300 const SUnit &SU = SUnits[
I];
2307 for (
int I : Topo) {
2309 int zeroLatencyDepth = 0;
2310 SUnit *SU = &SUnits[
I];
2312 SUnit *Pred =
IE.getSrc();
2313 if (
IE.getLatency() == 0)
2315 std::max(zeroLatencyDepth, getZeroLatencyDepth(Pred) + 1);
2316 if (
IE.ignoreDependence(
true))
2318 asap = std::max(asap, (
int)(getASAP(Pred) +
IE.getLatency() -
2319 IE.getDistance() * MII));
2321 maxASAP = std::max(maxASAP, asap);
2322 ScheduleInfo[
I].ASAP = asap;
2323 ScheduleInfo[
I].ZeroLatencyDepth = zeroLatencyDepth;
2329 int zeroLatencyHeight = 0;
2330 SUnit *SU = &SUnits[
I];
2332 SUnit *Succ = OE.getDst();
2335 if (OE.getLatency() == 0)
2337 std::max(zeroLatencyHeight, getZeroLatencyHeight(Succ) + 1);
2338 if (OE.ignoreDependence(
true))
2340 alap = std::min(alap, (
int)(getALAP(Succ) - OE.getLatency() +
2341 OE.getDistance() * MII));
2344 ScheduleInfo[
I].ALAP = alap;
2345 ScheduleInfo[
I].ZeroLatencyHeight = zeroLatencyHeight;
2349 for (NodeSet &
I : NodeSets)
2350 I.computeNodeSetInfo(
this);
2353 for (
unsigned i = 0; i < SUnits.size(); i++) {
2354 dbgs() <<
"\tNode " << i <<
":\n";
2355 dbgs() <<
"\t ASAP = " << getASAP(&SUnits[i]) <<
"\n";
2356 dbgs() <<
"\t ALAP = " << getALAP(&SUnits[i]) <<
"\n";
2357 dbgs() <<
"\t MOV = " << getMOV(&SUnits[i]) <<
"\n";
2358 dbgs() <<
"\t D = " << getDepth(&SUnits[i]) <<
"\n";
2359 dbgs() <<
"\t H = " << getHeight(&SUnits[i]) <<
"\n";
2360 dbgs() <<
"\t ZLD = " << getZeroLatencyDepth(&SUnits[i]) <<
"\n";
2361 dbgs() <<
"\t ZLH = " << getZeroLatencyHeight(&SUnits[i]) <<
"\n";
2376 SUnit *PredSU = IE.getSrc();
2377 if (S && S->count(PredSU) == 0)
2379 if (IE.ignoreDependence(
true))
2390 SUnit *SuccSU = OE.getDst();
2391 if (!OE.isAntiDep())
2393 if (S && S->count(SuccSU) == 0)
2399 return !Preds.
empty();
2412 SUnit *SuccSU = OE.getDst();
2413 if (S && S->count(SuccSU) == 0)
2415 if (OE.ignoreDependence(
false))
2426 SUnit *PredSU = IE.getSrc();
2427 if (!IE.isAntiDep())
2429 if (S && S->count(PredSU) == 0)
2435 return !Succs.
empty();
2451 if (!Visited.
insert(Cur).second)
2452 return Path.contains(Cur);
2453 bool FoundPath =
false;
2455 if (!OE.ignoreDependence(
false))
2457 computePath(OE.getDst(), Path, DestNodes, Exclude, Visited, DDG);
2459 if (IE.isAntiDep() && IE.getDistance() == 0)
2461 computePath(IE.getSrc(), Path, DestNodes, Exclude, Visited, DDG);
2476 for (
SUnit *SU : NS) {
2482 if (
Reg.isVirtual())
2485 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2489 for (
SUnit *SU : NS)
2493 if (
Reg.isVirtual()) {
2498 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2509void SwingSchedulerDAG::registerPressureFilter(NodeSetType &NodeSets) {
2510 for (
auto &NS : NodeSets) {
2514 IntervalPressure RecRegPressure;
2515 RegPressureTracker RecRPTracker(RecRegPressure);
2516 RecRPTracker.init(&MF, &RegClassInfo, &LIS, BB, BB->end(),
false,
true);
2518 RecRPTracker.closeBottom();
2520 std::vector<SUnit *> SUnits(NS.begin(), NS.end());
2521 llvm::sort(SUnits, [](
const SUnit *
A,
const SUnit *
B) {
2522 return A->NodeNum >
B->NodeNum;
2525 for (
auto &SU : SUnits) {
2531 RecRPTracker.setPos(std::next(CurInstI));
2533 RegPressureDelta RPDelta;
2535 RecRPTracker.getMaxUpwardPressureDelta(SU->
getInstr(),
nullptr, RPDelta,
2540 dbgs() <<
"Excess register pressure: SU(" << SU->
NodeNum <<
") "
2543 NS.setExceedPressure(SU);
2546 RecRPTracker.recede();
2553void SwingSchedulerDAG::colocateNodeSets(NodeSetType &NodeSets) {
2554 unsigned Colocate = 0;
2555 for (
int i = 0, e = NodeSets.size(); i < e; ++i) {
2557 SmallSetVector<SUnit *, 8>
S1;
2560 for (
int j = i + 1;
j <
e; ++
j) {
2564 SmallSetVector<SUnit *, 8> S2;
2581void SwingSchedulerDAG::checkNodeSets(NodeSetType &NodeSets) {
2586 for (
auto &NS : NodeSets) {
2587 if (NS.getRecMII() > 2)
2589 if (NS.getMaxDepth() > MII)
2598void SwingSchedulerDAG::groupRemainingNodes(NodeSetType &NodeSets) {
2599 SetVector<SUnit *> NodesAdded;
2600 SmallPtrSet<SUnit *, 8> Visited;
2603 for (NodeSet &
I : NodeSets) {
2604 SmallSetVector<SUnit *, 8>
N;
2607 SetVector<SUnit *>
Path;
2608 for (SUnit *NI :
N) {
2610 computePath(NI, Path, NodesAdded,
I, Visited, DDG.get());
2617 if (
succ_L(NodesAdded,
N, DDG.get())) {
2618 SetVector<SUnit *>
Path;
2619 for (SUnit *NI :
N) {
2621 computePath(NI, Path,
I, NodesAdded, Visited, DDG.get());
2632 SmallSetVector<SUnit *, 8>
N;
2633 if (
succ_L(NodesAdded,
N, DDG.get()))
2635 addConnectedNodes(
I, NewSet, NodesAdded);
2636 if (!NewSet.
empty())
2637 NodeSets.push_back(NewSet);
2642 if (
pred_L(NodesAdded,
N, DDG.get()))
2644 addConnectedNodes(
I, NewSet, NodesAdded);
2645 if (!NewSet.
empty())
2646 NodeSets.push_back(NewSet);
2650 for (SUnit &SU : SUnits) {
2651 if (NodesAdded.
count(&SU) == 0) {
2653 addConnectedNodes(&SU, NewSet, NodesAdded);
2654 if (!NewSet.
empty())
2655 NodeSets.push_back(NewSet);
2661void SwingSchedulerDAG::addConnectedNodes(SUnit *SU, NodeSet &NewSet,
2662 SetVector<SUnit *> &NodesAdded) {
2667 if (!OE.isArtificial() && !
Successor->isBoundaryNode() &&
2669 addConnectedNodes(
Successor, NewSet, NodesAdded);
2672 SUnit *Predecessor =
IE.getSrc();
2673 if (!
IE.isArtificial() && NodesAdded.
count(Predecessor) == 0)
2674 addConnectedNodes(Predecessor, NewSet, NodesAdded);
2683 for (
SUnit *SU : Set1) {
2684 if (Set2.
count(SU) != 0)
2687 return !Result.empty();
2691void SwingSchedulerDAG::fuseRecs(NodeSetType &NodeSets) {
2692 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2695 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2700 for (SUnit *SU : *J)
2712void SwingSchedulerDAG::removeDuplicateNodes(NodeSetType &NodeSets) {
2713 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2715 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2716 J->remove_if([&](SUnit *SUJ) {
return I->count(SUJ); });
2731void SwingSchedulerDAG::computeNodeOrder(NodeSetType &NodeSets) {
2732 SmallSetVector<SUnit *, 8>
R;
2735 for (
auto &Nodes : NodeSets) {
2738 SmallSetVector<SUnit *, 8>
N;
2753 }
else if (NodeSets.size() == 1) {
2754 for (
const auto &
N : Nodes)
2755 if (
N->Succs.size() == 0)
2761 SUnit *maxASAP =
nullptr;
2762 for (SUnit *SU : Nodes) {
2763 if (maxASAP ==
nullptr || getASAP(SU) > getASAP(maxASAP) ||
2764 (getASAP(SU) == getASAP(maxASAP) && SU->
NodeNum > maxASAP->
NodeNum))
2772 while (!
R.empty()) {
2773 if (Order == TopDown) {
2777 while (!
R.empty()) {
2778 SUnit *maxHeight =
nullptr;
2779 for (SUnit *
I : R) {
2780 if (maxHeight ==
nullptr || getHeight(
I) > getHeight(maxHeight))
2782 else if (getHeight(
I) == getHeight(maxHeight) &&
2783 getZeroLatencyHeight(
I) > getZeroLatencyHeight(maxHeight))
2785 else if (getHeight(
I) == getHeight(maxHeight) &&
2786 getZeroLatencyHeight(
I) ==
2787 getZeroLatencyHeight(maxHeight) &&
2788 getMOV(
I) < getMOV(maxHeight))
2793 R.remove(maxHeight);
2794 for (
const auto &OE : DDG->
getOutEdges(maxHeight)) {
2795 SUnit *SU = OE.getDst();
2796 if (Nodes.count(SU) == 0)
2800 if (OE.ignoreDependence(
false))
2809 for (
const auto &IE : DDG->
getInEdges(maxHeight)) {
2810 SUnit *SU =
IE.getSrc();
2811 if (!
IE.isAntiDep())
2813 if (Nodes.count(SU) == 0)
2822 SmallSetVector<SUnit *, 8>
N;
2829 while (!
R.empty()) {
2830 SUnit *maxDepth =
nullptr;
2831 for (SUnit *
I : R) {
2832 if (maxDepth ==
nullptr || getDepth(
I) > getDepth(maxDepth))
2834 else if (getDepth(
I) == getDepth(maxDepth) &&
2835 getZeroLatencyDepth(
I) > getZeroLatencyDepth(maxDepth))
2837 else if (getDepth(
I) == getDepth(maxDepth) &&
2838 getZeroLatencyDepth(
I) == getZeroLatencyDepth(maxDepth) &&
2839 getMOV(
I) < getMOV(maxDepth))
2845 if (Nodes.isExceedSU(maxDepth)) {
2848 R.insert(Nodes.getNode(0));
2851 for (
const auto &IE : DDG->
getInEdges(maxDepth)) {
2852 SUnit *SU =
IE.getSrc();
2853 if (Nodes.count(SU) == 0)
2864 for (
const auto &OE : DDG->
getOutEdges(maxDepth)) {
2865 SUnit *SU = OE.getDst();
2866 if (!OE.isAntiDep())
2868 if (Nodes.count(SU) == 0)
2877 SmallSetVector<SUnit *, 8>
N;
2886 dbgs() <<
"Node order: ";
2888 dbgs() <<
" " <<
I->NodeNum <<
" ";
2894void SwingSchedulerDAG::initPolicy() {
2904bool SwingSchedulerDAG::schedulePipeline(SMSchedule &Schedule) {
2911 bool scheduleFound =
false;
2912 std::unique_ptr<HighRegisterPressureDetector> HRPDetector;
2913 if (Policy.ShouldLimitRegPressure) {
2915 std::make_unique<HighRegisterPressureDetector>(
Loop.getHeader(), MF);
2916 HRPDetector->init(RegClassInfo);
2919 for (
unsigned II = MII;
II <= MAX_II && !scheduleFound; ++
II) {
2931 int EarlyStart = INT_MIN;
2932 int LateStart = INT_MAX;
2941 dbgs() <<
format(
"\tes: %8x ls: %8x\n", EarlyStart, LateStart));
2943 if (EarlyStart > LateStart)
2944 scheduleFound =
false;
2945 else if (EarlyStart != INT_MIN && LateStart == INT_MAX)
2947 Schedule.
insert(SU, EarlyStart, EarlyStart + (
int)
II - 1,
II);
2948 else if (EarlyStart == INT_MIN && LateStart != INT_MAX)
2950 Schedule.
insert(SU, LateStart, LateStart - (
int)
II + 1,
II);
2951 else if (EarlyStart != INT_MIN && LateStart != INT_MAX) {
2952 LateStart = std::min(LateStart, EarlyStart + (
int)
II - 1);
2961 scheduleFound = Schedule.
insert(SU, LateStart, EarlyStart,
II);
2963 scheduleFound = Schedule.
insert(SU, EarlyStart, LateStart,
II);
2966 scheduleFound = Schedule.
insert(SU, FirstCycle + getASAP(SU),
2967 FirstCycle + getASAP(SU) +
II - 1,
II);
2975 scheduleFound =
false;
2979 dbgs() <<
"\tCan't schedule\n";
2981 }
while (++NI != NE && scheduleFound);
2999 if (scheduleFound && HRPDetector)
3008 if (scheduleFound) {
3009 scheduleFound = LoopPipelinerInfo->shouldUseSchedule(*
this, Schedule);
3014 if (scheduleFound) {
3017 return MachineOptimizationRemarkAnalysis(
3019 <<
"Schedule found with Initiation Interval: "
3021 <<
", MaxStageCount: "
3035 if (!
Reg.isVirtual())
3050 if (!
Op.isReg() || !
Op.getReg().isVirtual())
3078 if (Def->getParent() != LoopBB)
3081 if (Def->isCopy()) {
3083 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
3085 CurReg = Def->getOperand(1).getReg();
3086 }
else if (Def->isPHI()) {
3092 }
else if (
TII->getIncrementValue(*Def,
Value)) {
3100 bool OffsetIsScalable;
3101 if (
TII->getMemOperandWithOffset(*Def, BaseOp,
Offset, OffsetIsScalable,
3104 CurReg = BaseOp->
getReg();
3116 if (CurReg == OrgReg)
3128bool SwingSchedulerDAG::computeDelta(
const MachineInstr &
MI,
int &Delta)
const {
3130 const MachineOperand *BaseOp;
3132 bool OffsetIsScalable;
3133 if (!
TII->getMemOperandWithOffset(
MI, BaseOp,
Offset, OffsetIsScalable,
TRI))
3137 if (OffsetIsScalable)
3140 if (!BaseOp->
isReg())
3153bool SwingSchedulerDAG::canUseLastOffsetValue(MachineInstr *
MI,
3155 unsigned &OffsetPos,
3161 unsigned BasePosLd, OffsetPosLd;
3169 if (!Phi || !
Phi->isPHI())
3177 MachineInstr *PrevDef = MRI.
getVRegDef(PrevReg);
3178 if (!PrevDef || PrevDef ==
MI)
3184 unsigned BasePos1 = 0, OffsetPos1 = 0;
3192 MachineInstr *NewMI = MF.CloneMachineInstr(
MI);
3195 MF.deleteMachineInstr(NewMI);
3200 BasePos = BasePosLd;
3201 OffsetPos = OffsetPosLd;
3213 InstrChanges.find(SU);
3214 if (It != InstrChanges.
end()) {
3215 std::pair<Register, int64_t> RegAndOffset = It->second;
3216 unsigned BasePos, OffsetPos;
3217 if (!
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3219 Register BaseReg =
MI->getOperand(BasePos).getReg();
3225 if (BaseStageNum < DefStageNum) {
3227 int OffsetDiff = DefStageNum - BaseStageNum;
3228 if (DefCycleNum < BaseCycleNum) {
3234 MI->getOperand(OffsetPos).getImm() + RegAndOffset.second * OffsetDiff;
3249 while (Def->isPHI()) {
3250 if (!Visited.
insert(Def).second)
3252 for (
unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2)
3253 if (Def->getOperand(i + 1).getMBB() == BB) {
3254 Def = MRI.
getVRegDef(Def->getOperand(i).getReg());
3265 int DeltaB, DeltaO, Delta;
3272 int64_t OffsetB, OffsetO;
3273 bool OffsetBIsScalable, OffsetOIsScalable;
3275 if (!
TII->getMemOperandWithOffset(*BaseMI, BaseOpB, OffsetB,
3276 OffsetBIsScalable,
TRI) ||
3277 !
TII->getMemOperandWithOffset(*OtherMI, BaseOpO, OffsetO,
3278 OffsetOIsScalable,
TRI))
3281 if (OffsetBIsScalable || OffsetOIsScalable)
3291 if (!RegB.
isVirtual() || !RegO.isVirtual())
3296 if (!DefB || !DefO || !DefB->
isPHI() || !DefO->
isPHI())
3321 dbgs() <<
"Overlap check:\n";
3322 dbgs() <<
" BaseMI: ";
3324 dbgs() <<
" Base + " << OffsetB <<
" + I * " << Delta
3325 <<
", Len: " << AccessSizeB.
getValue() <<
"\n";
3326 dbgs() <<
" OtherMI: ";
3328 dbgs() <<
" Base + " << OffsetO <<
" + I * " << Delta
3329 <<
", Len: " << AccessSizeO.
getValue() <<
"\n";
3337 int64_t BaseMinAddr = OffsetB;
3338 int64_t OhterNextIterMaxAddr = OffsetO + Delta + AccessSizeO.
getValue() - 1;
3339 if (BaseMinAddr > OhterNextIterMaxAddr) {
3344 int64_t BaseMaxAddr = OffsetB + AccessSizeB.
getValue() - 1;
3345 int64_t OtherNextIterMinAddr = OffsetO + Delta;
3346 if (BaseMaxAddr < OtherNextIterMinAddr) {
3355void SwingSchedulerDAG::postProcessDAG() {
3356 for (
auto &M : Mutations)
3366 bool forward =
true;
3368 dbgs() <<
"Trying to insert node between " << StartCycle <<
" and "
3369 << EndCycle <<
" II: " <<
II <<
"\n";
3371 if (StartCycle > EndCycle)
3375 int termCycle = forward ? EndCycle + 1 : EndCycle - 1;
3376 for (
int curCycle = StartCycle; curCycle != termCycle;
3377 forward ? ++curCycle : --curCycle) {
3380 ProcItinResources.canReserveResources(*SU, curCycle)) {
3382 dbgs() <<
"\tinsert at cycle " << curCycle <<
" ";
3387 ProcItinResources.reserveResources(*SU, curCycle);
3388 ScheduledInstrs[curCycle].push_back(SU);
3389 InstrToCycle.insert(std::make_pair(SU, curCycle));
3390 if (curCycle > LastCycle)
3391 LastCycle = curCycle;
3392 if (curCycle < FirstCycle)
3393 FirstCycle = curCycle;
3397 dbgs() <<
"\tfailed to insert at cycle " << curCycle <<
" ";
3408 for (
auto &
P : SU->
Preds)
3409 if (
P.getKind() ==
SDep::Anti &&
P.getSUnit()->getInstr()->isPHI())
3410 for (
auto &S :
P.getSUnit()->Succs)
3411 if (S.getKind() ==
SDep::Data && S.getSUnit()->getInstr()->isPHI())
3412 return P.getSUnit();
3425 for (
int cycle =
getFirstCycle(); cycle <= LastCycle; ++cycle) {
3428 if (IE.getSrc() ==
I) {
3429 int EarlyStart = cycle + IE.getLatency() - IE.getDistance() *
II;
3430 *MaxEarlyStart = std::max(*MaxEarlyStart, EarlyStart);
3435 if (OE.getDst() ==
I) {
3436 int LateStart = cycle - OE.getLatency() + OE.getDistance() *
II;
3437 *MinLateStart = std::min(*MinLateStart, LateStart);
3442 for (
const auto &Dep : SU->
Preds) {
3445 if (BE && Dep.getSUnit() == BE && !SU->
getInstr()->
isPHI() &&
3447 *MinLateStart = std::min(*MinLateStart, cycle);
3457 std::deque<SUnit *> &Insts)
const {
3459 bool OrderBeforeUse =
false;
3460 bool OrderAfterDef =
false;
3461 bool OrderBeforeDef =
false;
3462 unsigned MoveDef = 0;
3463 unsigned MoveUse = 0;
3468 for (std::deque<SUnit *>::iterator
I = Insts.begin(), E = Insts.end();
I != E;
3471 if (!MO.isReg() || !MO.getReg().isVirtual())
3475 unsigned BasePos, OffsetPos;
3476 if (ST.getInstrInfo()->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3477 if (
MI->getOperand(BasePos).getReg() == Reg)
3481 std::tie(Reads, Writes) =
3482 (*I)->getInstr()->readsWritesVirtualRegister(Reg);
3484 OrderBeforeUse =
true;
3489 OrderAfterDef =
true;
3491 }
else if (MO.isUse() && Writes &&
stageScheduled(*
I) == StageInst1) {
3493 OrderBeforeUse =
true;
3497 OrderAfterDef =
true;
3501 OrderBeforeUse =
true;
3505 OrderAfterDef =
true;
3510 OrderBeforeUse =
true;
3516 OrderBeforeDef =
true;
3524 if (OE.getDst() != *
I)
3527 OrderBeforeUse =
true;
3534 else if ((OE.isAntiDep() || OE.isOutputDep()) &&
3536 OrderBeforeUse =
true;
3537 if ((MoveUse == 0) || (Pos < MoveUse))
3542 if (IE.getSrc() != *
I)
3544 if ((IE.isAntiDep() || IE.isOutputDep() || IE.isOrderDep()) &&
3546 OrderAfterDef =
true;
3553 if (OrderAfterDef && OrderBeforeUse && MoveUse == MoveDef)
3554 OrderBeforeUse =
false;
3559 OrderBeforeUse = !OrderAfterDef || (MoveUse > MoveDef);
3563 if (OrderBeforeUse && OrderAfterDef) {
3564 SUnit *UseSU = Insts.at(MoveUse);
3565 SUnit *DefSU = Insts.at(MoveDef);
3566 if (MoveUse > MoveDef) {
3567 Insts.erase(Insts.begin() + MoveUse);
3568 Insts.erase(Insts.begin() + MoveDef);
3570 Insts.erase(Insts.begin() + MoveDef);
3571 Insts.erase(Insts.begin() + MoveUse);
3581 Insts.push_front(SU);
3583 Insts.push_back(SU);
3591 assert(Phi.isPHI() &&
"Expecting a Phi.");
3598 getPhiRegs(Phi, Phi.getParent(), InitVal, LoopVal);
3606 return (LoopCycle > DefCycle) || (LoopStage <= DefStage);
3624 if (!Phi || !Phi->isPHI() || Phi->getParent() != Def->getParent())
3630 if (DMO.getReg() == LoopReg)
3641 if (InstrToCycle.count(IE.getSrc()))
3652 for (
auto &SU : SSD->
SUnits)
3657 while (!Worklist.
empty()) {
3659 if (DoNotPipeline.
count(SU))
3662 DoNotPipeline.
insert(SU);
3669 if (OE.getDistance() == 1)
3672 return DoNotPipeline;
3681 int NewLastCycle = INT_MIN;
3686 NewLastCycle = std::max(NewLastCycle, InstrToCycle[&SU]);
3693 if (IE.getDistance() == 0)
3694 NewCycle = std::max(InstrToCycle[IE.getSrc()], NewCycle);
3699 if (OE.getDistance() == 1)
3700 NewCycle = std::max(InstrToCycle[OE.getDst()], NewCycle);
3702 int OldCycle = InstrToCycle[&SU];
3703 if (OldCycle != NewCycle) {
3704 InstrToCycle[&SU] = NewCycle;
3709 <<
") is not pipelined; moving from cycle " << OldCycle
3710 <<
" to " << NewCycle <<
" Instr:" << *SU.
getInstr());
3735 if (FirstCycle + InitiationInterval <= NewCycle)
3738 NewLastCycle = std::max(NewLastCycle, NewCycle);
3740 LastCycle = NewLastCycle;
3757 int CycleDef = InstrToCycle[&SU];
3758 assert(StageDef != -1 &&
"Instruction should have been scheduled.");
3760 SUnit *Dst = OE.getDst();
3761 if (OE.isAssignedRegDep() && !Dst->isBoundaryNode())
3762 if (OE.getReg().isPhysical()) {
3765 if (InstrToCycle[Dst] <= CycleDef)
3783void SwingSchedulerDAG::checkValidNodeOrder(
const NodeSetType &Circuits)
const {
3786 typedef std::pair<SUnit *, unsigned> UnitIndex;
3787 std::vector<UnitIndex> Indices(
NodeOrder.size(), std::make_pair(
nullptr, 0));
3789 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i)
3790 Indices.push_back(std::make_pair(
NodeOrder[i], i));
3792 auto CompareKey = [](UnitIndex i1, UnitIndex i2) {
3793 return std::get<0>(i1) < std::get<0>(i2);
3806 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i) {
3810 bool PredBefore =
false;
3811 bool SuccBefore =
false;
3819 SUnit *PredSU = IE.getSrc();
3820 unsigned PredIndex = std::get<1>(
3830 SUnit *SuccSU = OE.getDst();
3836 unsigned SuccIndex = std::get<1>(
3849 Circuits, [SU](
const NodeSet &Circuit) {
return Circuit.
count(SU); });
3854 NumNodeOrderIssues++;
3858 <<
" are scheduled before node " << SU->
NodeNum
3865 dbgs() <<
"Invalid node order found!\n";
3878 for (
SUnit *SU : Instrs) {
3880 for (
unsigned i = 0, e =
MI->getNumOperands(); i < e; ++i) {
3888 InstrChanges.find(SU);
3889 if (It != InstrChanges.
end()) {
3890 unsigned BasePos, OffsetPos;
3892 if (
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos)) {
3896 MI->getOperand(OffsetPos).getImm() - It->second.second;
3909 unsigned TiedUseIdx = 0;
3910 if (
MI->isRegTiedToUseOperand(i, &TiedUseIdx)) {
3912 OverlapReg =
MI->getOperand(TiedUseIdx).getReg();
3914 NewBaseReg =
MI->getOperand(i).getReg();
3923 const std::deque<SUnit *> &Instrs)
const {
3924 std::deque<SUnit *> NewOrderPhi;
3925 for (
SUnit *SU : Instrs) {
3927 NewOrderPhi.push_back(SU);
3929 std::deque<SUnit *> NewOrderI;
3930 for (
SUnit *SU : Instrs) {
3946 std::deque<SUnit *> &cycleInstrs =
3947 ScheduledInstrs[cycle + (stage * InitiationInterval)];
3949 ScheduledInstrs[cycle].push_front(SU);
3955 for (
int cycle =
getFinalCycle() + 1; cycle <= LastCycle; ++cycle)
3956 ScheduledInstrs.erase(cycle);
3966 std::deque<SUnit *> &cycleInstrs = ScheduledInstrs[Cycle];
3975 os <<
"Num nodes " <<
size() <<
" rec " << RecMII <<
" mov " << MaxMOV
3976 <<
" depth " << MaxDepth <<
" col " << Colocate <<
"\n";
3977 for (
const auto &
I : Nodes)
3978 os <<
" SU(" <<
I->NodeNum <<
") " << *(
I->getInstr());
3982#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3989 for (
SUnit *CI : cycleInstrs->second) {
3991 os <<
"(" << CI->
NodeNum <<
") ";
4002void ResourceManager::dumpMRT()
const {
4006 std::stringstream SS;
4008 SS << std::setw(4) <<
"Slot";
4009 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I)
4010 SS << std::setw(3) <<
I;
4011 SS << std::setw(7) <<
"#Mops"
4013 for (
int Slot = 0; Slot < InitiationInterval; ++Slot) {
4014 SS << std::setw(4) << Slot;
4015 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I)
4016 SS << std::setw(3) << MRT[Slot][
I];
4017 SS << std::setw(7) << NumScheduledMops[Slot] <<
"\n";
4026 unsigned ProcResourceID = 0;
4030 assert(SM.getNumProcResourceKinds() < 64 &&
4031 "Too many kinds of resources, unsupported");
4034 Masks.
resize(SM.getNumProcResourceKinds());
4035 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4037 if (
Desc.SubUnitsIdxBegin)
4039 Masks[
I] = 1ULL << ProcResourceID;
4043 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4045 if (!
Desc.SubUnitsIdxBegin)
4047 Masks[
I] = 1ULL << ProcResourceID;
4048 for (
unsigned U = 0; U <
Desc.NumUnits; ++U)
4049 Masks[
I] |= Masks[
Desc.SubUnitsIdxBegin[U]];
4054 dbgs() <<
"ProcResourceDesc:\n";
4055 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4057 dbgs() <<
format(
" %16s(%2d): Mask: 0x%08x, NumUnits:%2d\n",
4058 ProcResource->
Name,
I, Masks[
I],
4061 dbgs() <<
" -----------------\n";
4069 dbgs() <<
"canReserveResources:\n";
4072 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
4078 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
4084 reserveResources(SCDesc, Cycle);
4085 bool Result = !isOverbooked();
4086 unreserveResources(SCDesc, Cycle);
4092void ResourceManager::reserveResources(
SUnit &SU,
int Cycle) {
4095 dbgs() <<
"reserveResources:\n";
4098 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
4104 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
4110 reserveResources(SCDesc, Cycle);
4115 dbgs() <<
"reserveResources: done!\n\n";
4125 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4126 ++MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4129 ++NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4137 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4138 --MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4141 --NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4144bool ResourceManager::isOverbooked()
const {
4146 for (
int Slot = 0;
Slot < InitiationInterval; ++
Slot) {
4147 for (
unsigned I = 1,
E = SM.getNumProcResourceKinds();
I <
E; ++
I) {
4148 const MCProcResourceDesc *
Desc = SM.getProcResource(
I);
4149 if (MRT[Slot][
I] >
Desc->NumUnits)
4152 if (NumScheduledMops[Slot] > IssueWidth)
4158int ResourceManager::calculateResMIIDFA()
const {
4163 FuncUnitSorter FUS = FuncUnitSorter(*ST);
4164 for (SUnit &SU : DAG->
SUnits)
4165 FUS.calcCriticalResources(*SU.
getInstr());
4166 PriorityQueue<MachineInstr *, std::vector<MachineInstr *>, FuncUnitSorter>
4169 for (SUnit &SU : DAG->
SUnits)
4176 while (!FuncUnitOrder.empty()) {
4177 MachineInstr *
MI = FuncUnitOrder.top();
4178 FuncUnitOrder.pop();
4179 if (
TII->isZeroCost(
MI->getOpcode()))
4185 unsigned ReservedCycles = 0;
4189 dbgs() <<
"Trying to reserve resource for " << NumCycles
4190 <<
" cycles for \n";
4193 for (
unsigned C = 0;
C < NumCycles; ++
C)
4195 if ((*RI)->canReserveResources(*
MI)) {
4196 (*RI)->reserveResources(*
MI);
4203 <<
", NumCycles:" << NumCycles <<
"\n");
4205 for (
unsigned C = ReservedCycles;
C < NumCycles; ++
C) {
4207 <<
"NewResource created to reserve resources"
4210 assert(NewResource->canReserveResources(*
MI) &&
"Reserve error.");
4211 NewResource->reserveResources(*
MI);
4212 Resources.push_back(std::unique_ptr<DFAPacketizer>(NewResource));
4223 return calculateResMIIDFA();
4230 for (
SUnit &SU : DAG->SUnits) {
4242 <<
" WriteProcRes: ";
4247 make_range(STI->getWriteProcResBegin(SCDesc),
4248 STI->getWriteProcResEnd(SCDesc))) {
4252 SM.getProcResource(PRE.ProcResourceIdx);
4253 dbgs() <<
Desc->Name <<
": " << PRE.ReleaseAtCycle <<
", ";
4256 ResourceCount[PRE.ProcResourceIdx] += PRE.ReleaseAtCycle;
4261 int Result = (NumMops + IssueWidth - 1) / IssueWidth;
4264 dbgs() <<
"#Mops: " << NumMops <<
", "
4265 <<
"IssueWidth: " << IssueWidth <<
", "
4266 <<
"Cycles: " << Result <<
"\n";
4271 std::stringstream SS;
4272 SS << std::setw(2) <<
"ID" << std::setw(16) <<
"Name" << std::setw(10)
4273 <<
"Units" << std::setw(10) <<
"Consumed" << std::setw(10) <<
"Cycles"
4278 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4280 int Cycles = (ResourceCount[
I] +
Desc->NumUnits - 1) /
Desc->NumUnits;
4283 std::stringstream SS;
4284 SS << std::setw(2) <<
I << std::setw(16) <<
Desc->Name << std::setw(10)
4285 <<
Desc->NumUnits << std::setw(10) << ResourceCount[
I]
4286 << std::setw(10) << Cycles <<
"\n";
4290 if (Cycles > Result)
4297 InitiationInterval =
II;
4298 DFAResources.clear();
4299 DFAResources.resize(
II);
4300 for (
auto &
I : DFAResources)
4301 I.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST));
4304 NumScheduledMops.clear();
4305 NumScheduledMops.resize(
II);
4309 if (Pred.isArtificial() || Dst->isBoundaryNode())
4314 return IgnoreAnti && (Pred.getKind() ==
SDep::Kind::Anti || Distance != 0);
4317SwingSchedulerDDG::SwingSchedulerDDGEdges &
4318SwingSchedulerDDG::getEdges(
const SUnit *SU) {
4320 return EntrySUEdges;
4326const SwingSchedulerDDG::SwingSchedulerDDGEdges &
4327SwingSchedulerDDG::getEdges(
const SUnit *SU)
const {
4329 return EntrySUEdges;
4335void SwingSchedulerDDG::addEdge(
const SUnit *SU,
4336 const SwingSchedulerDDGEdge &
Edge) {
4338 "Validation-only edges are not expected here.");
4340 auto &Edges = getEdges(SU);
4341 if (
Edge.getSrc() == SU)
4342 Edges.Succs.push_back(
Edge);
4344 Edges.Preds.push_back(
Edge);
4347void SwingSchedulerDDG::initEdges(SUnit *SU) {
4348 for (
const auto &PI : SU->
Preds) {
4349 SwingSchedulerDDGEdge
Edge(SU, PI,
false,
4354 for (
const auto &SI : SU->
Succs) {
4355 SwingSchedulerDDGEdge
Edge(SU, SI,
true,
4363 : EntrySU(EntrySU), ExitSU(ExitSU) {
4364 EdgesVec.resize(SUnits.size());
4369 for (
auto &SU : SUnits)
4373 for (
SUnit &SU : SUnits) {
4378 for (
SUnit *Dst : *OD) {
4381 Edge.setDistance(1);
4382 ValidationOnlyEdges.push_back(Edge);
4394 bool UseAsExtraEdge = [&]() {
4395 if (Edge.getDistance() == 0 || !Edge.isOrderDep())
4398 SUnit *Src = Edge.getSrc();
4399 SUnit *Dst = Edge.getDst();
4400 if (Src->NodeNum < Dst->NodeNum)
4408 getEdges(Edge.getSrc()).ExtraSuccs.push_back(Edge.getDst());
4414const SwingSchedulerDDG::EdgesType &
4416 return getEdges(SU).Preds;
4419const SwingSchedulerDDG::EdgesType &
4421 return getEdges(SU).Succs;
4425 return getEdges(SU).ExtraSuccs;
4432 auto ExpandCycle = [&](
SUnit *SU) {
4435 return Cycle + (Stage *
II);
4439 SUnit *Src = Edge.getSrc();
4440 SUnit *Dst = Edge.getDst();
4441 if (!Src->isInstr() || !Dst->isInstr())
4443 int CycleSrc = ExpandCycle(Src);
4444 int CycleDst = ExpandCycle(Dst);
4445 int MaxLateStart = CycleDst + Edge.getDistance() *
II - Edge.getLatency();
4446 if (CycleSrc > MaxLateStart) {
4448 dbgs() <<
"Validation failed for edge from " << Src->NodeNum <<
" to "
4449 << Dst->NodeNum <<
"\n";
4459 for (
SUnit &SU : SUnits) {
4488 !
TII->isGlobalMemoryObject(FromMI) &&
4506 const auto DumpSU = [](
const SUnit *SU) {
4507 std::ostringstream OSS;
4508 OSS <<
"SU(" << SU->
NodeNum <<
")";
4512 dbgs() <<
" Loop carried edges from " << DumpSU(SU) <<
"\n"
4514 for (
SUnit *Dst : *Order)
4515 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< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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)
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 bool findLoopIncrementValue(const MachineInstr &MI, 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 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 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 bool runMachinePipeliner(MachineFunction &MF, function_ref< const MachineLoopInfo &()> GetMLI, function_ref< LiveIntervals &()> GetLIS, function_ref< AAResults &()> GetAA, function_ref< MachineOptimizationRemarkEmitter &()> GetORE, function_ref< RegisterClassInfo &()> GetRCI)
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.
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)
MachineOptimizationRemarkEmitter * ORE
const TargetInstrInfo * TII
bool run()
Run the software pipeliner over all loops in the function.
const MachineLoopInfo * MLI
const InstrItineraryData * InstrItins
MachinePipelinerImpl(MachineFunction &MF, const MachineLoopInfo &MLI, LiveIntervals &LIS, AAResults &AA, MachineOptimizationRemarkEmitter &ORE, RegisterClassInfo &RegClassInfo)
RegisterClassInfo * RegClassInfo
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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...
Itinerary data supplied by a subtarget to be used by a target.
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
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
Analysis pass that exposes the MachineLoopInfo for a machine function.
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 ...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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 LLVM_READONLY 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.
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
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...
const MachineFunction & getMF() const
LLVM_ABI LLVM_READONLY 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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
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.
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 void overridePipelinerPolicy(MachinePipelinerPolicy &Policy) const
Override generic software pipelining policy.
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.
int getNumOccurrences() const
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.
An efficient, type-erasing, non-owning reference to a callable.
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.
Abstract Attribute helper functions.
@ 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.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
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.
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.
Cache the target analysis information about the loop.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > LoopPipelinerInfo
SmallVector< MachineOperand, 4 > BrCond
MachineInstr * LoopCompare
MachineInstr * LoopInductionVar
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.