41#include "llvm/Config/llvm-config.h"
64#define DEBUG_TYPE "machine-scheduler"
68 cl::desc(
"Enable use of AA during MI DAG construction"));
75 cl::desc(
"Use TargetSchedModel for latency lookup"));
79 cl::desc(
"Use InstrItineraryData for latency lookup"));
90 cl::desc(
"The limit to use while constructing the DAG "
91 "prior to scheduling, at which point a trade-off "
92 "is made to avoid excessive compile time. Ignored when "
93 "store-sequencing is enabled."));
97 cl::desc(
"Enable the store-sequencing DAG construction algorithm. This can "
98 "eliminate a large number of redundant control dependencies and "
99 "spurious alias analysis queries at the cost of some unnecessary "
104 cl::desc(
"With store-sequencing DAG construction, after the number of "
105 "memops in a frontier reaches this threshold, automatically "
106 "promote the next store and clear the frontier."));
110 cl::desc(
"With store-sequencing DAG construction, if the occupancy of all "
111 "frontiers reaches this threshold, automatically promote the next "
112 "memory operation to a global memory barrier and clear the "
115#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
118 cl::desc(
"Report top/bottom cycles when dumping SUnit instances"));
140 bool AllObjectsIdentified =
true;
144 if (MMO->isVolatile() || MMO->isAtomic()) {
145 AllObjectsIdentified =
false;
156 AllObjectsIdentified =
false;
157 }
else if (PSV->isAliased(&MFI)) {
161 AllObjectsIdentified =
false;
165 }
else if (
const Value *V = MMO->getValue()) {
168 AllObjectsIdentified &= ObjectsIdentified;
170 for (
Value *V : Objs) {
175 AllObjectsIdentified =
false;
179 return AllObjectsIdentified;
194 unsigned regioninstrs) {
195 assert(bb ==
BB &&
"startBlock should set BB");
215 unsigned OpIdx = MO.getOperandNo();
217 if (Reg.isPhysical()) {
228 for (MCRegUnit Unit :
TRI->regunits(Reg))
230 }
else if (Reg.isVirtual() && MO.readsReg()) {
239 for (
const auto &LI : Succ->liveins()) {
241 auto [Unit, Mask] = *U;
242 if ((Mask & LI.LaneMask).any() && !
Uses.contains(Unit))
263 bool ImplicitPseudoDef = (OperIdx >= DefMIDesc.
getNumOperands() &&
265 for (MCRegUnit Unit :
TRI->regunits(Reg)) {
275 int UseOpIdx =
I->OpIdx;
276 bool ImplicitPseudoUse =
false;
288 ImplicitPseudoUse = UseOpIdx >= ((int)UseMIDesc.
getNumOperands()) &&
293 if (!ImplicitPseudoDef && !ImplicitPseudoUse) {
295 UseInstr, UseOpIdx));
299 ST.adjustSchedDependency(SU, OperIdx, UseSU, UseOpIdx, Dep, &
SchedModel);
313 if (
MRI.isConstantPhysReg(Reg))
325 for (MCRegUnit Unit :
TRI->regunits(Reg)) {
338 SchedModel.computeOutputLatency(
MI, OperIdx, DefInstr));
340 ST.adjustSchedDependency(SU, OperIdx, DefSU,
I->OpIdx, Dep,
352 for (MCRegUnit Unit :
TRI->regunits(Reg))
360 for (MCRegUnit Unit :
TRI->regunits(Reg)) {
372 for (MCRegUnit Unit :
TRI->regunits(Reg)) {
376 for (
bool isBegin =
I ==
B; !isBegin; ) {
377 isBegin = (--
I) ==
B;
386 for (MCRegUnit Unit :
TRI->regunits(Reg))
402 return TRI->getSubRegIndexLaneMask(SubReg);
439 if (OtherMO.isReg() && OtherMO.isDef() && OtherMO.getReg() == Reg)
460 if ((LaneMask & KillLaneMask).
none()) {
465 if ((LaneMask & DefLaneMask).any()) {
471 ST.adjustSchedDependency(SU, OperIdx, UseSU,
I->OperandIndex, Dep,
476 LaneMask &= ~KillLaneMask;
478 if (LaneMask.
any()) {
479 I->LaneMask = LaneMask;
487 if (
MRI.hasOneDef(Reg))
501 if ((V2SU.LaneMask & LaneMask).none())
504 SUnit *DefSU = V2SU.SU;
520 LaneBitmask OverlapMask = V2SU.LaneMask & LaneMask;
521 LaneBitmask NonOverlapMask = V2SU.LaneMask & ~LaneMask;
523 V2SU.LaneMask = OverlapMask;
524 if (NonOverlapMask.
any())
540 assert(!
MI->isDebugOrPseudoInstr());
555 if ((PrevDefLaneMask & LaneMask).
none())
582 if (
MI.isDebugOrPseudoInstr())
607 switch (
SchedModel.getResourceBufferSize(PRE.ProcResourceIdx)) {
628using SUList = std::list<SUnit *>;
666 struct MemopFrontier {
668 SUnit *SequencingStore =
nullptr;
670 SUList Stores, Loads;
674 bool shouldUpdate()
const;
677 unsigned size()
const;
711 struct UnanalyzableMemopFrontier {
713 MemopFrontier Frontier;
718 bool SeenSequencingLoad =
false;
736 UnanalyzableMemopFrontier UnanalyzableFrontier;
741 SUnit *BarrierChain =
nullptr;
743 unsigned MemOpsProcessed = 0;
747 unsigned MemopsInFlight = 0;
753 : DAG(DAG), AA(AA), RPTracker(RPTracker), PDiffs(PDiffs), LIS(LIS) {}
763 void addChainDependencies(
SUnit *SU, SUList &SUs,
unsigned Latency);
764 void addChainDependencies(
SUnit *SU, MemopFrontier &
F,
bool IsStore);
766 void addBarrierChain(SUList &SUs);
767 void addBarrierChain(MemopFrontier &
F);
771 void addBarrierMemoryDeps();
776 void updateSequencingStore(MemopFrontier &
F,
SUnit *SU,
777 bool PreserveNoAliasLoads =
false);
781 void updateSequencingStore(UnanalyzableMemopFrontier &UF,
SUnit *SU,
789unsigned ScheduleDAGDependencyBuilder::MemopFrontier::size()
const {
790 return Loads.size() + Stores.size();
793void ScheduleDAGDependencyBuilder::MemopFrontier::clear() {
794 SequencingStore =
nullptr;
799bool ScheduleDAGDependencyBuilder::MemopFrontier::shouldUpdate()
const {
805bool ScheduleDAGDependencyBuilder::UnanalyzableMemopFrontier::shouldUpdate(
809 return Frontier.shouldUpdate() || !Frontier.SequencingStore ||
810 SeenSequencingLoad || escapesBaseObjects(Objs);
813bool ScheduleDAGDependencyBuilder::UnanalyzableMemopFrontier::
823void ScheduleDAGDependencyBuilder::UnanalyzableMemopFrontier::clear() {
825 SeenSequencingLoad =
false;
829bool ScheduleDAGDependencyBuilder::addChainDependency(SUnit *SUa, SUnit *SUb,
840void ScheduleDAGDependencyBuilder::addChainDependencies(SUnit *SU, SUList &SUs,
842 for (SUnit *Entry : SUs)
843 addChainDependency(SU, Entry,
Latency);
846void ScheduleDAGDependencyBuilder::addChainDependencies(SUnit *SU,
849 if (
F.SequencingStore)
850 F.SequencingStore->addPredBarrier(SU);
852 addChainDependencies(SU,
F.Stores, 0);
854 addChainDependencies(SU,
F.Loads, 1);
857void ScheduleDAGDependencyBuilder::addBarrierChain(SUList &SUs) {
858 assert(BarrierChain !=
nullptr);
866void ScheduleDAGDependencyBuilder::addBarrierChain(MemopFrontier &
F) {
867 assert(BarrierChain !=
nullptr);
869 addBarrierChain(
F.Stores);
870 addBarrierChain(
F.Loads);
872 if (
F.SequencingStore)
873 F.SequencingStore->addPredBarrier(BarrierChain);
878void ScheduleDAGDependencyBuilder::addBarrierMemoryDeps() {
879 assert(BarrierChain !=
nullptr);
881 addBarrierChain(UnanalyzableFrontier.Frontier);
882 UnanalyzableFrontier.clear();
884 for (
auto &[
_, AF] : AnalyzableFrontiers)
886 AnalyzableFrontiers.clear();
891void ScheduleDAGDependencyBuilder::updateSequencingStore(
892 MemopFrontier &
F, SUnit *SU,
bool PreserveNoAliasLoads) {
894 "Only store instructions should be used as sequencing stores");
895 LLVM_DEBUG(
dbgs() <<
"Promoting " << *SU <<
" to sequencing store\n");
898 MemopsInFlight -=
F.size();
900 if (
F.SequencingStore) {
901 F.SequencingStore->addPredBarrier(SU);
908 for (SUnit *S :
F.Stores)
913 if (PreserveNoAliasLoads) {
919 for (
auto It =
F.Loads.begin(); It !=
F.Loads.end();) {
920 if (addChainDependency(SU, *It, 1)) {
921 It =
F.Loads.erase(It);
928 MemopsInFlight +=
F.Loads.size();
931 for (SUnit *S :
F.Loads)
937 F.SequencingStore = SU;
940void ScheduleDAGDependencyBuilder::updateSequencingStore(
943 "Only store instructions should be used as sequencing stores");
946 bool ShouldPreserveNoAliasLoads = !
UF.Frontier.shouldUpdate();
947 updateSequencingStore(
UF.Frontier, SU,
948 ShouldPreserveNoAliasLoads);
949 UF.BaseObjects = std::move(Objs);
950 UF.SeenSequencingLoad =
false;
961 DAG.addSchedBarrierDeps();
969 DAG.DbgValues.emplace_back(DbgMI, &
MI);
973 if (
MI.isDebugValue() ||
MI.isDebugPHI()) {
978 if (
MI.isDebugLabel() ||
MI.isDebugRef() ||
MI.isPseudoProbe())
981 SUnit *SU = DAG.MISUnitMap[&
MI];
982 assert(SU &&
"No SUnit mapped to this MI");
986 RegOpers.
collect(
MI, *DAG.TRI, DAG.MRI, DAG.TrackLaneMasks,
false);
987 if (DAG.TrackLaneMasks) {
995 if (PDiffs !=
nullptr)
996 PDiffs->addInstruction(SU->
NodeNum, RegOpers, DAG.MRI);
998 if (RPTracker->getPos() == DAG.RegionEnd || &*RPTracker->getPos() != &
MI)
999 RPTracker->recedeSkipDebugValues();
1000 assert(&*RPTracker->getPos() == &
MI &&
"RPTracker in sync");
1001 RPTracker->recede(RegOpers);
1004 assert((DAG.CanHandleTerminators ||
1005 (!
MI.isTerminator() && !
MI.isPosition())) &&
1006 "Cannot schedule terminators or labels!");
1013 bool HasVRegDef =
false;
1014 for (
unsigned j = 0, n =
MI.getNumOperands(); j != n; ++j) {
1019 if (Reg.isPhysical()) {
1020 DAG.addPhysRegDeps(SU, j);
1021 }
else if (Reg.isVirtual()) {
1023 DAG.addVRegDefDeps(SU, j);
1027 for (
unsigned j = 0, n =
MI.getNumOperands(); j != n; ++j) {
1036 if (Reg.isPhysical()) {
1037 DAG.addPhysRegDeps(SU, j);
1038 }
else if (Reg.isVirtual() && MO.
readsReg()) {
1039 DAG.addVRegUseDeps(SU, j);
1052 DAG.ExitSU.addPred(Dep);
1061 if (
TII->isGlobalMemoryObject(&
MI)) {
1065 BarrierChain->addPredBarrier(SU);
1068 LLVM_DEBUG(
dbgs() <<
"Global memory object and new barrier chain: "
1069 << *BarrierChain <<
".\n");
1072 addBarrierChain(FPExceptions);
1073 addBarrierMemoryDeps();
1080 if (
MI.mayRaiseFPException()) {
1082 BarrierChain->addPredBarrier(SU);
1087 <<
"Creating barrier chain and clearing FPExceptions map.\n");
1089 addBarrierChain(FPExceptions);
1091 FPExceptions.push_back(SU);
1096 if (!
MI.mayStore() &&
1097 !(
MI.mayLoad() && !
MI.isDereferenceableInvariantLoad()))
1103 if (BarrierChain && BarrierChain != SU)
1104 BarrierChain->addPredBarrier(SU);
1108 LLVM_DEBUG(
dbgs() <<
"Creating barrier chain and clearing maps.\n");
1111 addBarrierMemoryDeps();
1113 MemOpsProcessed = 0;
1120 LLVM_DEBUG(
dbgs() <<
"Number of in-flight memory operations reached "
1122 <<
" to barrier chain and clearing maps.\n");
1125 addBarrierMemoryDeps();
1134 DAG.MF.getDataLayout());
1135 bool IsStore =
MI.mayStore();
1137 if (!ObjsIdentified) {
1139 for (
auto &[
_, AF] : AnalyzableFrontiers)
1140 addChainDependencies(SU, AF, IsStore);
1142 if (IsStore && UnanalyzableFrontier.shouldUpdate(Objs)) {
1143 updateSequencingStore(UnanalyzableFrontier, SU, std::move(Objs));
1145 if (!IsStore && UnanalyzableFrontier.escapesBaseObjects(Objs))
1146 UnanalyzableFrontier.SeenSequencingLoad =
true;
1147 addChainDependencies(SU, UnanalyzableFrontier.Frontier, IsStore);
1148 (IsStore ? UnanalyzableFrontier.Frontier.Stores
1149 : UnanalyzableFrontier.Frontier.Loads)
1159 if (!SeenValues.
insert(V).second)
1162 MemopFrontier &Frontier = AnalyzableFrontiers[V];
1164 if (IsStore && Frontier.shouldUpdate()) {
1165 updateSequencingStore(Frontier, SU);
1167 addChainDependencies(SU, Frontier, IsStore);
1168 (IsStore ? Frontier.Stores : Frontier.Loads).push_back(SU);
1174 addChainDependencies(SU, UnanalyzableFrontier.Frontier, IsStore);
1179 DAG.FirstDbgValue = DbgMI;
1206 "Only BuildGraph should update Defs/Uses");
1207 Defs.setUniverse(
TRI->getNumRegs());
1208 Uses.setUniverse(
TRI->getNumRegs());
1212 unsigned NumVirtRegs =
MRI.getNumVirtRegs();
1216 std::optional<BatchAAResults> BatchAA;
1218 BatchAA.emplace(*
AA);
1221 *
this, BatchAA.has_value() ? &BatchAA.value() :
nullptr, RPTracker,
1234 PSV->printCustom(OS);
1241 if (!MO.isReg() || !MO.readsReg())
1251 MO.setIsKill(IsKill && !
MRI.isReserved(
Reg));
1265 if (
MI.isDebugOrPseudoInstr())
1286 if (!
MI.isBundled()) {
1297 while (
I->isBundledWithSucc())
1300 if (!
I->isDebugOrPseudoInstr())
1303 }
while (
I != Bundle);
1309#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1320#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1321 if (
EntrySU.getInstr() !=
nullptr)
1325 if (
ExitSU.getInstr() !=
nullptr)
1330#if !defined(NDEBUG) && LLVM_ENABLE_ABI_BREAKING_CHECKS
1331std::string ScheduleDAGInstrs::getGraphNodeLabel(
const SUnit *SU)
const {
1336 else if (SU == &ExitSU)
1347 return "dag." +
BB->getFullName();
1351 return SuccSU == &
ExitSU || !
Topo.IsReachable(PredSU, SuccSU);
1380 std::vector<std::pair<const SUnit *, const SUnit*>> ConnectionPairs;
1384 unsigned ParentNodeID;
1385 unsigned SubInstrCount = 0;
1388 RootData(
unsigned id): NodeID(
id),
1389 ParentNodeID(SchedDFSResult::InvalidSubtreeID) {}
1391 unsigned getSparseSetIndex()
const {
return NodeID; }
1398 RootSet.setUniverse(R.DFSNodeData.size());
1406 return R.DFSNodeData[SU->
NodeNum].SubtreeID
1407 != SchedDFSResult::InvalidSubtreeID;
1413 R.DFSNodeData[SU->
NodeNum].InstrCount =
1437 if ((
InstrCount - R.DFSNodeData[PredNum].InstrCount) < R.SubtreeLimit)
1441 if (R.DFSNodeData[PredNum].SubtreeID == PredNum) {
1444 if (RootSet[PredNum].ParentNodeID == SchedDFSResult::InvalidSubtreeID)
1445 RootSet[PredNum].ParentNodeID = SU->
NodeNum;
1447 else if (RootSet.count(PredNum)) {
1452 RData.SubInstrCount += RootSet[PredNum].SubInstrCount;
1453 RootSet.erase(PredNum);
1463 R.DFSNodeData[Succ->
NodeNum].InstrCount
1470 ConnectionPairs.emplace_back(PredDep.
getSUnit(), Succ);
1476 SubtreeClasses.compress();
1477 R.DFSTreeData.resize(SubtreeClasses.getNumClasses());
1478 assert(SubtreeClasses.getNumClasses() == RootSet.size()
1479 &&
"number of roots should match trees");
1480 for (
const RootData &Root : RootSet) {
1481 unsigned TreeID = SubtreeClasses[Root.NodeID];
1482 if (Root.ParentNodeID != SchedDFSResult::InvalidSubtreeID)
1483 R.DFSTreeData[TreeID].ParentTreeID = SubtreeClasses[Root.ParentNodeID];
1484 R.DFSTreeData[TreeID].SubInstrCount = Root.SubInstrCount;
1490 R.SubtreeConnections.resize(SubtreeClasses.getNumClasses());
1491 R.SubtreeConnectLevels.resize(SubtreeClasses.getNumClasses());
1493 for (
unsigned Idx = 0,
End = R.DFSNodeData.size(); Idx !=
End; ++Idx) {
1494 R.DFSNodeData[Idx].SubtreeID = SubtreeClasses[Idx];
1496 << R.DFSNodeData[Idx].SubtreeID <<
'\n');
1498 for (
const auto &[Pred, Succ] : ConnectionPairs) {
1499 unsigned PredTree = SubtreeClasses[Pred->NodeNum];
1500 unsigned SuccTree = SubtreeClasses[Succ->NodeNum];
1501 if (PredTree == SuccTree)
1503 unsigned Depth = Pred->getDepth();
1513 bool CheckLimit =
true) {
1518 unsigned PredNum = PredSU->
NodeNum;
1519 if (R.DFSNodeData[PredNum].SubtreeID != PredNum)
1524 unsigned NumDataSucs = 0;
1525 for (
const SDep &SuccDep : PredSU->
Succs) {
1527 if (++NumDataSucs >= 4)
1531 if (CheckLimit && R.DFSNodeData[PredNum].InstrCount > R.SubtreeLimit)
1533 R.DFSNodeData[PredNum].SubtreeID = Succ->
NodeNum;
1534 SubtreeClasses.join(Succ->
NodeNum, PredNum);
1545 R.SubtreeConnections[FromTree];
1546 for (SchedDFSResult::Connection &
C : Connections) {
1547 if (
C.TreeID == ToTree) {
1548 C.Level = std::max(
C.Level,
Depth);
1552 Connections.
push_back(SchedDFSResult::Connection(ToTree,
Depth));
1553 FromTree = R.DFSTreeData[FromTree].ParentTreeID;
1554 }
while (FromTree != SchedDFSResult::InvalidSubtreeID);
1563class SchedDAGReverseDFS {
1564 std::vector<std::pair<const SUnit *, SUnit::const_pred_iterator>> DFSStack;
1567 bool isComplete()
const {
return DFSStack.empty(); }
1569 void follow(
const SUnit *SU) {
1570 DFSStack.emplace_back(SU, SU->
Preds.begin());
1572 void advance() { ++DFSStack.back().second; }
1574 const SDep *backtrack() {
1575 DFSStack.pop_back();
1576 return DFSStack.empty() ? nullptr : std::prev(DFSStack.back().second);
1579 const SUnit *getCurr()
const {
return DFSStack.back().first; }
1584 return getCurr()->Preds.
end();
1606 for (
const SUnit &SU : SUnits) {
1610 SchedDAGReverseDFS DFS;
1611 Impl.visitPreorder(&SU);
1615 while (DFS.getPred() != DFS.getPredEnd()) {
1616 const SDep &PredDep = *DFS.getPred();
1624 if (Impl.isVisited(PredDep.
getSUnit())) {
1625 Impl.visitCrossEdge(PredDep, DFS.getCurr());
1628 Impl.visitPreorder(PredDep.
getSUnit());
1632 const SUnit *Child = DFS.getCurr();
1633 const SDep *PredDep = DFS.backtrack();
1634 Impl.visitPostorderNode(Child);
1636 Impl.visitPostorderEdge(*PredDep, DFS.getCurr());
1637 if (DFS.isComplete())
1641 Impl.finalize(SUnits);
1648 for (
const Connection &
C : SubtreeConnections[SubtreeID]) {
1649 SubtreeConnectLevels[
C.TreeID] =
1650 std::max(SubtreeConnectLevels[
C.TreeID],
C.Level);
1652 << SubtreeConnectLevels[
C.TreeID] <<
'\n');
1656#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1666 dbgs() << *
this <<
'\n';
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static unsigned InstrCount
static cl::opt< bool > UseAA("amdgpu-use-aa-in-codegen", cl::desc("Enable the use of AA during codegen."), cl::init(true))
static Register UseReg(const MachineOperand &MO)
const HexagonInstrInfo * TII
Equivalence classes for small integers.
A common definition of LaneBitmask for use in TableGen and CodeGen.
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
This file implements a map that provides insertion order iteration.
MachineRegisterInfo & MRI
static void toggleKills(const MachineRegisterInfo &MRI, LiveRegUnits &LiveRegs, MachineInstr &MI, bool addToLiveRegs)
static cl::opt< unsigned > MaxMemopsInFlight("store-sequencing-max-memops-in-flight", cl::Hidden, cl::init(3000), cl::desc("With store-sequencing DAG construction, if the occupancy of all " "frontiers reaches this threshold, automatically promote the next " "memory operation to a global memory barrier and clear the " "frontiers."))
static bool getUnderlyingObjectsForInstr(const MachineInstr *MI, const MachineFrameInfo &MFI, UnderlyingObjectsVector &Objects, const DataLayout &DL)
If this machine instruction has memory reference information, collect the list of underlying objects ...
static bool hasDataSucc(const SUnit *SU)
static cl::opt< unsigned > MaxFrontierSize("store-sequencing-max-frontier-size", cl::Hidden, cl::init(500), cl::desc("With store-sequencing DAG construction, after the number of " "memops in a frontier reaches this threshold, automatically " "promote the next store and clear the frontier."))
static cl::opt< bool > EnableSchedModel("schedmodel", cl::Hidden, cl::init(true), cl::desc("Use TargetSchedModel for latency lookup"))
static cl::opt< bool > EnableAASchedMI("enable-aa-sched-mi", cl::Hidden, cl::desc("Enable use of AA during MI DAG construction"))
static cl::opt< bool > UseTBAA("use-tbaa-in-sched-mi", cl::Hidden, cl::init(true), cl::desc("Enable use of TBAA during MI DAG construction"))
static cl::opt< unsigned > HugeRegion("dag-maps-huge-region", cl::Hidden, cl::init(500), cl::desc("The limit to use while constructing the DAG " "prior to scheduling, at which point a trade-off " "is made to avoid excessive compile time. Ignored when " "store-sequencing is enabled."))
static cl::opt< bool > EnableSchedItins("scheditins", cl::Hidden, cl::init(true), cl::desc("Use InstrItineraryData for latency lookup"))
static cl::opt< bool > EnableStoreSequencing("enable-store-sequencing", cl::Hidden, cl::init(false), cl::desc("Enable the store-sequencing DAG construction algorithm. This can " "eliminate a large number of redundant control dependencies and " "spurious alias analysis queries at the cost of some unnecessary " "dependencies."))
static cl::opt< bool > SchedPrintCycles("sched-print-cycles", cl::Hidden, cl::init(false), cl::desc("Report top/bottom cycles when dumping SUnit instances"))
This file defines the SmallVector class.
This file defines the SparseSet class derived from the version described in Briggs,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...
ConstMIBundleOperands - Iterate over all operands in a const bundle of machine instructions.
A parsed version of the target data layout string in and methods for querying it.
A set of register units used to track register liveness.
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
bool hasImplicitUseOfPhysReg(MCRegister Reg) const
Return true if this instruction implicitly uses the specified physical register.
LLVM_ABI bool hasImplicitDefOfPhysReg(MCRegister Reg, const MCRegisterInfo *MRI=nullptr) const
Return true if this instruction implicitly defines the specified physical register.
MCRegUnitMaskIterator enumerates a list of register units and their associated lane masks for Reg.
bool isValid() const
Returns true if this iterator is not yet at the end.
LaneBitmask getLaneMask() const
Returns the combination of all lane masks of register in this class.
const bool HasDisjunctSubRegs
Whether the class supports two (or more) disjunct subregister indices.
Instructions::iterator instr_iterator
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasTailCall() const
Returns true if the function contains a tail call.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
bool isBarrier(QueryType Type=AnyInBundle) const
Returns true if the specified instruction stops control flow from executing the instruction immediate...
bool isCall(QueryType Type=AnyInBundle) const
LLVM_ABI bool mayAlias(BatchAAResults *AA, const MachineInstr &Other, bool UseTBAA) const
Returns true if this instruction's memory access aliases the memory access of Other.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
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.
filtered_mop_range all_uses()
Returns an iterator range over all operands that are (explicit or implicit) register uses.
bool isTransient() const
Return true if this is a transient instruction that is either very likely to be eliminated during reg...
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
bool readsReg() const
readsReg - Returns true if this operand reads the previous value of its register.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isRegMask() const
isRegMask - Tests if this is a MO_RegisterMask operand.
void setIsKill(bool Val=true)
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
const uint32_t * getRegMask() const
getRegMask - Returns a bit mask of registers preserved by this RegMask operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
This class implements a map that also provides access to all stored values in a deterministic order.
LLVM_ABI void init(unsigned N)
Initialize an array of N PressureDiffs.
Special value supplied for machine level alias analysis.
Track the current register pressure at some position in the instruction stream, and remember the high...
List of registers defined and used by a machine instruction.
LLVM_ABI void detectDeadDefs(const MachineInstr &MI, LiveIntervals &LIS, const MachineRegisterInfo &MRI)
Use liveness information to find dead defs at MI's dead slot not marked with a dead flag and move the...
LLVM_ABI void adjustLaneLiveness(LiveIntervals &LIS, const MachineRegisterInfo &MRI, SlotIndex Pos)
Use liveness information to find out which uses/defs are partially undefined/dead at Pos and adjust t...
LLVM_ABI void collect(const MachineInstr &MI, const TargetRegisterInfo &TRI, const MachineRegisterInfo &MRI, bool TrackLaneMasks, bool IgnoreDead)
Analyze the given instruction MI and fill in the Uses, Defs and DeadDefs list based on the MachineOpe...
Wrapper class representing virtual and physical registers.
Kind getKind() const
Returns an enum value representing the kind of the dependence.
Kind
These are the different kinds of scheduling dependencies.
@ Output
A register output-dependence (aka WAW).
@ Anti
A register anti-dependence (aka WAR).
@ Data
Regular data dependence (aka true-dependence).
void setLatency(unsigned Lat)
Sets the latency for this edge.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
@ MayAliasMem
Nonvolatile load/Store instructions that may alias.
bool isArtificial() const
Tests if this is an Order dependence that is marked as "artificial", meaning it isn't necessary for c...
Scheduling unit. This is a node in the scheduling DAG.
bool isCall
Is a function call.
bool addPredBarrier(SUnit *SU)
Adds a barrier edge to SU by calling addPred(), with latency 0 generally or latency 1 for a store fol...
unsigned TopReadyCycle
Cycle relative to start when node is ready.
unsigned NodeNum
Entry # of node in the node vector.
bool isUnbuffered
Uses an unbuffered resource.
SmallVectorImpl< SDep >::const_iterator const_pred_iterator
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.
unsigned BotReadyCycle
Cycle relative to end when node is ready.
SmallVector< SDep, 4 > Succs
All sunit successors.
bool hasReservedResource
Uses a reserved resource.
bool isCommutable
Is a commutable instruction.
bool hasPhysRegUses
Has physreg uses.
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.
void visitPostorderNode(const SUnit *SU)
Called once for each node after all predecessors are visited.
bool joinPredSubtree(const SDep &PredDep, const SUnit *Succ, bool CheckLimit=true)
Joins the predecessor subtree with the successor that is its DFS parent.
void addConnection(unsigned FromTree, unsigned ToTree, unsigned Depth)
Called by finalize() to record a connection between trees.
void visitCrossEdge(const SDep &PredDep, const SUnit *Succ)
Adds a connection for cross edges.
void finalize(ArrayRef< SUnit > SUnits)
Sets each node's subtree ID to the representative ID and record connections between trees.
void visitPostorderEdge(const SDep &PredDep, const SUnit *Succ)
Called once for each tree edge after calling visitPostOrderNode on the predecessor.
void visitPreorder(const SUnit *SU)
Initializes this node's instruction count.
bool isVisited(const SUnit *SU) const
Returns true if this node been visited by the DFS traversal.
SchedDFSImpl(SchedDFSResult &r)
Compute the values of each DAG node for various metrics during DFS.
friend class SchedDFSImpl
LLVM_ABI void compute(ArrayRef< SUnit > SUnits)
Compute various metrics for the DAG with given roots.
LLVM_ABI void scheduleTree(unsigned SubtreeID)
Scheduler callback to update SubtreeConnectLevels when a tree is initially scheduled.
ScheduleDAGDependencyBuilder(ScheduleDAGInstrs &DAG, BatchAAResults *AA, RegPressureTracker *RPTracker, PressureDiffs *PDiffs, LiveIntervals *LIS)
A ScheduleDAG for scheduling lists of MachineInstr.
LiveRegUnits LiveRegs
Set of live physical registers for updating kill flags.
DenseMap< MachineInstr *, SUnit * > MISUnitMap
After calling BuildSchedGraph, each machine instruction in the current scheduling region is mapped to...
void addVRegUseDeps(SUnit *SU, unsigned OperIdx)
Adds a register data dependency if the instruction that defines the virtual register used at OperIdx ...
void addVRegDefDeps(SUnit *SU, unsigned OperIdx)
Adds register output and data dependencies from this SUnit to instructions that occur later in the sa...
virtual void finishBlock()
Cleans up after scheduling in the given block.
MachineBasicBlock::iterator end() const
Returns an iterator to the bottom of the current scheduling region.
std::string getDAGName() const override
Returns a label for the region of code covered by the DAG.
MachineBasicBlock * BB
The block in which to insert instructions.
MachineInstr * FirstDbgValue
virtual void startBlock(MachineBasicBlock *BB)
Prepares to perform scheduling in the given block.
void addPhysRegDeps(SUnit *SU, unsigned OperIdx)
Adds register dependencies (data, anti, and output) from this SUnit to following instructions in the ...
friend class ScheduleDAGDependencyBuilder
MachineBasicBlock::iterator RegionEnd
The end of the range to be scheduled.
VReg2SUnitOperIdxMultiMap CurrentVRegUses
Tracks the last instructions in this region using each virtual register.
const MCSchedClassDesc * getSchedClass(SUnit *SU) const
Resolves and cache a resolved scheduling class for an SUnit.
void fixupKills(MachineBasicBlock &MBB)
Fixes register kill flags that scheduling has made invalid.
void addPhysRegDataDeps(SUnit *SU, unsigned OperIdx)
MO is an operand of SU's instruction that defines a physical register.
ScheduleDAGInstrs(MachineFunction &mf, const MachineLoopInfo *mli, bool RemoveKillFlags=false)
LaneBitmask getLaneMaskForMO(const MachineOperand &MO) const
Returns a mask for which lanes get read/written by the given (register) machine operand.
DbgValueVector DbgValues
Remember instruction that precedes DBG_VALUE.
SUnit * newSUnit(MachineInstr *MI)
Creates a new SUnit and return a ptr to it.
void initSUnits()
Creates an SUnit for each real instruction, numbered in top-down topological order.
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
ScheduleDAGTopologicalSort Topo
Topo - A topological ordering for SUnits which permits fast IsReachable and similar queries.
bool TrackLaneMasks
Whether lane masks should get tracked.
void dumpNode(const SUnit &SU) const override
RegUnit2SUnitsMap Defs
Defs, Uses - Remember where defs and uses of each register are as we iterate upward through the instr...
VReg2SUnitMultiMap CurrentVRegDefs
Tracks the last instruction(s) in this region defining each virtual register.
MachineBasicBlock::iterator begin() const
Returns an iterator to the top of the current scheduling region.
void buildSchedGraph(AAResults *AA, RegPressureTracker *RPTracker=nullptr, PressureDiffs *PDiffs=nullptr, LiveIntervals *LIS=nullptr, bool TrackLaneMasks=false)
Builds SUnits for the current region.
TargetSchedModel SchedModel
TargetSchedModel provides an interface to the machine model.
virtual void exitRegion()
Called when the scheduler has finished scheduling the current region.
bool canAddEdge(SUnit *SuccSU, SUnit *PredSU)
True if an edge can be added from PredSU to SuccSU without creating a cycle.
const MachineLoopInfo * MLI
bool RemoveKillFlags
True if the DAG builder should remove kill flags (in preparation for rescheduling).
MachineBasicBlock::iterator RegionBegin
The beginning of the range to be scheduled.
void addSchedBarrierDeps()
Adds dependencies from instructions in the current list of instructions being scheduled to scheduling...
virtual void enterRegion(MachineBasicBlock *bb, MachineBasicBlock::iterator begin, MachineBasicBlock::iterator end, unsigned regioninstrs)
Initialize the DAG and common scheduler state for a new scheduling region.
void dump() const override
unsigned NumRegionInstrs
Instructions in this region (distance(RegionBegin, RegionEnd)).
const MachineFrameInfo & MFI
bool deadDefHasNoUse(const MachineOperand &MO)
Returns true if the def register in MO has no uses.
MachineRegisterInfo & MRI
Virtual/real register map.
void clearDAG()
Clears the DAG state (between regions).
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.
ScheduleDAG(const ScheduleDAG &)=delete
void dumpNodeAll(const SUnit &SU) const
void dumpNodeName(const SUnit &SU) const
SUnit ExitSU
Special node for the region exit.
SlotIndex - An opaque wrapper around machine indexes.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
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...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
std::pair< iterator, iterator > RangePair
iterator_base< SparseMultiSet * > iterator
SparseSet - Fast set implementation for objects that can be identified by small unsigned keys.
TargetInstrInfo - Interface to description of machine instruction set.
TargetSubtargetInfo - Generic base class for all target subtargets.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
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.
initializer< Ty > init(const Ty &Val)
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.
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.
SmallVector< ValueType, 4 > UnderlyingObjectsVector
LLVM_ABI bool getUnderlyingObjectsForCodeGen(const Value *V, SmallVectorImpl< Value * > &Objects)
This is a wrapper around getUnderlyingObjects and adds support for basic ptrtoint+arithmetic+inttoptr...
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IterT skipDebugInstructionsBackward(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It until it points to a non-debug instruction or to Begin and return the resulting iterator...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
@ End
Run the machine verifier once, at the end of the pipeline.
LLVM_ABI bool isIdentifiedObject(const Value *V)
Return true if this pointer refers to a distinct and identifiable object.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.
MCRegisterClass TargetRegisterClass
Represent the ILP of the subDAG rooted at a DAG node.
unsigned Length
Length may either correspond to depth or height, depending on direction, and cycles or nodes dependin...
LLVM_ABI void dump() const
LLVM_ABI void print(raw_ostream &OS) const
static constexpr LaneBitmask getAll()
constexpr bool any() const
Summarize the scheduling resources required for an instruction of a particular scheduling class.
Identify one of the processor resource kinds consumed by a particular scheduling class for the specif...
Record a physical register access.
Mapping from virtual register to SUnit including an operand index.
An individual mapping from virtual register number to SUnit.