003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/include/llvm/CodeGen
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
include
/
llvm
/
CodeGen
/
📁
..
📄
AccelTable.h
(13.54 KB)
📄
Analysis.h
(6.04 KB)
📄
AntiDepBreaker.h
(3.78 KB)
📄
AsmPrinter.h
(27.35 KB)
📄
AsmPrinterHandler.h
(2.6 KB)
📄
AtomicExpandUtils.h
(2.49 KB)
📄
BasicTTIImpl.h
(73.64 KB)
📄
BuiltinGCs.h
(1008 B)
📄
CSEConfigBase.h
(1.09 KB)
📄
CalcSpillWeights.h
(4.69 KB)
📄
CallingConvLower.h
(21 KB)
📄
CommandFlags.h
(3.65 KB)
📄
CostTable.h
(1.87 KB)
📄
DAGCombine.h
(606 B)
📄
DFAPacketizer.h
(7.47 KB)
📄
DIE.h
(32.19 KB)
📄
DIEValue.def
(1.4 KB)
📄
DbgEntityHistoryCalculator.h
(4.37 KB)
📄
DebugHandlerBase.h
(4.68 KB)
📄
DwarfStringPoolEntry.h
(2.18 KB)
📄
EdgeBundles.h
(2.13 KB)
📄
ExecutionDomainFix.h
(7.72 KB)
📄
ExpandReductions.h
(726 B)
📄
FastISel.h
(22.87 KB)
📄
FaultMaps.h
(6.66 KB)
📄
FunctionLoweringInfo.h
(9.68 KB)
📄
GCMetadata.h
(7.24 KB)
📄
GCMetadataPrinter.h
(2.46 KB)
📄
GCStrategy.h
(5.25 KB)
📁
GlobalISel
📄
ISDOpcodes.h
(52.75 KB)
📄
IndirectThunks.h
(3.85 KB)
📄
IntrinsicLowering.h
(1.67 KB)
📄
LatencyPriorityQueue.h
(3.09 KB)
📄
LazyMachineBlockFrequencyInfo.h
(2.82 KB)
📄
LexicalScopes.h
(10.06 KB)
📄
LinkAllAsmWriterComponents.h
(1.34 KB)
📄
LinkAllCodegenComponents.h
(2.18 KB)
📄
LiveInterval.h
(37.24 KB)
📄
LiveIntervalCalc.h
(2.91 KB)
📄
LiveIntervalUnion.h
(6.93 KB)
📄
LiveIntervals.h
(19.86 KB)
📄
LivePhysRegs.h
(7.51 KB)
📄
LiveRangeCalc.h
(11.49 KB)
📄
LiveRangeEdit.h
(10.45 KB)
📄
LiveRegMatrix.h
(6.18 KB)
📄
LiveRegUnits.h
(6.24 KB)
📄
LiveStacks.h
(3.35 KB)
📄
LiveVariables.h
(12.98 KB)
📄
LoopTraversal.h
(4.38 KB)
📄
LowLevelType.h
(1.28 KB)
📄
MBFIWrapper.h
(1.58 KB)
📄
MIRFormatter.h
(3.13 KB)
📁
MIRParser
📄
MIRPrinter.h
(1.73 KB)
📄
MIRYamlMapping.h
(23.95 KB)
📄
MachORelocation.h
(2.19 KB)
📄
MachineBasicBlock.h
(42.95 KB)
📄
MachineBlockFrequencyInfo.h
(3.21 KB)
📄
MachineBranchProbabilityInfo.h
(2.69 KB)
📄
MachineCombinerPattern.h
(3.5 KB)
📄
MachineConstantPool.h
(5.25 KB)
📄
MachineDominanceFrontier.h
(2.93 KB)
📄
MachineDominators.h
(9.59 KB)
📄
MachineFrameInfo.h
(34.84 KB)
📄
MachineFunction.h
(42.94 KB)
📄
MachineFunctionPass.h
(2.93 KB)
📄
MachineInstr.h
(73.72 KB)
📄
MachineInstrBuilder.h
(22.84 KB)
📄
MachineInstrBundle.h
(10.16 KB)
📄
MachineInstrBundleIterator.h
(10.92 KB)
📄
MachineJumpTableInfo.h
(4.66 KB)
📄
MachineLoopInfo.h
(7.3 KB)
📄
MachineLoopUtils.h
(1.74 KB)
📄
MachineMemOperand.h
(12.69 KB)
📄
MachineModuleInfo.h
(9.88 KB)
📄
MachineModuleInfoImpls.h
(3.36 KB)
📄
MachineOperand.h
(37.64 KB)
📄
MachineOptimizationRemarkEmitter.h
(8.99 KB)
📄
MachineOutliner.h
(8.04 KB)
📄
MachinePassRegistry.h
(6.1 KB)
📄
MachinePipeliner.h
(21.17 KB)
📄
MachinePostDominators.h
(2.93 KB)
📄
MachineRegionInfo.h
(5.93 KB)
📄
MachineRegisterInfo.h
(46.75 KB)
📄
MachineSSAUpdater.h
(4.37 KB)
📄
MachineScheduler.h
(36.6 KB)
📄
MachineSizeOpts.h
(1.86 KB)
📄
MachineTraceMetrics.h
(17.17 KB)
📄
MacroFusion.h
(1.96 KB)
📄
ModuloSchedule.h
(15.8 KB)
📄
NonRelocatableStringpool.h
(2.9 KB)
📁
PBQP
📄
PBQPRAConstraint.h
(1.83 KB)
📄
ParallelCG.h
(1.66 KB)
📄
Passes.h
(18.96 KB)
📄
PreISelIntrinsicLowering.h
(944 B)
📄
PseudoSourceValue.h
(6.21 KB)
📄
RDFGraph.h
(33.73 KB)
📄
RDFLiveness.h
(5.01 KB)
📄
RDFRegisters.h
(6.51 KB)
📄
ReachingDefAnalysis.h
(10.68 KB)
📄
RegAllocPBQP.h
(16.47 KB)
📄
RegAllocRegistry.h
(2.27 KB)
📄
Register.h
(5.61 KB)
📄
RegisterClassInfo.h
(4.86 KB)
📄
RegisterPressure.h
(21.04 KB)
📄
RegisterScavenging.h
(8.73 KB)
📄
RegisterUsageInfo.h
(2.3 KB)
📄
ResourcePriorityQueue.h
(4.19 KB)
📄
RuntimeLibcalls.h
(3.05 KB)
📄
SDNodeProperties.td
(1.57 KB)
📄
ScheduleDAG.h
(28.92 KB)
📄
ScheduleDAGInstrs.h
(15.49 KB)
📄
ScheduleDAGMutation.h
(1021 B)
📄
ScheduleDFS.h
(5.79 KB)
📄
ScheduleHazardRecognizer.h
(4.65 KB)
📄
SchedulerRegistry.h
(4.27 KB)
📄
ScoreboardHazardRecognizer.h
(3.7 KB)
📄
SelectionDAG.h
(89.12 KB)
📄
SelectionDAGAddressAnalysis.h
(3.58 KB)
📄
SelectionDAGISel.h
(13.48 KB)
📄
SelectionDAGNodes.h
(91.77 KB)
📄
SelectionDAGTargetInfo.h
(7.99 KB)
📄
SlotIndexes.h
(24.12 KB)
📄
Spiller.h
(1.16 KB)
📄
StackMaps.h
(11.45 KB)
📄
StackProtector.h
(4.1 KB)
📄
SwiftErrorValueTracking.h
(3.87 KB)
📄
SwitchLoweringUtils.h
(9.51 KB)
📄
TailDuplicator.h
(5.54 KB)
📄
TargetCallingConv.h
(8.26 KB)
📄
TargetFrameLowering.h
(19.21 KB)
📄
TargetInstrInfo.h
(84.48 KB)
📄
TargetLowering.h
(194.17 KB)
📄
TargetLoweringObjectFileImpl.h
(11.63 KB)
📄
TargetOpcodes.h
(1.37 KB)
📄
TargetPassConfig.h
(17.9 KB)
📄
TargetRegisterInfo.h
(48.65 KB)
📄
TargetSchedule.h
(7.75 KB)
📄
TargetSubtargetInfo.h
(12.53 KB)
📄
UnreachableBlockElim.h
(1.39 KB)
📄
ValueTypes.h
(17.2 KB)
📄
ValueTypes.td
(11.42 KB)
📄
VirtRegMap.h
(6.37 KB)
📄
WasmEHFuncInfo.h
(1.92 KB)
📄
WinEHFuncInfo.h
(4.01 KB)
Editing: MachinePipeliner.h
//===- MachinePipeliner.h - Machine Software Pipeliner Pass -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // An implementation of the Swing Modulo Scheduling (SMS) software pipeliner. // // Software pipelining (SWP) is an instruction scheduling technique for loops // that overlap loop iterations and exploits ILP via a compiler transformation. // // Swing Modulo Scheduling is an implementation of software pipelining // that generates schedules that are near optimal in terms of initiation // interval, register requirements, and stage count. See the papers: // // "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa, // A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Proceedings of the 1996 // Conference on Parallel Architectures and Compilation Techiniques. // // "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J. // Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE // Transactions on Computers, Vol. 50, No. 3, 2001. // // "An Implementation of Swing Modulo Scheduling With Extensions for // Superblocks", by T. Lattner, Master's Thesis, University of Illinois at // Urbana-Champaign, 2005. // // // The SMS algorithm consists of three main steps after computing the minimal // initiation interval (MII). // 1) Analyze the dependence graph and compute information about each // instruction in the graph. // 2) Order the nodes (instructions) by priority based upon the heuristics // described in the algorithm. // 3) Attempt to schedule the nodes in the specified order using the MII. // //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_CODEGEN_MACHINEPIPELINER_H #define LLVM_LIB_CODEGEN_MACHINEPIPELINER_H #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/RegisterClassInfo.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/InitializePasses.h" namespace llvm { class NodeSet; class SMSchedule; extern cl::opt<bool> SwpEnableCopyToPhi; /// The main class in the implementation of the target independent /// software pipeliner pass. class MachinePipeliner : public MachineFunctionPass { public: MachineFunction *MF = nullptr; MachineOptimizationRemarkEmitter *ORE = nullptr; const MachineLoopInfo *MLI = nullptr; const MachineDominatorTree *MDT = nullptr; const InstrItineraryData *InstrItins; const TargetInstrInfo *TII = nullptr; RegisterClassInfo RegClassInfo; bool disabledByPragma = false; unsigned II_setByPragma = 0; #ifndef NDEBUG static int NumTries; #endif /// Cache the target analysis information about the loop. struct LoopInfo { MachineBasicBlock *TBB = nullptr; MachineBasicBlock *FBB = nullptr; SmallVector<MachineOperand, 4> BrCond; MachineInstr *LoopInductionVar = nullptr; MachineInstr *LoopCompare = nullptr; }; LoopInfo LI; static char ID; MachinePipeliner() : MachineFunctionPass(ID) { initializeMachinePipelinerPass(*PassRegistry::getPassRegistry()); } bool runOnMachineFunction(MachineFunction &MF) override; void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<AAResultsWrapperPass>(); AU.addPreserved<AAResultsWrapperPass>(); AU.addRequired<MachineLoopInfo>(); AU.addRequired<MachineDominatorTree>(); AU.addRequired<LiveIntervals>(); AU.addRequired<MachineOptimizationRemarkEmitterPass>(); MachineFunctionPass::getAnalysisUsage(AU); } private: void preprocessPhiNodes(MachineBasicBlock &B); bool canPipelineLoop(MachineLoop &L); bool scheduleLoop(MachineLoop &L); bool swingModuloScheduler(MachineLoop &L); void setPragmaPipelineOptions(MachineLoop &L); }; /// This class builds the dependence graph for the instructions in a loop, /// and attempts to schedule the instructions using the SMS algorithm. class SwingSchedulerDAG : public ScheduleDAGInstrs { MachinePipeliner &Pass; /// The minimum initiation interval between iterations for this schedule. unsigned MII = 0; /// The maximum initiation interval between iterations for this schedule. unsigned MAX_II = 0; /// Set to true if a valid pipelined schedule is found for the loop. bool Scheduled = false; MachineLoop &Loop; LiveIntervals &LIS; const RegisterClassInfo &RegClassInfo; unsigned II_setByPragma = 0; /// A toplogical ordering of the SUnits, which is needed for changing /// dependences and iterating over the SUnits. ScheduleDAGTopologicalSort Topo; struct NodeInfo { int ASAP = 0; int ALAP = 0; int ZeroLatencyDepth = 0; int ZeroLatencyHeight = 0; NodeInfo() = default; }; /// Computed properties for each node in the graph. std::vector<NodeInfo> ScheduleInfo; enum OrderKind { BottomUp = 0, TopDown = 1 }; /// Computed node ordering for scheduling. SetVector<SUnit *> NodeOrder; using NodeSetType = SmallVector<NodeSet, 8>; using ValueMapTy = DenseMap<unsigned, unsigned>; using MBBVectorTy = SmallVectorImpl<MachineBasicBlock *>; using InstrMapTy = DenseMap<MachineInstr *, MachineInstr *>; /// Instructions to change when emitting the final schedule. DenseMap<SUnit *, std::pair<unsigned, int64_t>> InstrChanges; /// We may create a new instruction, so remember it because it /// must be deleted when the pass is finished. DenseMap<MachineInstr*, MachineInstr *> NewMIs; /// Ordered list of DAG postprocessing steps. std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations; /// Helper class to implement Johnson's circuit finding algorithm. class Circuits { std::vector<SUnit> &SUnits; SetVector<SUnit *> Stack; BitVector Blocked; SmallVector<SmallPtrSet<SUnit *, 4>, 10> B; SmallVector<SmallVector<int, 4>, 16> AdjK; // Node to Index from ScheduleDAGTopologicalSort std::vector<int> *Node2Idx; unsigned NumPaths; static unsigned MaxPaths; public: Circuits(std::vector<SUnit> &SUs, ScheduleDAGTopologicalSort &Topo) : SUnits(SUs), Blocked(SUs.size()), B(SUs.size()), AdjK(SUs.size()) { Node2Idx = new std::vector<int>(SUs.size()); unsigned Idx = 0; for (const auto &NodeNum : Topo) Node2Idx->at(NodeNum) = Idx++; } ~Circuits() { delete Node2Idx; } /// Reset the data structures used in the circuit algorithm. void reset() { Stack.clear(); Blocked.reset(); B.assign(SUnits.size(), SmallPtrSet<SUnit *, 4>()); NumPaths = 0; } void createAdjacencyStructure(SwingSchedulerDAG *DAG); bool circuit(int V, int S, NodeSetType &NodeSets, bool HasBackedge = false); void unblock(int U); }; struct CopyToPhiMutation : public ScheduleDAGMutation { void apply(ScheduleDAGInstrs *DAG) override; }; public: SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis, const RegisterClassInfo &rci, unsigned II) : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), Loop(L), LIS(lis), RegClassInfo(rci), II_setByPragma(II), Topo(SUnits, &ExitSU) { P.MF->getSubtarget().getSMSMutations(Mutations); if (SwpEnableCopyToPhi) Mutations.push_back(std::make_unique<CopyToPhiMutation>()); } void schedule() override; void finishBlock() override; /// Return true if the loop kernel has been scheduled. bool hasNewSchedule() { return Scheduled; } /// Return the earliest time an instruction may be scheduled. int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; } /// Return the latest time an instruction my be scheduled. int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; } /// The mobility function, which the number of slots in which /// an instruction may be scheduled. int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); } /// The depth, in the dependence graph, for a node. unsigned getDepth(SUnit *Node) { return Node->getDepth(); } /// The maximum unweighted length of a path from an arbitrary node to the /// given node in which each edge has latency 0 int getZeroLatencyDepth(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ZeroLatencyDepth; } /// The height, in the dependence graph, for a node. unsigned getHeight(SUnit *Node) { return Node->getHeight(); } /// The maximum unweighted length of a path from the given node to an /// arbitrary node in which each edge has latency 0 int getZeroLatencyHeight(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight; } /// Return true if the dependence is a back-edge in the data dependence graph. /// Since the DAG doesn't contain cycles, we represent a cycle in the graph /// using an anti dependence from a Phi to an instruction. bool isBackedge(SUnit *Source, const SDep &Dep) { if (Dep.getKind() != SDep::Anti) return false; return Source->getInstr()->isPHI() || Dep.getSUnit()->getInstr()->isPHI(); } bool isLoopCarriedDep(SUnit *Source, const SDep &Dep, bool isSucc = true); /// The distance function, which indicates that operation V of iteration I /// depends on operations U of iteration I-distance. unsigned getDistance(SUnit *U, SUnit *V, const SDep &Dep) { // Instructions that feed a Phi have a distance of 1. Computing larger // values for arrays requires data dependence information. if (V->getInstr()->isPHI() && Dep.getKind() == SDep::Anti) return 1; return 0; } void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule); void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs); /// Return the new base register that was stored away for the changed /// instruction. unsigned getInstrBaseReg(SUnit *SU) { DenseMap<SUnit *, std::pair<unsigned, int64_t>>::iterator It = InstrChanges.find(SU); if (It != InstrChanges.end()) return It->second.first; return 0; } void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) { Mutations.push_back(std::move(Mutation)); } static bool classof(const ScheduleDAGInstrs *DAG) { return true; } private: void addLoopCarriedDependences(AliasAnalysis *AA); void updatePhiDependences(); void changeDependences(); unsigned calculateResMII(); unsigned calculateRecMII(NodeSetType &RecNodeSets); void findCircuits(NodeSetType &NodeSets); void fuseRecs(NodeSetType &NodeSets); void removeDuplicateNodes(NodeSetType &NodeSets); void computeNodeFunctions(NodeSetType &NodeSets); void registerPressureFilter(NodeSetType &NodeSets); void colocateNodeSets(NodeSetType &NodeSets); void checkNodeSets(NodeSetType &NodeSets); void groupRemainingNodes(NodeSetType &NodeSets); void addConnectedNodes(SUnit *SU, NodeSet &NewSet, SetVector<SUnit *> &NodesAdded); void computeNodeOrder(NodeSetType &NodeSets); void checkValidNodeOrder(const NodeSetType &Circuits) const; bool schedulePipeline(SMSchedule &Schedule); bool computeDelta(MachineInstr &MI, unsigned &Delta); MachineInstr *findDefInLoop(unsigned Reg); bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos, unsigned &OffsetPos, unsigned &NewBase, int64_t &NewOffset); void postprocessDAG(); /// Set the Minimum Initiation Interval for this schedule attempt. void setMII(unsigned ResMII, unsigned RecMII); /// Set the Maximum Initiation Interval for this schedule attempt. void setMAX_II(); }; /// A NodeSet contains a set of SUnit DAG nodes with additional information /// that assigns a priority to the set. class NodeSet { SetVector<SUnit *> Nodes; bool HasRecurrence = false; unsigned RecMII = 0; int MaxMOV = 0; unsigned MaxDepth = 0; unsigned Colocate = 0; SUnit *ExceedPressure = nullptr; unsigned Latency = 0; public: using iterator = SetVector<SUnit *>::const_iterator; NodeSet() = default; NodeSet(iterator S, iterator E) : Nodes(S, E), HasRecurrence(true) { Latency = 0; for (unsigned i = 0, e = Nodes.size(); i < e; ++i) { DenseMap<SUnit *, unsigned> SuccSUnitLatency; for (const SDep &Succ : Nodes[i]->Succs) { auto SuccSUnit = Succ.getSUnit(); if (!Nodes.count(SuccSUnit)) continue; unsigned CurLatency = Succ.getLatency(); unsigned MaxLatency = 0; if (SuccSUnitLatency.count(SuccSUnit)) MaxLatency = SuccSUnitLatency[SuccSUnit]; if (CurLatency > MaxLatency) SuccSUnitLatency[SuccSUnit] = CurLatency; } for (auto SUnitLatency : SuccSUnitLatency) Latency += SUnitLatency.second; } } bool insert(SUnit *SU) { return Nodes.insert(SU); } void insert(iterator S, iterator E) { Nodes.insert(S, E); } template <typename UnaryPredicate> bool remove_if(UnaryPredicate P) { return Nodes.remove_if(P); } unsigned count(SUnit *SU) const { return Nodes.count(SU); } bool hasRecurrence() { return HasRecurrence; }; unsigned size() const { return Nodes.size(); } bool empty() const { return Nodes.empty(); } SUnit *getNode(unsigned i) const { return Nodes[i]; }; void setRecMII(unsigned mii) { RecMII = mii; }; void setColocate(unsigned c) { Colocate = c; }; void setExceedPressure(SUnit *SU) { ExceedPressure = SU; } bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; } int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; } int getRecMII() { return RecMII; } /// Summarize node functions for the entire node set. void computeNodeSetInfo(SwingSchedulerDAG *SSD) { for (SUnit *SU : *this) { MaxMOV = std::max(MaxMOV, SSD->getMOV(SU)); MaxDepth = std::max(MaxDepth, SSD->getDepth(SU)); } } unsigned getLatency() { return Latency; } unsigned getMaxDepth() { return MaxDepth; } void clear() { Nodes.clear(); RecMII = 0; HasRecurrence = false; MaxMOV = 0; MaxDepth = 0; Colocate = 0; ExceedPressure = nullptr; } operator SetVector<SUnit *> &() { return Nodes; } /// Sort the node sets by importance. First, rank them by recurrence MII, /// then by mobility (least mobile done first), and finally by depth. /// Each node set may contain a colocate value which is used as the first /// tie breaker, if it's set. bool operator>(const NodeSet &RHS) const { if (RecMII == RHS.RecMII) { if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate) return Colocate < RHS.Colocate; if (MaxMOV == RHS.MaxMOV) return MaxDepth > RHS.MaxDepth; return MaxMOV < RHS.MaxMOV; } return RecMII > RHS.RecMII; } bool operator==(const NodeSet &RHS) const { return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV && MaxDepth == RHS.MaxDepth; } bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); } iterator begin() { return Nodes.begin(); } iterator end() { return Nodes.end(); } void print(raw_ostream &os) const; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void dump() const; #endif }; // 16 was selected based on the number of ProcResource kinds for all // existing Subtargets, so that SmallVector don't need to resize too often. static const int DefaultProcResSize = 16; class ResourceManager { private: const MCSubtargetInfo *STI; const MCSchedModel &SM; const bool UseDFA; std::unique_ptr<DFAPacketizer> DFAResources; /// Each processor resource is associated with a so-called processor resource /// mask. This vector allows to correlate processor resource IDs with /// processor resource masks. There is exactly one element per each processor /// resource declared by the scheduling model. llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceMasks; llvm::SmallVector<uint64_t, DefaultProcResSize> ProcResourceCount; public: ResourceManager(const TargetSubtargetInfo *ST) : STI(ST), SM(ST->getSchedModel()), UseDFA(ST->useDFAforSMS()), ProcResourceMasks(SM.getNumProcResourceKinds(), 0), ProcResourceCount(SM.getNumProcResourceKinds(), 0) { if (UseDFA) DFAResources.reset(ST->getInstrInfo()->CreateTargetScheduleState(*ST)); initProcResourceVectors(SM, ProcResourceMasks); } void initProcResourceVectors(const MCSchedModel &SM, SmallVectorImpl<uint64_t> &Masks); /// Check if the resources occupied by a MCInstrDesc are available in /// the current state. bool canReserveResources(const MCInstrDesc *MID) const; /// Reserve the resources occupied by a MCInstrDesc and change the current /// state to reflect that change. void reserveResources(const MCInstrDesc *MID); /// Check if the resources occupied by a machine instruction are available /// in the current state. bool canReserveResources(const MachineInstr &MI) const; /// Reserve the resources occupied by a machine instruction and change the /// current state to reflect that change. void reserveResources(const MachineInstr &MI); /// Reset the state void clearResources(); }; /// This class represents the scheduled code. The main data structure is a /// map from scheduled cycle to instructions. During scheduling, the /// data structure explicitly represents all stages/iterations. When /// the algorithm finshes, the schedule is collapsed into a single stage, /// which represents instructions from different loop iterations. /// /// The SMS algorithm allows negative values for cycles, so the first cycle /// in the schedule is the smallest cycle value. class SMSchedule { private: /// Map from execution cycle to instructions. DenseMap<int, std::deque<SUnit *>> ScheduledInstrs; /// Map from instruction to execution cycle. std::map<SUnit *, int> InstrToCycle; /// Keep track of the first cycle value in the schedule. It starts /// as zero, but the algorithm allows negative values. int FirstCycle = 0; /// Keep track of the last cycle value in the schedule. int LastCycle = 0; /// The initiation interval (II) for the schedule. int InitiationInterval = 0; /// Target machine information. const TargetSubtargetInfo &ST; /// Virtual register information. MachineRegisterInfo &MRI; ResourceManager ProcItinResources; public: SMSchedule(MachineFunction *mf) : ST(mf->getSubtarget()), MRI(mf->getRegInfo()), ProcItinResources(&ST) {} void reset() { ScheduledInstrs.clear(); InstrToCycle.clear(); FirstCycle = 0; LastCycle = 0; InitiationInterval = 0; } /// Set the initiation interval for this schedule. void setInitiationInterval(int ii) { InitiationInterval = ii; } /// Return the first cycle in the completed schedule. This /// can be a negative value. int getFirstCycle() const { return FirstCycle; } /// Return the last cycle in the finalized schedule. int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; } /// Return the cycle of the earliest scheduled instruction in the dependence /// chain. int earliestCycleInChain(const SDep &Dep); /// Return the cycle of the latest scheduled instruction in the dependence /// chain. int latestCycleInChain(const SDep &Dep); void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart, int *MinEnd, int *MaxStart, int II, SwingSchedulerDAG *DAG); bool insert(SUnit *SU, int StartCycle, int EndCycle, int II); /// Iterators for the cycle to instruction map. using sched_iterator = DenseMap<int, std::deque<SUnit *>>::iterator; using const_sched_iterator = DenseMap<int, std::deque<SUnit *>>::const_iterator; /// Return true if the instruction is scheduled at the specified stage. bool isScheduledAtStage(SUnit *SU, unsigned StageNum) { return (stageScheduled(SU) == (int)StageNum); } /// Return the stage for a scheduled instruction. Return -1 if /// the instruction has not been scheduled. int stageScheduled(SUnit *SU) const { std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU); if (it == InstrToCycle.end()) return -1; return (it->second - FirstCycle) / InitiationInterval; } /// Return the cycle for a scheduled instruction. This function normalizes /// the first cycle to be 0. unsigned cycleScheduled(SUnit *SU) const { std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU); assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled."); return (it->second - FirstCycle) % InitiationInterval; } /// Return the maximum stage count needed for this schedule. unsigned getMaxStageCount() { return (LastCycle - FirstCycle) / InitiationInterval; } /// Return the instructions that are scheduled at the specified cycle. std::deque<SUnit *> &getInstructions(int cycle) { return ScheduledInstrs[cycle]; } bool isValidSchedule(SwingSchedulerDAG *SSD); void finalizeSchedule(SwingSchedulerDAG *SSD); void orderDependence(SwingSchedulerDAG *SSD, SUnit *SU, std::deque<SUnit *> &Insts); bool isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi); bool isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD, MachineInstr *Def, MachineOperand &MO); void print(raw_ostream &os) const; void dump() const; }; } // end namespace llvm #endif // LLVM_LIB_CODEGEN_MACHINEPIPELINER_H
Upload File
Create Folder