1234285Sdim//==- MachineScheduler.h - MachineInstr Scheduling Pass ----------*- C++ -*-==// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10263508Sdim// This file provides an interface for customizing the standard MachineScheduler 11263508Sdim// pass. Note that the entire pass may be replaced as follows: 12263508Sdim// 13263508Sdim// <Target>TargetMachine::createPassConfig(PassManagerBase &PM) { 14263508Sdim// PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID); 15263508Sdim// ...} 16263508Sdim// 17263508Sdim// The MachineScheduler pass is only responsible for choosing the regions to be 18263508Sdim// scheduled. Targets can override the DAG builder and scheduler without 19263508Sdim// replacing the pass as follows: 20263508Sdim// 21263508Sdim// ScheduleDAGInstrs *<Target>PassConfig:: 22263508Sdim// createMachineScheduler(MachineSchedContext *C) { 23263508Sdim// return new CustomMachineScheduler(C); 24263508Sdim// } 25263508Sdim// 26263508Sdim// The default scheduler, ScheduleDAGMI, builds the DAG and drives list 27263508Sdim// scheduling while updating the instruction stream, register pressure, and live 28263508Sdim// intervals. Most targets don't need to override the DAG builder and list 29263508Sdim// schedulier, but subtargets that require custom scheduling heuristics may 30263508Sdim// plugin an alternate MachineSchedStrategy. The strategy is responsible for 31263508Sdim// selecting the highest priority node from the list: 32263508Sdim// 33263508Sdim// ScheduleDAGInstrs *<Target>PassConfig:: 34263508Sdim// createMachineScheduler(MachineSchedContext *C) { 35263508Sdim// return new ScheduleDAGMI(C, CustomStrategy(C)); 36263508Sdim// } 37263508Sdim// 38263508Sdim// The DAG builder can also be customized in a sense by adding DAG mutations 39263508Sdim// that will run after DAG building and before list scheduling. DAG mutations 40263508Sdim// can adjust dependencies based on target-specific knowledge or add weak edges 41263508Sdim// to aid heuristics: 42263508Sdim// 43263508Sdim// ScheduleDAGInstrs *<Target>PassConfig:: 44263508Sdim// createMachineScheduler(MachineSchedContext *C) { 45263508Sdim// ScheduleDAGMI *DAG = new ScheduleDAGMI(C, CustomStrategy(C)); 46263508Sdim// DAG->addMutation(new CustomDependencies(DAG->TII, DAG->TRI)); 47263508Sdim// return DAG; 48263508Sdim// } 49263508Sdim// 50263508Sdim// A target that supports alternative schedulers can use the 51263508Sdim// MachineSchedRegistry to allow command line selection. This can be done by 52234285Sdim// implementing the following boilerplate: 53234285Sdim// 54234285Sdim// static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) { 55234285Sdim// return new CustomMachineScheduler(C); 56234285Sdim// } 57234285Sdim// static MachineSchedRegistry 58234285Sdim// SchedCustomRegistry("custom", "Run my target's custom scheduler", 59234285Sdim// createCustomMachineSched); 60234285Sdim// 61234285Sdim// 62263508Sdim// Finally, subtargets that don't need to implement custom heuristics but would 63263508Sdim// like to configure the GenericScheduler's policy for a given scheduler region, 64263508Sdim// including scheduling direction and register pressure tracking policy, can do 65263508Sdim// this: 66263508Sdim// 67263508Sdim// void <SubTarget>Subtarget:: 68263508Sdim// overrideSchedPolicy(MachineSchedPolicy &Policy, 69263508Sdim// MachineInstr *begin, 70263508Sdim// MachineInstr *end, 71263508Sdim// unsigned NumRegionInstrs) const { 72263508Sdim// Policy.<Flag> = true; 73263508Sdim// } 74263508Sdim// 75234285Sdim//===----------------------------------------------------------------------===// 76234285Sdim 77249423Sdim#ifndef LLVM_CODEGEN_MACHINESCHEDULER_H 78249423Sdim#define LLVM_CODEGEN_MACHINESCHEDULER_H 79234285Sdim 80234285Sdim#include "llvm/CodeGen/MachinePassRegistry.h" 81243830Sdim#include "llvm/CodeGen/RegisterPressure.h" 82243830Sdim#include "llvm/CodeGen/ScheduleDAGInstrs.h" 83234285Sdim 84234285Sdimnamespace llvm { 85234285Sdim 86243830Sdimextern cl::opt<bool> ForceTopDown; 87243830Sdimextern cl::opt<bool> ForceBottomUp; 88243830Sdim 89234285Sdimclass AliasAnalysis; 90234285Sdimclass LiveIntervals; 91234285Sdimclass MachineDominatorTree; 92234285Sdimclass MachineLoopInfo; 93239462Sdimclass RegisterClassInfo; 94234285Sdimclass ScheduleDAGInstrs; 95249423Sdimclass SchedDFSResult; 96234285Sdim 97234285Sdim/// MachineSchedContext provides enough context from the MachineScheduler pass 98234285Sdim/// for the target to instantiate a scheduler. 99234285Sdimstruct MachineSchedContext { 100234285Sdim MachineFunction *MF; 101234285Sdim const MachineLoopInfo *MLI; 102234285Sdim const MachineDominatorTree *MDT; 103234285Sdim const TargetPassConfig *PassConfig; 104234285Sdim AliasAnalysis *AA; 105234285Sdim LiveIntervals *LIS; 106234285Sdim 107239462Sdim RegisterClassInfo *RegClassInfo; 108239462Sdim 109239462Sdim MachineSchedContext(); 110239462Sdim virtual ~MachineSchedContext(); 111234285Sdim}; 112234285Sdim 113234285Sdim/// MachineSchedRegistry provides a selection of available machine instruction 114234285Sdim/// schedulers. 115234285Sdimclass MachineSchedRegistry : public MachinePassRegistryNode { 116234285Sdimpublic: 117234285Sdim typedef ScheduleDAGInstrs *(*ScheduleDAGCtor)(MachineSchedContext *); 118234285Sdim 119234285Sdim // RegisterPassParser requires a (misnamed) FunctionPassCtor type. 120234285Sdim typedef ScheduleDAGCtor FunctionPassCtor; 121234285Sdim 122234285Sdim static MachinePassRegistry Registry; 123234285Sdim 124234285Sdim MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C) 125234285Sdim : MachinePassRegistryNode(N, D, (MachinePassCtor)C) { 126234285Sdim Registry.Add(this); 127234285Sdim } 128234285Sdim ~MachineSchedRegistry() { Registry.Remove(this); } 129234285Sdim 130234285Sdim // Accessors. 131234285Sdim // 132234285Sdim MachineSchedRegistry *getNext() const { 133234285Sdim return (MachineSchedRegistry *)MachinePassRegistryNode::getNext(); 134234285Sdim } 135234285Sdim static MachineSchedRegistry *getList() { 136234285Sdim return (MachineSchedRegistry *)Registry.getList(); 137234285Sdim } 138234285Sdim static void setListener(MachinePassRegistryListener *L) { 139234285Sdim Registry.setListener(L); 140234285Sdim } 141234285Sdim}; 142234285Sdim 143243830Sdimclass ScheduleDAGMI; 144243830Sdim 145263508Sdim/// Define a generic scheduling policy for targets that don't provide their own 146263508Sdim/// MachineSchedStrategy. This can be overriden for each scheduling region 147263508Sdim/// before building the DAG. 148263508Sdimstruct MachineSchedPolicy { 149263508Sdim // Allow the scheduler to disable register pressure tracking. 150263508Sdim bool ShouldTrackPressure; 151263508Sdim 152263508Sdim // Allow the scheduler to force top-down or bottom-up scheduling. If neither 153263508Sdim // is true, the scheduler runs in both directions and converges. 154263508Sdim bool OnlyTopDown; 155263508Sdim bool OnlyBottomUp; 156263508Sdim 157263508Sdim MachineSchedPolicy(): 158263508Sdim ShouldTrackPressure(false), OnlyTopDown(false), OnlyBottomUp(false) {} 159263508Sdim}; 160263508Sdim 161243830Sdim/// MachineSchedStrategy - Interface to the scheduling algorithm used by 162243830Sdim/// ScheduleDAGMI. 163263508Sdim/// 164263508Sdim/// Initialization sequence: 165263508Sdim/// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots 166243830Sdimclass MachineSchedStrategy { 167263508Sdim virtual void anchor(); 168243830Sdimpublic: 169243830Sdim virtual ~MachineSchedStrategy() {} 170243830Sdim 171263508Sdim /// Optionally override the per-region scheduling policy. 172263508Sdim virtual void initPolicy(MachineBasicBlock::iterator Begin, 173263508Sdim MachineBasicBlock::iterator End, 174263508Sdim unsigned NumRegionInstrs) {} 175263508Sdim 176263508Sdim /// Check if pressure tracking is needed before building the DAG and 177263508Sdim /// initializing this strategy. Called after initPolicy. 178263508Sdim virtual bool shouldTrackPressure() const { return true; } 179263508Sdim 180243830Sdim /// Initialize the strategy after building the DAG for a new region. 181243830Sdim virtual void initialize(ScheduleDAGMI *DAG) = 0; 182243830Sdim 183243830Sdim /// Notify this strategy that all roots have been released (including those 184243830Sdim /// that depend on EntrySU or ExitSU). 185243830Sdim virtual void registerRoots() {} 186243830Sdim 187243830Sdim /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to 188243830Sdim /// schedule the node at the top of the unscheduled region. Otherwise it will 189243830Sdim /// be scheduled at the bottom. 190243830Sdim virtual SUnit *pickNode(bool &IsTopNode) = 0; 191243830Sdim 192249423Sdim /// \brief Scheduler callback to notify that a new subtree is scheduled. 193249423Sdim virtual void scheduleTree(unsigned SubtreeID) {} 194249423Sdim 195243830Sdim /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an 196243830Sdim /// instruction and updated scheduled/remaining flags in the DAG nodes. 197243830Sdim virtual void schedNode(SUnit *SU, bool IsTopNode) = 0; 198243830Sdim 199243830Sdim /// When all predecessor dependencies have been resolved, free this node for 200243830Sdim /// top-down scheduling. 201243830Sdim virtual void releaseTopNode(SUnit *SU) = 0; 202243830Sdim /// When all successor dependencies have been resolved, free this node for 203243830Sdim /// bottom-up scheduling. 204243830Sdim virtual void releaseBottomNode(SUnit *SU) = 0; 205243830Sdim}; 206243830Sdim 207243830Sdim/// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience 208243830Sdim/// methods for pushing and removing nodes. ReadyQueue's are uniquely identified 209243830Sdim/// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in. 210243830Sdim/// 211243830Sdim/// This is a convenience class that may be used by implementations of 212243830Sdim/// MachineSchedStrategy. 213243830Sdimclass ReadyQueue { 214243830Sdim unsigned ID; 215243830Sdim std::string Name; 216243830Sdim std::vector<SUnit*> Queue; 217243830Sdim 218243830Sdimpublic: 219243830Sdim ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {} 220243830Sdim 221243830Sdim unsigned getID() const { return ID; } 222243830Sdim 223243830Sdim StringRef getName() const { return Name; } 224243830Sdim 225243830Sdim // SU is in this queue if it's NodeQueueID is a superset of this ID. 226243830Sdim bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); } 227243830Sdim 228243830Sdim bool empty() const { return Queue.empty(); } 229243830Sdim 230243830Sdim void clear() { Queue.clear(); } 231243830Sdim 232243830Sdim unsigned size() const { return Queue.size(); } 233243830Sdim 234243830Sdim typedef std::vector<SUnit*>::iterator iterator; 235243830Sdim 236243830Sdim iterator begin() { return Queue.begin(); } 237243830Sdim 238243830Sdim iterator end() { return Queue.end(); } 239243830Sdim 240249423Sdim ArrayRef<SUnit*> elements() { return Queue; } 241249423Sdim 242243830Sdim iterator find(SUnit *SU) { 243243830Sdim return std::find(Queue.begin(), Queue.end(), SU); 244243830Sdim } 245243830Sdim 246243830Sdim void push(SUnit *SU) { 247243830Sdim Queue.push_back(SU); 248243830Sdim SU->NodeQueueId |= ID; 249243830Sdim } 250243830Sdim 251243830Sdim iterator remove(iterator I) { 252243830Sdim (*I)->NodeQueueId &= ~ID; 253243830Sdim *I = Queue.back(); 254243830Sdim unsigned idx = I - Queue.begin(); 255243830Sdim Queue.pop_back(); 256243830Sdim return Queue.begin() + idx; 257243830Sdim } 258243830Sdim 259249423Sdim#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 260243830Sdim void dump(); 261243830Sdim#endif 262243830Sdim}; 263243830Sdim 264243830Sdim/// Mutate the DAG as a postpass after normal DAG building. 265243830Sdimclass ScheduleDAGMutation { 266263508Sdim virtual void anchor(); 267243830Sdimpublic: 268243830Sdim virtual ~ScheduleDAGMutation() {} 269243830Sdim 270243830Sdim virtual void apply(ScheduleDAGMI *DAG) = 0; 271243830Sdim}; 272243830Sdim 273243830Sdim/// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that schedules 274243830Sdim/// machine instructions while updating LiveIntervals and tracking regpressure. 275243830Sdimclass ScheduleDAGMI : public ScheduleDAGInstrs { 276243830Sdimprotected: 277243830Sdim AliasAnalysis *AA; 278243830Sdim RegisterClassInfo *RegClassInfo; 279243830Sdim MachineSchedStrategy *SchedImpl; 280243830Sdim 281249423Sdim /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees 282249423Sdim /// will be empty. 283249423Sdim SchedDFSResult *DFSResult; 284249423Sdim BitVector ScheduledTrees; 285249423Sdim 286249423Sdim /// Topo - A topological ordering for SUnits which permits fast IsReachable 287249423Sdim /// and similar queries. 288249423Sdim ScheduleDAGTopologicalSort Topo; 289249423Sdim 290243830Sdim /// Ordered list of DAG postprocessing steps. 291243830Sdim std::vector<ScheduleDAGMutation*> Mutations; 292243830Sdim 293243830Sdim MachineBasicBlock::iterator LiveRegionEnd; 294243830Sdim 295263508Sdim // Map each SU to its summary of pressure changes. This array is updated for 296263508Sdim // liveness during bottom-up scheduling. Top-down scheduling may proceed but 297263508Sdim // has no affect on the pressure diffs. 298263508Sdim PressureDiffs SUPressureDiffs; 299263508Sdim 300263508Sdim /// Register pressure in this region computed by initRegPressure. 301263508Sdim bool ShouldTrackPressure; 302243830Sdim IntervalPressure RegPressure; 303243830Sdim RegPressureTracker RPTracker; 304243830Sdim 305243830Sdim /// List of pressure sets that exceed the target's pressure limit before 306243830Sdim /// scheduling, listed in increasing set ID order. Each pressure set is paired 307243830Sdim /// with its max pressure in the currently scheduled regions. 308263508Sdim std::vector<PressureChange> RegionCriticalPSets; 309243830Sdim 310243830Sdim /// The top of the unscheduled zone. 311243830Sdim MachineBasicBlock::iterator CurrentTop; 312243830Sdim IntervalPressure TopPressure; 313243830Sdim RegPressureTracker TopRPTracker; 314243830Sdim 315243830Sdim /// The bottom of the unscheduled zone. 316243830Sdim MachineBasicBlock::iterator CurrentBottom; 317243830Sdim IntervalPressure BotPressure; 318243830Sdim RegPressureTracker BotRPTracker; 319243830Sdim 320249423Sdim /// Record the next node in a scheduled cluster. 321249423Sdim const SUnit *NextClusterPred; 322249423Sdim const SUnit *NextClusterSucc; 323249423Sdim 324243830Sdim#ifndef NDEBUG 325243830Sdim /// The number of instructions scheduled so far. Used to cut off the 326243830Sdim /// scheduler at the point determined by misched-cutoff. 327243830Sdim unsigned NumInstrsScheduled; 328243830Sdim#endif 329243830Sdim 330243830Sdimpublic: 331243830Sdim ScheduleDAGMI(MachineSchedContext *C, MachineSchedStrategy *S): 332243830Sdim ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, /*IsPostRA=*/false, C->LIS), 333249423Sdim AA(C->AA), RegClassInfo(C->RegClassInfo), SchedImpl(S), DFSResult(0), 334263508Sdim Topo(SUnits, &ExitSU), ShouldTrackPressure(false), 335263508Sdim RPTracker(RegPressure), CurrentTop(), TopRPTracker(TopPressure), 336263508Sdim CurrentBottom(), BotRPTracker(BotPressure), 337249423Sdim NextClusterPred(NULL), NextClusterSucc(NULL) { 338243830Sdim#ifndef NDEBUG 339243830Sdim NumInstrsScheduled = 0; 340243830Sdim#endif 341243830Sdim } 342243830Sdim 343249423Sdim virtual ~ScheduleDAGMI(); 344243830Sdim 345263508Sdim /// \brief Return true if register pressure tracking is enabled. 346263508Sdim bool isTrackingPressure() const { return ShouldTrackPressure; } 347263508Sdim 348243830Sdim /// Add a postprocessing step to the DAG builder. 349243830Sdim /// Mutations are applied in the order that they are added after normal DAG 350243830Sdim /// building and before MachineSchedStrategy initialization. 351249423Sdim /// 352249423Sdim /// ScheduleDAGMI takes ownership of the Mutation object. 353243830Sdim void addMutation(ScheduleDAGMutation *Mutation) { 354243830Sdim Mutations.push_back(Mutation); 355243830Sdim } 356243830Sdim 357251662Sdim /// \brief True if an edge can be added from PredSU to SuccSU without creating 358251662Sdim /// a cycle. 359251662Sdim bool canAddEdge(SUnit *SuccSU, SUnit *PredSU); 360251662Sdim 361249423Sdim /// \brief Add a DAG edge to the given SU with the given predecessor 362249423Sdim /// dependence data. 363249423Sdim /// 364249423Sdim /// \returns true if the edge may be added without creating a cycle OR if an 365249423Sdim /// equivalent edge already existed (false indicates failure). 366249423Sdim bool addEdge(SUnit *SuccSU, const SDep &PredDep); 367249423Sdim 368243830Sdim MachineBasicBlock::iterator top() const { return CurrentTop; } 369243830Sdim MachineBasicBlock::iterator bottom() const { return CurrentBottom; } 370243830Sdim 371243830Sdim /// Implement the ScheduleDAGInstrs interface for handling the next scheduling 372243830Sdim /// region. This covers all instructions in a block, while schedule() may only 373243830Sdim /// cover a subset. 374243830Sdim void enterRegion(MachineBasicBlock *bb, 375243830Sdim MachineBasicBlock::iterator begin, 376243830Sdim MachineBasicBlock::iterator end, 377263508Sdim unsigned regioninstrs) LLVM_OVERRIDE; 378243830Sdim 379243830Sdim /// Implement ScheduleDAGInstrs interface for scheduling a sequence of 380243830Sdim /// reorderable instructions. 381243830Sdim virtual void schedule(); 382243830Sdim 383251662Sdim /// Change the position of an instruction within the basic block and update 384251662Sdim /// live ranges and region boundary iterators. 385251662Sdim void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos); 386251662Sdim 387243830Sdim /// Get current register pressure for the top scheduled instructions. 388243830Sdim const IntervalPressure &getTopPressure() const { return TopPressure; } 389243830Sdim const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; } 390243830Sdim 391243830Sdim /// Get current register pressure for the bottom scheduled instructions. 392243830Sdim const IntervalPressure &getBotPressure() const { return BotPressure; } 393243830Sdim const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; } 394243830Sdim 395243830Sdim /// Get register pressure for the entire scheduling region before scheduling. 396243830Sdim const IntervalPressure &getRegPressure() const { return RegPressure; } 397243830Sdim 398263508Sdim const std::vector<PressureChange> &getRegionCriticalPSets() const { 399243830Sdim return RegionCriticalPSets; 400243830Sdim } 401243830Sdim 402263508Sdim PressureDiff &getPressureDiff(const SUnit *SU) { 403263508Sdim return SUPressureDiffs[SU->NodeNum]; 404263508Sdim } 405263508Sdim 406249423Sdim const SUnit *getNextClusterPred() const { return NextClusterPred; } 407249423Sdim 408249423Sdim const SUnit *getNextClusterSucc() const { return NextClusterSucc; } 409249423Sdim 410249423Sdim /// Compute a DFSResult after DAG building is complete, and before any 411249423Sdim /// queue comparisons. 412249423Sdim void computeDFSResult(); 413249423Sdim 414249423Sdim /// Return a non-null DFS result if the scheduling strategy initialized it. 415249423Sdim const SchedDFSResult *getDFSResult() const { return DFSResult; } 416249423Sdim 417249423Sdim BitVector &getScheduledTrees() { return ScheduledTrees; } 418249423Sdim 419263508Sdim /// Compute the cyclic critical path through the DAG. 420263508Sdim unsigned computeCyclicCriticalPath(); 421263508Sdim 422249423Sdim void viewGraph(const Twine &Name, const Twine &Title) LLVM_OVERRIDE; 423249423Sdim void viewGraph() LLVM_OVERRIDE; 424249423Sdim 425243830Sdimprotected: 426243830Sdim // Top-Level entry points for the schedule() driver... 427243830Sdim 428243830Sdim /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking 429243830Sdim /// enabled. This sets up three trackers. RPTracker will cover the entire DAG 430243830Sdim /// region, TopTracker and BottomTracker will be initialized to the top and 431243830Sdim /// bottom of the DAG region without covereing any unscheduled instruction. 432243830Sdim void buildDAGWithRegPressure(); 433243830Sdim 434243830Sdim /// Apply each ScheduleDAGMutation step in order. This allows different 435243830Sdim /// instances of ScheduleDAGMI to perform custom DAG postprocessing. 436243830Sdim void postprocessDAG(); 437243830Sdim 438249423Sdim /// Release ExitSU predecessors and setup scheduler queues. 439249423Sdim void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots); 440243830Sdim 441243830Sdim /// Move an instruction and update register pressure. 442243830Sdim void scheduleMI(SUnit *SU, bool IsTopNode); 443243830Sdim 444243830Sdim /// Update scheduler DAG and queues after scheduling an instruction. 445243830Sdim void updateQueues(SUnit *SU, bool IsTopNode); 446243830Sdim 447243830Sdim /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues. 448243830Sdim void placeDebugValues(); 449243830Sdim 450243830Sdim /// \brief dump the scheduled Sequence. 451243830Sdim void dumpSchedule() const; 452243830Sdim 453243830Sdim // Lesser helpers... 454243830Sdim 455243830Sdim void initRegPressure(); 456243830Sdim 457263508Sdim void updatePressureDiffs(ArrayRef<unsigned> LiveUses); 458243830Sdim 459263508Sdim void updateScheduledPressure(const SUnit *SU, 460263508Sdim const std::vector<unsigned> &NewMaxPressure); 461263508Sdim 462243830Sdim bool checkSchedLimit(); 463243830Sdim 464249423Sdim void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots, 465249423Sdim SmallVectorImpl<SUnit*> &BotRoots); 466243830Sdim 467243830Sdim void releaseSucc(SUnit *SU, SDep *SuccEdge); 468243830Sdim void releaseSuccessors(SUnit *SU); 469243830Sdim void releasePred(SUnit *SU, SDep *PredEdge); 470243830Sdim void releasePredecessors(SUnit *SU); 471243830Sdim}; 472243830Sdim 473234285Sdim} // namespace llvm 474234285Sdim 475234285Sdim#endif 476