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 *, SmallSet<VirtRegOrUnit, 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) {
1725 void dumpPSet(VirtRegOrUnit VRegOrUnit)
const {
1729 dbgs() << *PSetIter <<
' ';
1734 void increaseRegisterPressure(std::vector<unsigned> &Pressure,
1735 VirtRegOrUnit VRegOrUnit)
const {
1738 for (; PSetIter.isValid(); ++PSetIter)
1739 Pressure[*PSetIter] += Weight;
1742 void decreaseRegisterPressure(std::vector<unsigned> &Pressure,
1743 VirtRegOrUnit VRegOrUnit)
const {
1745 unsigned Weight = PSetIter.getWeight();
1746 for (; PSetIter.isValid(); ++PSetIter) {
1747 auto &
P = Pressure[*PSetIter];
1749 "register pressure must be greater than or equal weight");
1755 bool isReservedRegUnit(VirtRegOrUnit VRegOrUnit)
const {
1760 bool isDefinedInThisLoop(VirtRegOrUnit VRegOrUnit)
const {
1773 void computeLiveIn() {
1774 SmallSet<VirtRegOrUnit, 8>
Used;
1775 for (
auto &
MI : *OrigMBB) {
1776 if (
MI.isDebugInstr())
1778 for (
auto &Use : ROMap[&
MI].
Uses) {
1779 VirtRegOrUnit
Reg =
Use.VRegOrUnit;
1782 if (
MI.isPHI() &&
Reg.isVirtualReg() &&
1785 if (isReservedRegUnit(
Reg))
1787 if (isDefinedInThisLoop(
Reg))
1793 for (
auto LiveIn : Used)
1794 increaseRegisterPressure(InitSetPressure, LiveIn);
1798 void computePressureSetLimit(
const RegisterClassInfo &RCI) {
1799 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1814 Instr2LastUsesTy computeLastUses(
const OrderedInstsTy &OrderedInsts,
1815 Instr2StageTy &Stages)
const {
1820 SmallSet<VirtRegOrUnit, 8> TargetRegs;
1821 const auto UpdateTargetRegs = [
this, &TargetRegs](VirtRegOrUnit
Reg) {
1822 if (isDefinedInThisLoop(
Reg))
1825 for (MachineInstr *
MI : OrderedInsts) {
1828 UpdateTargetRegs(VirtRegOrUnit(
Reg));
1830 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses)
1831 UpdateTargetRegs(
Use.VRegOrUnit);
1835 const auto InstrScore = [&Stages](MachineInstr *
MI) {
1836 return Stages[
MI] +
MI->isPHI();
1839 std::map<VirtRegOrUnit, MachineInstr *> LastUseMI;
1841 for (
auto &Use : ROMap.
find(
MI)->getSecond().Uses) {
1842 VirtRegOrUnit
Reg =
Use.VRegOrUnit;
1847 MachineInstr *Orig = Ite->second;
1848 MachineInstr *
New =
MI;
1849 if (InstrScore(Orig) < InstrScore(New))
1855 Instr2LastUsesTy LastUses;
1856 for (
auto [
Reg,
MI] : LastUseMI)
1857 LastUses[
MI].insert(
Reg);
1873 std::vector<unsigned>
1874 computeMaxSetPressure(
const OrderedInstsTy &OrderedInsts,
1875 Instr2StageTy &Stages,
1876 const unsigned StageCount)
const {
1877 using RegSetTy = SmallSet<VirtRegOrUnit, 16>;
1883 auto CurSetPressure = InitSetPressure;
1884 auto MaxSetPressure = InitSetPressure;
1885 auto LastUses = computeLastUses(OrderedInsts, Stages);
1888 dbgs() <<
"Ordered instructions:\n";
1889 for (MachineInstr *
MI : OrderedInsts) {
1890 dbgs() <<
"Stage " << Stages[
MI] <<
": ";
1895 const auto InsertReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1896 VirtRegOrUnit
Reg) {
1897 if (isReservedRegUnit(
Reg))
1905 increaseRegisterPressure(CurSetPressure,
Reg);
1909 const auto EraseReg = [
this, &CurSetPressure](RegSetTy &RegSet,
1910 VirtRegOrUnit
Reg) {
1911 if (isReservedRegUnit(
Reg))
1915 if (!RegSet.contains(
Reg))
1920 decreaseRegisterPressure(CurSetPressure,
Reg);
1924 for (
unsigned I = 0;
I < StageCount;
I++) {
1925 for (MachineInstr *
MI : OrderedInsts) {
1926 const auto Stage = Stages[
MI];
1930 const unsigned Iter =
I - Stage;
1932 for (
auto &Def : ROMap.
find(
MI)->getSecond().Defs)
1933 InsertReg(LiveRegSets[Iter],
Def.VRegOrUnit);
1935 for (
auto LastUse : LastUses[
MI]) {
1938 EraseReg(LiveRegSets[Iter - 1], LastUse);
1940 EraseReg(LiveRegSets[Iter], LastUse);
1944 for (
unsigned PSet = 0; PSet < PSetNum; PSet++)
1945 MaxSetPressure[PSet] =
1946 std::max(MaxSetPressure[PSet], CurSetPressure[PSet]);
1949 dbgs() <<
"CurSetPressure=";
1950 dumpRegisterPressures(CurSetPressure);
1951 dbgs() <<
" iter=" << Iter <<
" stage=" << Stage <<
":";
1957 return MaxSetPressure;
1961 HighRegisterPressureDetector(MachineBasicBlock *OrigMBB,
1963 : OrigMBB(OrigMBB), MRI(MF.getRegInfo()),
1964 TRI(MF.getSubtarget().getRegisterInfo()),
1965 PSetNum(
TRI->getNumRegPressureSets()), InitSetPressure(PSetNum, 0),
1966 PressureSetLimit(PSetNum, 0) {}
1970 void init(
const RegisterClassInfo &RCI) {
1971 for (MachineInstr &
MI : *OrigMBB) {
1972 if (
MI.isDebugInstr())
1974 ROMap[&
MI].collect(
MI, *
TRI, MRI,
false,
true);
1978 computePressureSetLimit(RCI);
1983 bool detect(
const SwingSchedulerDAG *SSD, SMSchedule &Schedule,
1984 const unsigned MaxStage)
const {
1986 "the percentage of the margin must be between 0 to 100");
1988 OrderedInstsTy OrderedInsts;
1989 Instr2StageTy Stages;
1991 const auto MaxSetPressure =
1992 computeMaxSetPressure(OrderedInsts, Stages, MaxStage + 1);
1995 dbgs() <<
"Dump MaxSetPressure:\n";
1996 for (
unsigned I = 0;
I < MaxSetPressure.size();
I++) {
1997 dbgs() <<
format(
"MaxSetPressure[%d]=%d\n",
I, MaxSetPressure[
I]);
2002 for (
unsigned PSet = 0; PSet < PSetNum; PSet++) {
2003 unsigned Limit = PressureSetLimit[PSet];
2006 <<
" Margin=" << Margin <<
"\n");
2007 if (Limit < MaxSetPressure[PSet] + Margin) {
2010 <<
"Rejected the schedule because of too high register pressure\n");
2026unsigned SwingSchedulerDAG::calculateResMII() {
2029 return RM.calculateResMII();
2038unsigned SwingSchedulerDAG::calculateRecMII(NodeSetType &NodeSets) {
2039 unsigned RecMII = 0;
2041 for (NodeSet &Nodes : NodeSets) {
2045 unsigned Delay = Nodes.getLatency();
2046 unsigned Distance = 1;
2049 unsigned CurMII = (Delay + Distance - 1) / Distance;
2050 Nodes.setRecMII(CurMII);
2051 if (CurMII > RecMII)
2059void SwingSchedulerDAG::Circuits::createAdjacencyStructure(
2060 SwingSchedulerDDG *DDG) {
2061 BitVector
Added(SUnits.size());
2062 DenseMap<int, int> OutputDeps;
2063 for (
int i = 0, e = SUnits.size(); i != e; ++i) {
2069 if (OE.isOutputDep()) {
2070 int N = OE.getDst()->NodeNum;
2072 auto Dep = OutputDeps.
find(BackEdge);
2073 if (Dep != OutputDeps.
end()) {
2074 BackEdge = Dep->second;
2075 OutputDeps.
erase(Dep);
2077 OutputDeps[
N] = BackEdge;
2080 if (OE.getDst()->isBoundaryNode() || OE.isArtificial())
2092 int N = OE.getDst()->NodeNum;
2094 AdjK[i].push_back(
N);
2101 int N = Dst->NodeNum;
2103 AdjK[i].push_back(
N);
2110 for (
auto &OD : OutputDeps)
2111 if (!
Added.test(OD.second)) {
2112 AdjK[OD.first].push_back(OD.second);
2113 Added.set(OD.second);
2119bool SwingSchedulerDAG::Circuits::circuit(
int V,
int S, NodeSetType &NodeSets,
2120 const SwingSchedulerDAG *DAG,
2122 SUnit *
SV = &SUnits[
V];
2127 for (
auto W : AdjK[V]) {
2128 if (NumPaths > MaxPaths)
2139 if (!Blocked.test(W)) {
2140 if (circuit(W, S, NodeSets, DAG,
2141 Node2Idx->at(W) < Node2Idx->at(V) ?
true : HasBackedge))
2149 for (
auto W : AdjK[V]) {
2160void SwingSchedulerDAG::Circuits::unblock(
int U) {
2162 SmallPtrSet<SUnit *, 4> &BU =
B[
U];
2163 while (!BU.
empty()) {
2164 SmallPtrSet<SUnit *, 4>::iterator
SI = BU.
begin();
2165 assert(SI != BU.
end() &&
"Invalid B set.");
2168 if (Blocked.test(
W->NodeNum))
2169 unblock(
W->NodeNum);
2175void SwingSchedulerDAG::findCircuits(NodeSetType &NodeSets) {
2176 Circuits Cir(SUnits, Topo);
2178 Cir.createAdjacencyStructure(&*DDG);
2179 for (
int I = 0,
E = SUnits.size();
I !=
E; ++
I) {
2181 Cir.circuit(
I,
I, NodeSets,
this);
2203void SwingSchedulerDAG::CopyToPhiMutation::apply(ScheduleDAGInstrs *DAG) {
2204 for (SUnit &SU : DAG->
SUnits) {
2214 for (
auto &Dep : SU.
Preds) {
2215 SUnit *TmpSU = Dep.getSUnit();
2216 MachineInstr *TmpMI = TmpSU->
getInstr();
2227 if (PHISUs.
size() == 0 || SrcSUs.
size() == 0)
2235 for (
auto &Dep : PHISUs[Index]->Succs) {
2239 SUnit *TmpSU = Dep.getSUnit();
2240 MachineInstr *TmpMI = TmpSU->
getInstr();
2249 if (UseSUs.
size() == 0)
2254 for (
auto *
I : UseSUs) {
2255 for (
auto *Src : SrcSUs) {
2271void SwingSchedulerDAG::computeNodeFunctions(NodeSetType &NodeSets) {
2272 ScheduleInfo.resize(SUnits.size());
2275 for (
int I : Topo) {
2276 const SUnit &SU = SUnits[
I];
2283 for (
int I : Topo) {
2285 int zeroLatencyDepth = 0;
2286 SUnit *SU = &SUnits[
I];
2288 SUnit *Pred =
IE.getSrc();
2289 if (
IE.getLatency() == 0)
2291 std::max(zeroLatencyDepth, getZeroLatencyDepth(Pred) + 1);
2292 if (
IE.ignoreDependence(
true))
2294 asap = std::max(asap, (
int)(getASAP(Pred) +
IE.getLatency() -
2295 IE.getDistance() * MII));
2297 maxASAP = std::max(maxASAP, asap);
2298 ScheduleInfo[
I].ASAP = asap;
2299 ScheduleInfo[
I].ZeroLatencyDepth = zeroLatencyDepth;
2305 int zeroLatencyHeight = 0;
2306 SUnit *SU = &SUnits[
I];
2308 SUnit *Succ = OE.getDst();
2311 if (OE.getLatency() == 0)
2313 std::max(zeroLatencyHeight, getZeroLatencyHeight(Succ) + 1);
2314 if (OE.ignoreDependence(
true))
2316 alap = std::min(alap, (
int)(getALAP(Succ) - OE.getLatency() +
2317 OE.getDistance() * MII));
2320 ScheduleInfo[
I].ALAP = alap;
2321 ScheduleInfo[
I].ZeroLatencyHeight = zeroLatencyHeight;
2325 for (NodeSet &
I : NodeSets)
2326 I.computeNodeSetInfo(
this);
2329 for (
unsigned i = 0; i < SUnits.size(); i++) {
2330 dbgs() <<
"\tNode " << i <<
":\n";
2331 dbgs() <<
"\t ASAP = " << getASAP(&SUnits[i]) <<
"\n";
2332 dbgs() <<
"\t ALAP = " << getALAP(&SUnits[i]) <<
"\n";
2333 dbgs() <<
"\t MOV = " << getMOV(&SUnits[i]) <<
"\n";
2334 dbgs() <<
"\t D = " << getDepth(&SUnits[i]) <<
"\n";
2335 dbgs() <<
"\t H = " << getHeight(&SUnits[i]) <<
"\n";
2336 dbgs() <<
"\t ZLD = " << getZeroLatencyDepth(&SUnits[i]) <<
"\n";
2337 dbgs() <<
"\t ZLH = " << getZeroLatencyHeight(&SUnits[i]) <<
"\n";
2352 SUnit *PredSU = IE.getSrc();
2353 if (S && S->count(PredSU) == 0)
2355 if (IE.ignoreDependence(
true))
2366 SUnit *SuccSU = OE.getDst();
2367 if (!OE.isAntiDep())
2369 if (S && S->count(SuccSU) == 0)
2375 return !Preds.
empty();
2388 SUnit *SuccSU = OE.getDst();
2389 if (S && S->count(SuccSU) == 0)
2391 if (OE.ignoreDependence(
false))
2402 SUnit *PredSU = IE.getSrc();
2403 if (!IE.isAntiDep())
2405 if (S && S->count(PredSU) == 0)
2411 return !Succs.
empty();
2427 if (!Visited.
insert(Cur).second)
2428 return Path.contains(Cur);
2429 bool FoundPath =
false;
2431 if (!OE.ignoreDependence(
false))
2433 computePath(OE.getDst(), Path, DestNodes, Exclude, Visited, DDG);
2435 if (IE.isAntiDep() && IE.getDistance() == 0)
2437 computePath(IE.getSrc(), Path, DestNodes, Exclude, Visited, DDG);
2452 for (
SUnit *SU : NS) {
2458 if (
Reg.isVirtual())
2461 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2465 for (
SUnit *SU : NS)
2469 if (
Reg.isVirtual()) {
2474 for (MCRegUnit Unit :
TRI->regunits(
Reg.asMCReg()))
2485void SwingSchedulerDAG::registerPressureFilter(NodeSetType &NodeSets) {
2486 for (
auto &NS : NodeSets) {
2490 IntervalPressure RecRegPressure;
2491 RegPressureTracker RecRPTracker(RecRegPressure);
2492 RecRPTracker.init(&MF, &RegClassInfo, &LIS, BB, BB->end(),
false,
true);
2494 RecRPTracker.closeBottom();
2496 std::vector<SUnit *> SUnits(NS.begin(), NS.end());
2497 llvm::sort(SUnits, [](
const SUnit *
A,
const SUnit *
B) {
2498 return A->NodeNum >
B->NodeNum;
2501 for (
auto &SU : SUnits) {
2507 RecRPTracker.setPos(std::next(CurInstI));
2509 RegPressureDelta RPDelta;
2511 RecRPTracker.getMaxUpwardPressureDelta(SU->
getInstr(),
nullptr, RPDelta,
2516 dbgs() <<
"Excess register pressure: SU(" << SU->
NodeNum <<
") "
2519 NS.setExceedPressure(SU);
2522 RecRPTracker.recede();
2529void SwingSchedulerDAG::colocateNodeSets(NodeSetType &NodeSets) {
2530 unsigned Colocate = 0;
2531 for (
int i = 0, e = NodeSets.size(); i < e; ++i) {
2533 SmallSetVector<SUnit *, 8>
S1;
2536 for (
int j = i + 1;
j <
e; ++
j) {
2540 SmallSetVector<SUnit *, 8> S2;
2557void SwingSchedulerDAG::checkNodeSets(NodeSetType &NodeSets) {
2562 for (
auto &NS : NodeSets) {
2563 if (NS.getRecMII() > 2)
2565 if (NS.getMaxDepth() > MII)
2574void SwingSchedulerDAG::groupRemainingNodes(NodeSetType &NodeSets) {
2575 SetVector<SUnit *> NodesAdded;
2576 SmallPtrSet<SUnit *, 8> Visited;
2579 for (NodeSet &
I : NodeSets) {
2580 SmallSetVector<SUnit *, 8>
N;
2583 SetVector<SUnit *>
Path;
2584 for (SUnit *NI :
N) {
2586 computePath(NI, Path, NodesAdded,
I, Visited, DDG.get());
2593 if (
succ_L(NodesAdded,
N, DDG.get())) {
2594 SetVector<SUnit *>
Path;
2595 for (SUnit *NI :
N) {
2597 computePath(NI, Path,
I, NodesAdded, Visited, DDG.get());
2608 SmallSetVector<SUnit *, 8>
N;
2609 if (
succ_L(NodesAdded,
N, DDG.get()))
2611 addConnectedNodes(
I, NewSet, NodesAdded);
2612 if (!NewSet.
empty())
2613 NodeSets.push_back(NewSet);
2618 if (
pred_L(NodesAdded,
N, DDG.get()))
2620 addConnectedNodes(
I, NewSet, NodesAdded);
2621 if (!NewSet.
empty())
2622 NodeSets.push_back(NewSet);
2626 for (SUnit &SU : SUnits) {
2627 if (NodesAdded.
count(&SU) == 0) {
2629 addConnectedNodes(&SU, NewSet, NodesAdded);
2630 if (!NewSet.
empty())
2631 NodeSets.push_back(NewSet);
2637void SwingSchedulerDAG::addConnectedNodes(SUnit *SU, NodeSet &NewSet,
2638 SetVector<SUnit *> &NodesAdded) {
2643 if (!OE.isArtificial() && !
Successor->isBoundaryNode() &&
2645 addConnectedNodes(
Successor, NewSet, NodesAdded);
2648 SUnit *Predecessor =
IE.getSrc();
2649 if (!
IE.isArtificial() && NodesAdded.
count(Predecessor) == 0)
2650 addConnectedNodes(Predecessor, NewSet, NodesAdded);
2659 for (
SUnit *SU : Set1) {
2660 if (Set2.
count(SU) != 0)
2663 return !Result.empty();
2667void SwingSchedulerDAG::fuseRecs(NodeSetType &NodeSets) {
2668 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2671 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2676 for (SUnit *SU : *J)
2688void SwingSchedulerDAG::removeDuplicateNodes(NodeSetType &NodeSets) {
2689 for (NodeSetType::iterator
I = NodeSets.begin(),
E = NodeSets.end();
I !=
E;
2691 for (NodeSetType::iterator J =
I + 1; J !=
E;) {
2692 J->remove_if([&](SUnit *SUJ) {
return I->count(SUJ); });
2707void SwingSchedulerDAG::computeNodeOrder(NodeSetType &NodeSets) {
2708 SmallSetVector<SUnit *, 8>
R;
2711 for (
auto &Nodes : NodeSets) {
2714 SmallSetVector<SUnit *, 8>
N;
2729 }
else if (NodeSets.size() == 1) {
2730 for (
const auto &
N : Nodes)
2731 if (
N->Succs.size() == 0)
2737 SUnit *maxASAP =
nullptr;
2738 for (SUnit *SU : Nodes) {
2739 if (maxASAP ==
nullptr || getASAP(SU) > getASAP(maxASAP) ||
2740 (getASAP(SU) == getASAP(maxASAP) && SU->
NodeNum > maxASAP->
NodeNum))
2748 while (!
R.empty()) {
2749 if (Order == TopDown) {
2753 while (!
R.empty()) {
2754 SUnit *maxHeight =
nullptr;
2755 for (SUnit *
I : R) {
2756 if (maxHeight ==
nullptr || getHeight(
I) > getHeight(maxHeight))
2758 else if (getHeight(
I) == getHeight(maxHeight) &&
2759 getZeroLatencyHeight(
I) > getZeroLatencyHeight(maxHeight))
2761 else if (getHeight(
I) == getHeight(maxHeight) &&
2762 getZeroLatencyHeight(
I) ==
2763 getZeroLatencyHeight(maxHeight) &&
2764 getMOV(
I) < getMOV(maxHeight))
2769 R.remove(maxHeight);
2770 for (
const auto &OE : DDG->
getOutEdges(maxHeight)) {
2771 SUnit *SU = OE.getDst();
2772 if (Nodes.count(SU) == 0)
2776 if (OE.ignoreDependence(
false))
2785 for (
const auto &IE : DDG->
getInEdges(maxHeight)) {
2786 SUnit *SU =
IE.getSrc();
2787 if (!
IE.isAntiDep())
2789 if (Nodes.count(SU) == 0)
2798 SmallSetVector<SUnit *, 8>
N;
2805 while (!
R.empty()) {
2806 SUnit *maxDepth =
nullptr;
2807 for (SUnit *
I : R) {
2808 if (maxDepth ==
nullptr || getDepth(
I) > getDepth(maxDepth))
2810 else if (getDepth(
I) == getDepth(maxDepth) &&
2811 getZeroLatencyDepth(
I) > getZeroLatencyDepth(maxDepth))
2813 else if (getDepth(
I) == getDepth(maxDepth) &&
2814 getZeroLatencyDepth(
I) == getZeroLatencyDepth(maxDepth) &&
2815 getMOV(
I) < getMOV(maxDepth))
2821 if (Nodes.isExceedSU(maxDepth)) {
2824 R.insert(Nodes.getNode(0));
2827 for (
const auto &IE : DDG->
getInEdges(maxDepth)) {
2828 SUnit *SU =
IE.getSrc();
2829 if (Nodes.count(SU) == 0)
2840 for (
const auto &OE : DDG->
getOutEdges(maxDepth)) {
2841 SUnit *SU = OE.getDst();
2842 if (!OE.isAntiDep())
2844 if (Nodes.count(SU) == 0)
2853 SmallSetVector<SUnit *, 8>
N;
2862 dbgs() <<
"Node order: ";
2864 dbgs() <<
" " <<
I->NodeNum <<
" ";
2870void SwingSchedulerDAG::initPolicy() {
2880bool SwingSchedulerDAG::schedulePipeline(SMSchedule &Schedule) {
2887 bool scheduleFound =
false;
2888 std::unique_ptr<HighRegisterPressureDetector> HRPDetector;
2889 if (Policy.ShouldLimitRegPressure) {
2891 std::make_unique<HighRegisterPressureDetector>(
Loop.getHeader(), MF);
2892 HRPDetector->init(RegClassInfo);
2895 for (
unsigned II = MII;
II <= MAX_II && !scheduleFound; ++
II) {
2907 int EarlyStart = INT_MIN;
2908 int LateStart = INT_MAX;
2917 dbgs() <<
format(
"\tes: %8x ls: %8x\n", EarlyStart, LateStart));
2919 if (EarlyStart > LateStart)
2920 scheduleFound =
false;
2921 else if (EarlyStart != INT_MIN && LateStart == INT_MAX)
2923 Schedule.
insert(SU, EarlyStart, EarlyStart + (
int)
II - 1,
II);
2924 else if (EarlyStart == INT_MIN && LateStart != INT_MAX)
2926 Schedule.
insert(SU, LateStart, LateStart - (
int)
II + 1,
II);
2927 else if (EarlyStart != INT_MIN && LateStart != INT_MAX) {
2928 LateStart = std::min(LateStart, EarlyStart + (
int)
II - 1);
2937 scheduleFound = Schedule.
insert(SU, LateStart, EarlyStart,
II);
2939 scheduleFound = Schedule.
insert(SU, EarlyStart, LateStart,
II);
2942 scheduleFound = Schedule.
insert(SU, FirstCycle + getASAP(SU),
2943 FirstCycle + getASAP(SU) +
II - 1,
II);
2951 scheduleFound =
false;
2955 dbgs() <<
"\tCan't schedule\n";
2957 }
while (++NI != NE && scheduleFound);
2975 if (scheduleFound && HRPDetector)
2984 if (scheduleFound) {
2985 scheduleFound = LoopPipelinerInfo->shouldUseSchedule(*
this, Schedule);
2990 if (scheduleFound) {
2993 return MachineOptimizationRemarkAnalysis(
2995 <<
"Schedule found with Initiation Interval: "
2997 <<
", MaxStageCount: "
3011 if (!
Reg.isVirtual())
3026 if (!
Op.isReg() || !
Op.getReg().isVirtual())
3054 if (Def->getParent() != LoopBB)
3057 if (Def->isCopy()) {
3059 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
3061 CurReg = Def->getOperand(1).getReg();
3062 }
else if (Def->isPHI()) {
3068 }
else if (
TII->getIncrementValue(*Def,
Value)) {
3076 bool OffsetIsScalable;
3077 if (
TII->getMemOperandWithOffset(*Def, BaseOp,
Offset, OffsetIsScalable,
3080 CurReg = BaseOp->
getReg();
3092 if (CurReg == OrgReg)
3104bool SwingSchedulerDAG::computeDelta(
const MachineInstr &
MI,
int &Delta)
const {
3106 const MachineOperand *BaseOp;
3108 bool OffsetIsScalable;
3109 if (!
TII->getMemOperandWithOffset(
MI, BaseOp,
Offset, OffsetIsScalable,
TRI))
3113 if (OffsetIsScalable)
3116 if (!BaseOp->
isReg())
3129bool SwingSchedulerDAG::canUseLastOffsetValue(MachineInstr *
MI,
3131 unsigned &OffsetPos,
3137 unsigned BasePosLd, OffsetPosLd;
3145 if (!Phi || !
Phi->isPHI())
3153 MachineInstr *PrevDef = MRI.
getVRegDef(PrevReg);
3154 if (!PrevDef || PrevDef ==
MI)
3160 unsigned BasePos1 = 0, OffsetPos1 = 0;
3168 MachineInstr *NewMI = MF.CloneMachineInstr(
MI);
3171 MF.deleteMachineInstr(NewMI);
3176 BasePos = BasePosLd;
3177 OffsetPos = OffsetPosLd;
3189 InstrChanges.find(SU);
3190 if (It != InstrChanges.
end()) {
3191 std::pair<Register, int64_t> RegAndOffset = It->second;
3192 unsigned BasePos, OffsetPos;
3193 if (!
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3195 Register BaseReg =
MI->getOperand(BasePos).getReg();
3201 if (BaseStageNum < DefStageNum) {
3203 int OffsetDiff = DefStageNum - BaseStageNum;
3204 if (DefCycleNum < BaseCycleNum) {
3210 MI->getOperand(OffsetPos).getImm() + RegAndOffset.second * OffsetDiff;
3225 while (Def->isPHI()) {
3226 if (!Visited.
insert(Def).second)
3228 for (
unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2)
3229 if (Def->getOperand(i + 1).getMBB() == BB) {
3230 Def = MRI.
getVRegDef(Def->getOperand(i).getReg());
3241 int DeltaB, DeltaO, Delta;
3248 int64_t OffsetB, OffsetO;
3249 bool OffsetBIsScalable, OffsetOIsScalable;
3251 if (!
TII->getMemOperandWithOffset(*BaseMI, BaseOpB, OffsetB,
3252 OffsetBIsScalable,
TRI) ||
3253 !
TII->getMemOperandWithOffset(*OtherMI, BaseOpO, OffsetO,
3254 OffsetOIsScalable,
TRI))
3257 if (OffsetBIsScalable || OffsetOIsScalable)
3267 if (!RegB.
isVirtual() || !RegO.isVirtual())
3272 if (!DefB || !DefO || !DefB->
isPHI() || !DefO->
isPHI())
3297 dbgs() <<
"Overlap check:\n";
3298 dbgs() <<
" BaseMI: ";
3300 dbgs() <<
" Base + " << OffsetB <<
" + I * " << Delta
3301 <<
", Len: " << AccessSizeB.
getValue() <<
"\n";
3302 dbgs() <<
" OtherMI: ";
3304 dbgs() <<
" Base + " << OffsetO <<
" + I * " << Delta
3305 <<
", Len: " << AccessSizeO.
getValue() <<
"\n";
3313 int64_t BaseMinAddr = OffsetB;
3314 int64_t OhterNextIterMaxAddr = OffsetO + Delta + AccessSizeO.
getValue() - 1;
3315 if (BaseMinAddr > OhterNextIterMaxAddr) {
3320 int64_t BaseMaxAddr = OffsetB + AccessSizeB.
getValue() - 1;
3321 int64_t OtherNextIterMinAddr = OffsetO + Delta;
3322 if (BaseMaxAddr < OtherNextIterMinAddr) {
3331void SwingSchedulerDAG::postProcessDAG() {
3332 for (
auto &M : Mutations)
3342 bool forward =
true;
3344 dbgs() <<
"Trying to insert node between " << StartCycle <<
" and "
3345 << EndCycle <<
" II: " <<
II <<
"\n";
3347 if (StartCycle > EndCycle)
3351 int termCycle = forward ? EndCycle + 1 : EndCycle - 1;
3352 for (
int curCycle = StartCycle; curCycle != termCycle;
3353 forward ? ++curCycle : --curCycle) {
3356 ProcItinResources.canReserveResources(*SU, curCycle)) {
3358 dbgs() <<
"\tinsert at cycle " << curCycle <<
" ";
3363 ProcItinResources.reserveResources(*SU, curCycle);
3364 ScheduledInstrs[curCycle].push_back(SU);
3365 InstrToCycle.insert(std::make_pair(SU, curCycle));
3366 if (curCycle > LastCycle)
3367 LastCycle = curCycle;
3368 if (curCycle < FirstCycle)
3369 FirstCycle = curCycle;
3373 dbgs() <<
"\tfailed to insert at cycle " << curCycle <<
" ";
3384 for (
auto &
P : SU->
Preds)
3385 if (
P.getKind() ==
SDep::Anti &&
P.getSUnit()->getInstr()->isPHI())
3386 for (
auto &S :
P.getSUnit()->Succs)
3387 if (S.getKind() ==
SDep::Data && S.getSUnit()->getInstr()->isPHI())
3388 return P.getSUnit();
3401 for (
int cycle =
getFirstCycle(); cycle <= LastCycle; ++cycle) {
3404 if (IE.getSrc() ==
I) {
3405 int EarlyStart = cycle + IE.getLatency() - IE.getDistance() *
II;
3406 *MaxEarlyStart = std::max(*MaxEarlyStart, EarlyStart);
3411 if (OE.getDst() ==
I) {
3412 int LateStart = cycle - OE.getLatency() + OE.getDistance() *
II;
3413 *MinLateStart = std::min(*MinLateStart, LateStart);
3418 for (
const auto &Dep : SU->
Preds) {
3421 if (BE && Dep.getSUnit() == BE && !SU->
getInstr()->
isPHI() &&
3423 *MinLateStart = std::min(*MinLateStart, cycle);
3433 std::deque<SUnit *> &Insts)
const {
3435 bool OrderBeforeUse =
false;
3436 bool OrderAfterDef =
false;
3437 bool OrderBeforeDef =
false;
3438 unsigned MoveDef = 0;
3439 unsigned MoveUse = 0;
3444 for (std::deque<SUnit *>::iterator
I = Insts.begin(), E = Insts.end();
I != E;
3447 if (!MO.isReg() || !MO.getReg().isVirtual())
3451 unsigned BasePos, OffsetPos;
3452 if (ST.getInstrInfo()->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos))
3453 if (
MI->getOperand(BasePos).getReg() == Reg)
3457 std::tie(Reads, Writes) =
3458 (*I)->getInstr()->readsWritesVirtualRegister(Reg);
3460 OrderBeforeUse =
true;
3465 OrderAfterDef =
true;
3467 }
else if (MO.isUse() && Writes &&
stageScheduled(*
I) == StageInst1) {
3469 OrderBeforeUse =
true;
3473 OrderAfterDef =
true;
3477 OrderBeforeUse =
true;
3481 OrderAfterDef =
true;
3486 OrderBeforeUse =
true;
3492 OrderBeforeDef =
true;
3500 if (OE.getDst() != *
I)
3503 OrderBeforeUse =
true;
3510 else if ((OE.isAntiDep() || OE.isOutputDep()) &&
3512 OrderBeforeUse =
true;
3513 if ((MoveUse == 0) || (Pos < MoveUse))
3518 if (IE.getSrc() != *
I)
3520 if ((IE.isAntiDep() || IE.isOutputDep() || IE.isOrderDep()) &&
3522 OrderAfterDef =
true;
3529 if (OrderAfterDef && OrderBeforeUse && MoveUse == MoveDef)
3530 OrderBeforeUse =
false;
3535 OrderBeforeUse = !OrderAfterDef || (MoveUse > MoveDef);
3539 if (OrderBeforeUse && OrderAfterDef) {
3540 SUnit *UseSU = Insts.at(MoveUse);
3541 SUnit *DefSU = Insts.at(MoveDef);
3542 if (MoveUse > MoveDef) {
3543 Insts.erase(Insts.begin() + MoveUse);
3544 Insts.erase(Insts.begin() + MoveDef);
3546 Insts.erase(Insts.begin() + MoveDef);
3547 Insts.erase(Insts.begin() + MoveUse);
3557 Insts.push_front(SU);
3559 Insts.push_back(SU);
3567 assert(Phi.isPHI() &&
"Expecting a Phi.");
3574 getPhiRegs(Phi, Phi.getParent(), InitVal, LoopVal);
3582 return (LoopCycle > DefCycle) || (LoopStage <= DefStage);
3600 if (!Phi || !Phi->isPHI() || Phi->getParent() != Def->getParent())
3606 if (DMO.getReg() == LoopReg)
3617 if (InstrToCycle.count(IE.getSrc()))
3628 for (
auto &SU : SSD->
SUnits)
3633 while (!Worklist.
empty()) {
3635 if (DoNotPipeline.
count(SU))
3638 DoNotPipeline.
insert(SU);
3645 if (OE.getDistance() == 1)
3648 return DoNotPipeline;
3657 int NewLastCycle = INT_MIN;
3662 NewLastCycle = std::max(NewLastCycle, InstrToCycle[&SU]);
3669 if (IE.getDistance() == 0)
3670 NewCycle = std::max(InstrToCycle[IE.getSrc()], NewCycle);
3675 if (OE.getDistance() == 1)
3676 NewCycle = std::max(InstrToCycle[OE.getDst()], NewCycle);
3678 int OldCycle = InstrToCycle[&SU];
3679 if (OldCycle != NewCycle) {
3680 InstrToCycle[&SU] = NewCycle;
3685 <<
") is not pipelined; moving from cycle " << OldCycle
3686 <<
" to " << NewCycle <<
" Instr:" << *SU.
getInstr());
3711 if (FirstCycle + InitiationInterval <= NewCycle)
3714 NewLastCycle = std::max(NewLastCycle, NewCycle);
3716 LastCycle = NewLastCycle;
3733 int CycleDef = InstrToCycle[&SU];
3734 assert(StageDef != -1 &&
"Instruction should have been scheduled.");
3736 SUnit *Dst = OE.getDst();
3737 if (OE.isAssignedRegDep() && !Dst->isBoundaryNode())
3738 if (OE.getReg().isPhysical()) {
3741 if (InstrToCycle[Dst] <= CycleDef)
3759void SwingSchedulerDAG::checkValidNodeOrder(
const NodeSetType &Circuits)
const {
3762 typedef std::pair<SUnit *, unsigned> UnitIndex;
3763 std::vector<UnitIndex> Indices(
NodeOrder.size(), std::make_pair(
nullptr, 0));
3765 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i)
3766 Indices.push_back(std::make_pair(
NodeOrder[i], i));
3768 auto CompareKey = [](UnitIndex i1, UnitIndex i2) {
3769 return std::get<0>(i1) < std::get<0>(i2);
3782 for (
unsigned i = 0, s =
NodeOrder.size(); i < s; ++i) {
3786 bool PredBefore =
false;
3787 bool SuccBefore =
false;
3795 SUnit *PredSU = IE.getSrc();
3796 unsigned PredIndex = std::get<1>(
3806 SUnit *SuccSU = OE.getDst();
3812 unsigned SuccIndex = std::get<1>(
3825 Circuits, [SU](
const NodeSet &Circuit) {
return Circuit.
count(SU); });
3830 NumNodeOrderIssues++;
3834 <<
" are scheduled before node " << SU->
NodeNum
3841 dbgs() <<
"Invalid node order found!\n";
3854 for (
SUnit *SU : Instrs) {
3856 for (
unsigned i = 0, e =
MI->getNumOperands(); i < e; ++i) {
3864 InstrChanges.find(SU);
3865 if (It != InstrChanges.
end()) {
3866 unsigned BasePos, OffsetPos;
3868 if (
TII->getBaseAndOffsetPosition(*
MI, BasePos, OffsetPos)) {
3872 MI->getOperand(OffsetPos).getImm() - It->second.second;
3885 unsigned TiedUseIdx = 0;
3886 if (
MI->isRegTiedToUseOperand(i, &TiedUseIdx)) {
3888 OverlapReg =
MI->getOperand(TiedUseIdx).getReg();
3890 NewBaseReg =
MI->getOperand(i).getReg();
3899 const std::deque<SUnit *> &Instrs)
const {
3900 std::deque<SUnit *> NewOrderPhi;
3901 for (
SUnit *SU : Instrs) {
3903 NewOrderPhi.push_back(SU);
3905 std::deque<SUnit *> NewOrderI;
3906 for (
SUnit *SU : Instrs) {
3922 std::deque<SUnit *> &cycleInstrs =
3923 ScheduledInstrs[cycle + (stage * InitiationInterval)];
3925 ScheduledInstrs[cycle].push_front(SU);
3931 for (
int cycle =
getFinalCycle() + 1; cycle <= LastCycle; ++cycle)
3932 ScheduledInstrs.erase(cycle);
3942 std::deque<SUnit *> &cycleInstrs = ScheduledInstrs[Cycle];
3951 os <<
"Num nodes " <<
size() <<
" rec " << RecMII <<
" mov " << MaxMOV
3952 <<
" depth " << MaxDepth <<
" col " << Colocate <<
"\n";
3953 for (
const auto &
I : Nodes)
3954 os <<
" SU(" <<
I->NodeNum <<
") " << *(
I->getInstr());
3958#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
3965 for (
SUnit *CI : cycleInstrs->second) {
3967 os <<
"(" << CI->
NodeNum <<
") ";
3978void ResourceManager::dumpMRT()
const {
3982 std::stringstream SS;
3984 SS << std::setw(4) <<
"Slot";
3985 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I)
3986 SS << std::setw(3) <<
I;
3987 SS << std::setw(7) <<
"#Mops"
3989 for (
int Slot = 0; Slot < InitiationInterval; ++Slot) {
3990 SS << std::setw(4) << Slot;
3991 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I)
3992 SS << std::setw(3) << MRT[Slot][
I];
3993 SS << std::setw(7) << NumScheduledMops[Slot] <<
"\n";
4002 unsigned ProcResourceID = 0;
4006 assert(SM.getNumProcResourceKinds() < 64 &&
4007 "Too many kinds of resources, unsupported");
4010 Masks.
resize(SM.getNumProcResourceKinds());
4011 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4013 if (
Desc.SubUnitsIdxBegin)
4015 Masks[
I] = 1ULL << ProcResourceID;
4019 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4021 if (!
Desc.SubUnitsIdxBegin)
4023 Masks[
I] = 1ULL << ProcResourceID;
4024 for (
unsigned U = 0; U <
Desc.NumUnits; ++U)
4025 Masks[
I] |= Masks[
Desc.SubUnitsIdxBegin[U]];
4030 dbgs() <<
"ProcResourceDesc:\n";
4031 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4033 dbgs() <<
format(
" %16s(%2d): Mask: 0x%08x, NumUnits:%2d\n",
4034 ProcResource->
Name,
I, Masks[
I],
4037 dbgs() <<
" -----------------\n";
4045 dbgs() <<
"canReserveResources:\n";
4048 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
4054 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
4060 reserveResources(SCDesc, Cycle);
4061 bool Result = !isOverbooked();
4062 unreserveResources(SCDesc, Cycle);
4068void ResourceManager::reserveResources(
SUnit &SU,
int Cycle) {
4071 dbgs() <<
"reserveResources:\n";
4074 return DFAResources[positiveModulo(Cycle, InitiationInterval)]
4080 dbgs() <<
"No valid Schedule Class Desc for schedClass!\n";
4086 reserveResources(SCDesc, Cycle);
4091 dbgs() <<
"reserveResources: done!\n\n";
4101 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4102 ++MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4105 ++NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4113 for (
int C = Cycle;
C < Cycle + PRE.ReleaseAtCycle; ++
C)
4114 --MRT[positiveModulo(
C, InitiationInterval)][PRE.ProcResourceIdx];
4117 --NumScheduledMops[positiveModulo(
C, InitiationInterval)];
4120bool ResourceManager::isOverbooked()
const {
4122 for (
int Slot = 0;
Slot < InitiationInterval; ++
Slot) {
4123 for (
unsigned I = 1,
E = SM.getNumProcResourceKinds();
I <
E; ++
I) {
4124 const MCProcResourceDesc *
Desc = SM.getProcResource(
I);
4125 if (MRT[Slot][
I] >
Desc->NumUnits)
4128 if (NumScheduledMops[Slot] > IssueWidth)
4134int ResourceManager::calculateResMIIDFA()
const {
4139 FuncUnitSorter FUS = FuncUnitSorter(*ST);
4140 for (SUnit &SU : DAG->
SUnits)
4141 FUS.calcCriticalResources(*SU.
getInstr());
4142 PriorityQueue<MachineInstr *, std::vector<MachineInstr *>, FuncUnitSorter>
4145 for (SUnit &SU : DAG->
SUnits)
4152 while (!FuncUnitOrder.empty()) {
4153 MachineInstr *
MI = FuncUnitOrder.top();
4154 FuncUnitOrder.pop();
4155 if (
TII->isZeroCost(
MI->getOpcode()))
4161 unsigned ReservedCycles = 0;
4165 dbgs() <<
"Trying to reserve resource for " << NumCycles
4166 <<
" cycles for \n";
4169 for (
unsigned C = 0;
C < NumCycles; ++
C)
4171 if ((*RI)->canReserveResources(*
MI)) {
4172 (*RI)->reserveResources(*
MI);
4179 <<
", NumCycles:" << NumCycles <<
"\n");
4181 for (
unsigned C = ReservedCycles;
C < NumCycles; ++
C) {
4183 <<
"NewResource created to reserve resources"
4186 assert(NewResource->canReserveResources(*
MI) &&
"Reserve error.");
4187 NewResource->reserveResources(*
MI);
4188 Resources.push_back(std::unique_ptr<DFAPacketizer>(NewResource));
4199 return calculateResMIIDFA();
4206 for (
SUnit &SU : DAG->SUnits) {
4218 <<
" WriteProcRes: ";
4223 make_range(STI->getWriteProcResBegin(SCDesc),
4224 STI->getWriteProcResEnd(SCDesc))) {
4228 SM.getProcResource(PRE.ProcResourceIdx);
4229 dbgs() <<
Desc->Name <<
": " << PRE.ReleaseAtCycle <<
", ";
4232 ResourceCount[PRE.ProcResourceIdx] += PRE.ReleaseAtCycle;
4237 int Result = (NumMops + IssueWidth - 1) / IssueWidth;
4240 dbgs() <<
"#Mops: " << NumMops <<
", "
4241 <<
"IssueWidth: " << IssueWidth <<
", "
4242 <<
"Cycles: " << Result <<
"\n";
4247 std::stringstream SS;
4248 SS << std::setw(2) <<
"ID" << std::setw(16) <<
"Name" << std::setw(10)
4249 <<
"Units" << std::setw(10) <<
"Consumed" << std::setw(10) <<
"Cycles"
4254 for (
unsigned I = 1, E = SM.getNumProcResourceKinds();
I < E; ++
I) {
4256 int Cycles = (ResourceCount[
I] +
Desc->NumUnits - 1) /
Desc->NumUnits;
4259 std::stringstream SS;
4260 SS << std::setw(2) <<
I << std::setw(16) <<
Desc->Name << std::setw(10)
4261 <<
Desc->NumUnits << std::setw(10) << ResourceCount[
I]
4262 << std::setw(10) << Cycles <<
"\n";
4266 if (Cycles > Result)
4273 InitiationInterval =
II;
4274 DFAResources.clear();
4275 DFAResources.resize(
II);
4276 for (
auto &
I : DFAResources)
4277 I.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST));
4280 NumScheduledMops.clear();
4281 NumScheduledMops.resize(
II);
4285 if (Pred.isArtificial() || Dst->isBoundaryNode())
4290 return IgnoreAnti && (Pred.getKind() ==
SDep::Kind::Anti || Distance != 0);
4293SwingSchedulerDDG::SwingSchedulerDDGEdges &
4294SwingSchedulerDDG::getEdges(
const SUnit *SU) {
4296 return EntrySUEdges;
4302const SwingSchedulerDDG::SwingSchedulerDDGEdges &
4303SwingSchedulerDDG::getEdges(
const SUnit *SU)
const {
4305 return EntrySUEdges;
4311void SwingSchedulerDDG::addEdge(
const SUnit *SU,
4312 const SwingSchedulerDDGEdge &
Edge) {
4314 "Validation-only edges are not expected here.");
4316 auto &Edges = getEdges(SU);
4317 if (
Edge.getSrc() == SU)
4318 Edges.Succs.push_back(
Edge);
4320 Edges.Preds.push_back(
Edge);
4323void SwingSchedulerDDG::initEdges(SUnit *SU) {
4324 for (
const auto &PI : SU->
Preds) {
4325 SwingSchedulerDDGEdge
Edge(SU, PI,
false,
4330 for (
const auto &SI : SU->
Succs) {
4331 SwingSchedulerDDGEdge
Edge(SU, SI,
true,
4339 : EntrySU(EntrySU), ExitSU(ExitSU) {
4340 EdgesVec.resize(SUnits.size());
4345 for (
auto &SU : SUnits)
4349 for (
SUnit &SU : SUnits) {
4354 for (
SUnit *Dst : *OD) {
4357 Edge.setDistance(1);
4358 ValidationOnlyEdges.push_back(Edge);
4370 bool UseAsExtraEdge = [&]() {
4371 if (Edge.getDistance() == 0 || !Edge.isOrderDep())
4374 SUnit *Src = Edge.getSrc();
4375 SUnit *Dst = Edge.getDst();
4376 if (Src->NodeNum < Dst->NodeNum)
4384 getEdges(Edge.getSrc()).ExtraSuccs.push_back(Edge.getDst());
4390const SwingSchedulerDDG::EdgesType &
4392 return getEdges(SU).Preds;
4395const SwingSchedulerDDG::EdgesType &
4397 return getEdges(SU).Succs;
4401 return getEdges(SU).ExtraSuccs;
4408 auto ExpandCycle = [&](
SUnit *SU) {
4411 return Cycle + (Stage *
II);
4415 SUnit *Src = Edge.getSrc();
4416 SUnit *Dst = Edge.getDst();
4417 if (!Src->isInstr() || !Dst->isInstr())
4419 int CycleSrc = ExpandCycle(Src);
4420 int CycleDst = ExpandCycle(Dst);
4421 int MaxLateStart = CycleDst + Edge.getDistance() *
II - Edge.getLatency();
4422 if (CycleSrc > MaxLateStart) {
4424 dbgs() <<
"Validation failed for edge from " << Src->NodeNum <<
" to "
4425 << Dst->NodeNum <<
"\n";
4435 for (
SUnit &SU : SUnits) {
4464 !
TII->isGlobalMemoryObject(FromMI) &&
4482 const auto DumpSU = [](
const SUnit *SU) {
4483 std::ostringstream OSS;
4484 OSS <<
"SU(" << SU->
NodeNum <<
")";
4488 dbgs() <<
" Loop carried edges from " << DumpSU(SU) <<
"\n"
4490 for (
SUnit *Dst : *Order)
4491 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.
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 bool isReservedRegUnit(MCRegUnit Unit) const
Returns true when the given register unit is considered reserved.
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.
constexpr bool isValid() const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual 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.
bool contains(const T &V) const
Check if the SmallSet contains the given element.
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
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 printVRegOrUnit(VirtRegOrUnit VRegOrUnit, const TargetRegisterInfo *TRI)
Create Printable object to print virtual registers and physical registers on a raw_ostream.
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.