123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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_CODEGEN_MACHINEPIPELINER_H
- #define LLVM_CODEGEN_MACHINEPIPELINER_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 AAResults;
- 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;
- 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(AAResults *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(Register 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 initiation interval for this schedule.
- int getInitiationInterval() const { return InitiationInterval; }
- /// 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_CODEGEN_MACHINEPIPELINER_H
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|