MachineScheduler.h 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- MachineScheduler.h - MachineInstr Scheduling Pass --------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file provides an interface for customizing the standard MachineScheduler
  15. // pass. Note that the entire pass may be replaced as follows:
  16. //
  17. // <Target>TargetMachine::createPassConfig(PassManagerBase &PM) {
  18. // PM.substitutePass(&MachineSchedulerID, &CustomSchedulerPassID);
  19. // ...}
  20. //
  21. // The MachineScheduler pass is only responsible for choosing the regions to be
  22. // scheduled. Targets can override the DAG builder and scheduler without
  23. // replacing the pass as follows:
  24. //
  25. // ScheduleDAGInstrs *<Target>PassConfig::
  26. // createMachineScheduler(MachineSchedContext *C) {
  27. // return new CustomMachineScheduler(C);
  28. // }
  29. //
  30. // The default scheduler, ScheduleDAGMILive, builds the DAG and drives list
  31. // scheduling while updating the instruction stream, register pressure, and live
  32. // intervals. Most targets don't need to override the DAG builder and list
  33. // scheduler, but subtargets that require custom scheduling heuristics may
  34. // plugin an alternate MachineSchedStrategy. The strategy is responsible for
  35. // selecting the highest priority node from the list:
  36. //
  37. // ScheduleDAGInstrs *<Target>PassConfig::
  38. // createMachineScheduler(MachineSchedContext *C) {
  39. // return new ScheduleDAGMILive(C, CustomStrategy(C));
  40. // }
  41. //
  42. // The DAG builder can also be customized in a sense by adding DAG mutations
  43. // that will run after DAG building and before list scheduling. DAG mutations
  44. // can adjust dependencies based on target-specific knowledge or add weak edges
  45. // to aid heuristics:
  46. //
  47. // ScheduleDAGInstrs *<Target>PassConfig::
  48. // createMachineScheduler(MachineSchedContext *C) {
  49. // ScheduleDAGMI *DAG = createGenericSchedLive(C);
  50. // DAG->addMutation(new CustomDAGMutation(...));
  51. // return DAG;
  52. // }
  53. //
  54. // A target that supports alternative schedulers can use the
  55. // MachineSchedRegistry to allow command line selection. This can be done by
  56. // implementing the following boilerplate:
  57. //
  58. // static ScheduleDAGInstrs *createCustomMachineSched(MachineSchedContext *C) {
  59. // return new CustomMachineScheduler(C);
  60. // }
  61. // static MachineSchedRegistry
  62. // SchedCustomRegistry("custom", "Run my target's custom scheduler",
  63. // createCustomMachineSched);
  64. //
  65. //
  66. // Finally, subtargets that don't need to implement custom heuristics but would
  67. // like to configure the GenericScheduler's policy for a given scheduler region,
  68. // including scheduling direction and register pressure tracking policy, can do
  69. // this:
  70. //
  71. // void <SubTarget>Subtarget::
  72. // overrideSchedPolicy(MachineSchedPolicy &Policy,
  73. // unsigned NumRegionInstrs) const {
  74. // Policy.<Flag> = true;
  75. // }
  76. //
  77. //===----------------------------------------------------------------------===//
  78. #ifndef LLVM_CODEGEN_MACHINESCHEDULER_H
  79. #define LLVM_CODEGEN_MACHINESCHEDULER_H
  80. #include "llvm/ADT/APInt.h"
  81. #include "llvm/ADT/ArrayRef.h"
  82. #include "llvm/ADT/BitVector.h"
  83. #include "llvm/ADT/STLExtras.h"
  84. #include "llvm/ADT/SmallVector.h"
  85. #include "llvm/ADT/StringRef.h"
  86. #include "llvm/ADT/Twine.h"
  87. #include "llvm/CodeGen/MachineBasicBlock.h"
  88. #include "llvm/CodeGen/MachinePassRegistry.h"
  89. #include "llvm/CodeGen/RegisterPressure.h"
  90. #include "llvm/CodeGen/ScheduleDAG.h"
  91. #include "llvm/CodeGen/ScheduleDAGInstrs.h"
  92. #include "llvm/CodeGen/ScheduleDAGMutation.h"
  93. #include "llvm/CodeGen/TargetSchedule.h"
  94. #include "llvm/Support/CommandLine.h"
  95. #include "llvm/Support/ErrorHandling.h"
  96. #include <algorithm>
  97. #include <cassert>
  98. #include <memory>
  99. #include <string>
  100. #include <vector>
  101. namespace llvm {
  102. extern cl::opt<bool> ForceTopDown;
  103. extern cl::opt<bool> ForceBottomUp;
  104. extern cl::opt<bool> VerifyScheduling;
  105. #ifndef NDEBUG
  106. extern cl::opt<bool> ViewMISchedDAGs;
  107. #else
  108. extern const bool ViewMISchedDAGs;
  109. #endif
  110. class AAResults;
  111. class LiveIntervals;
  112. class MachineDominatorTree;
  113. class MachineFunction;
  114. class MachineInstr;
  115. class MachineLoopInfo;
  116. class RegisterClassInfo;
  117. class SchedDFSResult;
  118. class ScheduleHazardRecognizer;
  119. class TargetInstrInfo;
  120. class TargetPassConfig;
  121. class TargetRegisterInfo;
  122. /// MachineSchedContext provides enough context from the MachineScheduler pass
  123. /// for the target to instantiate a scheduler.
  124. struct MachineSchedContext {
  125. MachineFunction *MF = nullptr;
  126. const MachineLoopInfo *MLI = nullptr;
  127. const MachineDominatorTree *MDT = nullptr;
  128. const TargetPassConfig *PassConfig = nullptr;
  129. AAResults *AA = nullptr;
  130. LiveIntervals *LIS = nullptr;
  131. RegisterClassInfo *RegClassInfo;
  132. MachineSchedContext();
  133. virtual ~MachineSchedContext();
  134. };
  135. /// MachineSchedRegistry provides a selection of available machine instruction
  136. /// schedulers.
  137. class MachineSchedRegistry
  138. : public MachinePassRegistryNode<
  139. ScheduleDAGInstrs *(*)(MachineSchedContext *)> {
  140. public:
  141. using ScheduleDAGCtor = ScheduleDAGInstrs *(*)(MachineSchedContext *);
  142. // RegisterPassParser requires a (misnamed) FunctionPassCtor type.
  143. using FunctionPassCtor = ScheduleDAGCtor;
  144. static MachinePassRegistry<ScheduleDAGCtor> Registry;
  145. MachineSchedRegistry(const char *N, const char *D, ScheduleDAGCtor C)
  146. : MachinePassRegistryNode(N, D, C) {
  147. Registry.Add(this);
  148. }
  149. ~MachineSchedRegistry() { Registry.Remove(this); }
  150. // Accessors.
  151. //
  152. MachineSchedRegistry *getNext() const {
  153. return (MachineSchedRegistry *)MachinePassRegistryNode::getNext();
  154. }
  155. static MachineSchedRegistry *getList() {
  156. return (MachineSchedRegistry *)Registry.getList();
  157. }
  158. static void setListener(MachinePassRegistryListener<FunctionPassCtor> *L) {
  159. Registry.setListener(L);
  160. }
  161. };
  162. class ScheduleDAGMI;
  163. /// Define a generic scheduling policy for targets that don't provide their own
  164. /// MachineSchedStrategy. This can be overriden for each scheduling region
  165. /// before building the DAG.
  166. struct MachineSchedPolicy {
  167. // Allow the scheduler to disable register pressure tracking.
  168. bool ShouldTrackPressure = false;
  169. /// Track LaneMasks to allow reordering of independent subregister writes
  170. /// of the same vreg. \sa MachineSchedStrategy::shouldTrackLaneMasks()
  171. bool ShouldTrackLaneMasks = false;
  172. // Allow the scheduler to force top-down or bottom-up scheduling. If neither
  173. // is true, the scheduler runs in both directions and converges.
  174. bool OnlyTopDown = false;
  175. bool OnlyBottomUp = false;
  176. // Disable heuristic that tries to fetch nodes from long dependency chains
  177. // first.
  178. bool DisableLatencyHeuristic = false;
  179. // Compute DFSResult for use in scheduling heuristics.
  180. bool ComputeDFSResult = false;
  181. MachineSchedPolicy() = default;
  182. };
  183. /// MachineSchedStrategy - Interface to the scheduling algorithm used by
  184. /// ScheduleDAGMI.
  185. ///
  186. /// Initialization sequence:
  187. /// initPolicy -> shouldTrackPressure -> initialize(DAG) -> registerRoots
  188. class MachineSchedStrategy {
  189. virtual void anchor();
  190. public:
  191. virtual ~MachineSchedStrategy() = default;
  192. /// Optionally override the per-region scheduling policy.
  193. virtual void initPolicy(MachineBasicBlock::iterator Begin,
  194. MachineBasicBlock::iterator End,
  195. unsigned NumRegionInstrs) {}
  196. virtual void dumpPolicy() const {}
  197. /// Check if pressure tracking is needed before building the DAG and
  198. /// initializing this strategy. Called after initPolicy.
  199. virtual bool shouldTrackPressure() const { return true; }
  200. /// Returns true if lanemasks should be tracked. LaneMask tracking is
  201. /// necessary to reorder independent subregister defs for the same vreg.
  202. /// This has to be enabled in combination with shouldTrackPressure().
  203. virtual bool shouldTrackLaneMasks() const { return false; }
  204. // If this method returns true, handling of the scheduling regions
  205. // themselves (in case of a scheduling boundary in MBB) will be done
  206. // beginning with the topmost region of MBB.
  207. virtual bool doMBBSchedRegionsTopDown() const { return false; }
  208. /// Initialize the strategy after building the DAG for a new region.
  209. virtual void initialize(ScheduleDAGMI *DAG) = 0;
  210. /// Tell the strategy that MBB is about to be processed.
  211. virtual void enterMBB(MachineBasicBlock *MBB) {};
  212. /// Tell the strategy that current MBB is done.
  213. virtual void leaveMBB() {};
  214. /// Notify this strategy that all roots have been released (including those
  215. /// that depend on EntrySU or ExitSU).
  216. virtual void registerRoots() {}
  217. /// Pick the next node to schedule, or return NULL. Set IsTopNode to true to
  218. /// schedule the node at the top of the unscheduled region. Otherwise it will
  219. /// be scheduled at the bottom.
  220. virtual SUnit *pickNode(bool &IsTopNode) = 0;
  221. /// Scheduler callback to notify that a new subtree is scheduled.
  222. virtual void scheduleTree(unsigned SubtreeID) {}
  223. /// Notify MachineSchedStrategy that ScheduleDAGMI has scheduled an
  224. /// instruction and updated scheduled/remaining flags in the DAG nodes.
  225. virtual void schedNode(SUnit *SU, bool IsTopNode) = 0;
  226. /// When all predecessor dependencies have been resolved, free this node for
  227. /// top-down scheduling.
  228. virtual void releaseTopNode(SUnit *SU) = 0;
  229. /// When all successor dependencies have been resolved, free this node for
  230. /// bottom-up scheduling.
  231. virtual void releaseBottomNode(SUnit *SU) = 0;
  232. };
  233. /// ScheduleDAGMI is an implementation of ScheduleDAGInstrs that simply
  234. /// schedules machine instructions according to the given MachineSchedStrategy
  235. /// without much extra book-keeping. This is the common functionality between
  236. /// PreRA and PostRA MachineScheduler.
  237. class ScheduleDAGMI : public ScheduleDAGInstrs {
  238. protected:
  239. AAResults *AA;
  240. LiveIntervals *LIS;
  241. std::unique_ptr<MachineSchedStrategy> SchedImpl;
  242. /// Ordered list of DAG postprocessing steps.
  243. std::vector<std::unique_ptr<ScheduleDAGMutation>> Mutations;
  244. /// The top of the unscheduled zone.
  245. MachineBasicBlock::iterator CurrentTop;
  246. /// The bottom of the unscheduled zone.
  247. MachineBasicBlock::iterator CurrentBottom;
  248. /// Record the next node in a scheduled cluster.
  249. const SUnit *NextClusterPred = nullptr;
  250. const SUnit *NextClusterSucc = nullptr;
  251. #ifndef NDEBUG
  252. /// The number of instructions scheduled so far. Used to cut off the
  253. /// scheduler at the point determined by misched-cutoff.
  254. unsigned NumInstrsScheduled = 0;
  255. #endif
  256. public:
  257. ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr<MachineSchedStrategy> S,
  258. bool RemoveKillFlags)
  259. : ScheduleDAGInstrs(*C->MF, C->MLI, RemoveKillFlags), AA(C->AA),
  260. LIS(C->LIS), SchedImpl(std::move(S)) {}
  261. // Provide a vtable anchor
  262. ~ScheduleDAGMI() override;
  263. /// If this method returns true, handling of the scheduling regions
  264. /// themselves (in case of a scheduling boundary in MBB) will be done
  265. /// beginning with the topmost region of MBB.
  266. bool doMBBSchedRegionsTopDown() const override {
  267. return SchedImpl->doMBBSchedRegionsTopDown();
  268. }
  269. // Returns LiveIntervals instance for use in DAG mutators and such.
  270. LiveIntervals *getLIS() const { return LIS; }
  271. /// Return true if this DAG supports VReg liveness and RegPressure.
  272. virtual bool hasVRegLiveness() const { return false; }
  273. /// Add a postprocessing step to the DAG builder.
  274. /// Mutations are applied in the order that they are added after normal DAG
  275. /// building and before MachineSchedStrategy initialization.
  276. ///
  277. /// ScheduleDAGMI takes ownership of the Mutation object.
  278. void addMutation(std::unique_ptr<ScheduleDAGMutation> Mutation) {
  279. if (Mutation)
  280. Mutations.push_back(std::move(Mutation));
  281. }
  282. MachineBasicBlock::iterator top() const { return CurrentTop; }
  283. MachineBasicBlock::iterator bottom() const { return CurrentBottom; }
  284. /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
  285. /// region. This covers all instructions in a block, while schedule() may only
  286. /// cover a subset.
  287. void enterRegion(MachineBasicBlock *bb,
  288. MachineBasicBlock::iterator begin,
  289. MachineBasicBlock::iterator end,
  290. unsigned regioninstrs) override;
  291. /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
  292. /// reorderable instructions.
  293. void schedule() override;
  294. void startBlock(MachineBasicBlock *bb) override;
  295. void finishBlock() override;
  296. /// Change the position of an instruction within the basic block and update
  297. /// live ranges and region boundary iterators.
  298. void moveInstruction(MachineInstr *MI, MachineBasicBlock::iterator InsertPos);
  299. const SUnit *getNextClusterPred() const { return NextClusterPred; }
  300. const SUnit *getNextClusterSucc() const { return NextClusterSucc; }
  301. void viewGraph(const Twine &Name, const Twine &Title) override;
  302. void viewGraph() override;
  303. protected:
  304. // Top-Level entry points for the schedule() driver...
  305. /// Apply each ScheduleDAGMutation step in order. This allows different
  306. /// instances of ScheduleDAGMI to perform custom DAG postprocessing.
  307. void postprocessDAG();
  308. /// Release ExitSU predecessors and setup scheduler queues.
  309. void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
  310. /// Update scheduler DAG and queues after scheduling an instruction.
  311. void updateQueues(SUnit *SU, bool IsTopNode);
  312. /// Reinsert debug_values recorded in ScheduleDAGInstrs::DbgValues.
  313. void placeDebugValues();
  314. /// dump the scheduled Sequence.
  315. void dumpSchedule() const;
  316. // Lesser helpers...
  317. bool checkSchedLimit();
  318. void findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
  319. SmallVectorImpl<SUnit*> &BotRoots);
  320. void releaseSucc(SUnit *SU, SDep *SuccEdge);
  321. void releaseSuccessors(SUnit *SU);
  322. void releasePred(SUnit *SU, SDep *PredEdge);
  323. void releasePredecessors(SUnit *SU);
  324. };
  325. /// ScheduleDAGMILive is an implementation of ScheduleDAGInstrs that schedules
  326. /// machine instructions while updating LiveIntervals and tracking regpressure.
  327. class ScheduleDAGMILive : public ScheduleDAGMI {
  328. protected:
  329. RegisterClassInfo *RegClassInfo;
  330. /// Information about DAG subtrees. If DFSResult is NULL, then SchedulerTrees
  331. /// will be empty.
  332. SchedDFSResult *DFSResult = nullptr;
  333. BitVector ScheduledTrees;
  334. MachineBasicBlock::iterator LiveRegionEnd;
  335. /// Maps vregs to the SUnits of their uses in the current scheduling region.
  336. VReg2SUnitMultiMap VRegUses;
  337. // Map each SU to its summary of pressure changes. This array is updated for
  338. // liveness during bottom-up scheduling. Top-down scheduling may proceed but
  339. // has no affect on the pressure diffs.
  340. PressureDiffs SUPressureDiffs;
  341. /// Register pressure in this region computed by initRegPressure.
  342. bool ShouldTrackPressure = false;
  343. bool ShouldTrackLaneMasks = false;
  344. IntervalPressure RegPressure;
  345. RegPressureTracker RPTracker;
  346. /// List of pressure sets that exceed the target's pressure limit before
  347. /// scheduling, listed in increasing set ID order. Each pressure set is paired
  348. /// with its max pressure in the currently scheduled regions.
  349. std::vector<PressureChange> RegionCriticalPSets;
  350. /// The top of the unscheduled zone.
  351. IntervalPressure TopPressure;
  352. RegPressureTracker TopRPTracker;
  353. /// The bottom of the unscheduled zone.
  354. IntervalPressure BotPressure;
  355. RegPressureTracker BotRPTracker;
  356. public:
  357. ScheduleDAGMILive(MachineSchedContext *C,
  358. std::unique_ptr<MachineSchedStrategy> S)
  359. : ScheduleDAGMI(C, std::move(S), /*RemoveKillFlags=*/false),
  360. RegClassInfo(C->RegClassInfo), RPTracker(RegPressure),
  361. TopRPTracker(TopPressure), BotRPTracker(BotPressure) {}
  362. ~ScheduleDAGMILive() override;
  363. /// Return true if this DAG supports VReg liveness and RegPressure.
  364. bool hasVRegLiveness() const override { return true; }
  365. /// Return true if register pressure tracking is enabled.
  366. bool isTrackingPressure() const { return ShouldTrackPressure; }
  367. /// Get current register pressure for the top scheduled instructions.
  368. const IntervalPressure &getTopPressure() const { return TopPressure; }
  369. const RegPressureTracker &getTopRPTracker() const { return TopRPTracker; }
  370. /// Get current register pressure for the bottom scheduled instructions.
  371. const IntervalPressure &getBotPressure() const { return BotPressure; }
  372. const RegPressureTracker &getBotRPTracker() const { return BotRPTracker; }
  373. /// Get register pressure for the entire scheduling region before scheduling.
  374. const IntervalPressure &getRegPressure() const { return RegPressure; }
  375. const std::vector<PressureChange> &getRegionCriticalPSets() const {
  376. return RegionCriticalPSets;
  377. }
  378. PressureDiff &getPressureDiff(const SUnit *SU) {
  379. return SUPressureDiffs[SU->NodeNum];
  380. }
  381. const PressureDiff &getPressureDiff(const SUnit *SU) const {
  382. return SUPressureDiffs[SU->NodeNum];
  383. }
  384. /// Compute a DFSResult after DAG building is complete, and before any
  385. /// queue comparisons.
  386. void computeDFSResult();
  387. /// Return a non-null DFS result if the scheduling strategy initialized it.
  388. const SchedDFSResult *getDFSResult() const { return DFSResult; }
  389. BitVector &getScheduledTrees() { return ScheduledTrees; }
  390. /// Implement the ScheduleDAGInstrs interface for handling the next scheduling
  391. /// region. This covers all instructions in a block, while schedule() may only
  392. /// cover a subset.
  393. void enterRegion(MachineBasicBlock *bb,
  394. MachineBasicBlock::iterator begin,
  395. MachineBasicBlock::iterator end,
  396. unsigned regioninstrs) override;
  397. /// Implement ScheduleDAGInstrs interface for scheduling a sequence of
  398. /// reorderable instructions.
  399. void schedule() override;
  400. /// Compute the cyclic critical path through the DAG.
  401. unsigned computeCyclicCriticalPath();
  402. void dump() const override;
  403. protected:
  404. // Top-Level entry points for the schedule() driver...
  405. /// Call ScheduleDAGInstrs::buildSchedGraph with register pressure tracking
  406. /// enabled. This sets up three trackers. RPTracker will cover the entire DAG
  407. /// region, TopTracker and BottomTracker will be initialized to the top and
  408. /// bottom of the DAG region without covereing any unscheduled instruction.
  409. void buildDAGWithRegPressure();
  410. /// Release ExitSU predecessors and setup scheduler queues. Re-position
  411. /// the Top RP tracker in case the region beginning has changed.
  412. void initQueues(ArrayRef<SUnit*> TopRoots, ArrayRef<SUnit*> BotRoots);
  413. /// Move an instruction and update register pressure.
  414. void scheduleMI(SUnit *SU, bool IsTopNode);
  415. // Lesser helpers...
  416. void initRegPressure();
  417. void updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses);
  418. void updateScheduledPressure(const SUnit *SU,
  419. const std::vector<unsigned> &NewMaxPressure);
  420. void collectVRegUses(SUnit &SU);
  421. };
  422. //===----------------------------------------------------------------------===//
  423. ///
  424. /// Helpers for implementing custom MachineSchedStrategy classes. These take
  425. /// care of the book-keeping associated with list scheduling heuristics.
  426. ///
  427. //===----------------------------------------------------------------------===//
  428. /// ReadyQueue encapsulates vector of "ready" SUnits with basic convenience
  429. /// methods for pushing and removing nodes. ReadyQueue's are uniquely identified
  430. /// by an ID. SUnit::NodeQueueId is a mask of the ReadyQueues the SUnit is in.
  431. ///
  432. /// This is a convenience class that may be used by implementations of
  433. /// MachineSchedStrategy.
  434. class ReadyQueue {
  435. unsigned ID;
  436. std::string Name;
  437. std::vector<SUnit*> Queue;
  438. public:
  439. ReadyQueue(unsigned id, const Twine &name): ID(id), Name(name.str()) {}
  440. unsigned getID() const { return ID; }
  441. StringRef getName() const { return Name; }
  442. // SU is in this queue if it's NodeQueueID is a superset of this ID.
  443. bool isInQueue(SUnit *SU) const { return (SU->NodeQueueId & ID); }
  444. bool empty() const { return Queue.empty(); }
  445. void clear() { Queue.clear(); }
  446. unsigned size() const { return Queue.size(); }
  447. using iterator = std::vector<SUnit*>::iterator;
  448. iterator begin() { return Queue.begin(); }
  449. iterator end() { return Queue.end(); }
  450. ArrayRef<SUnit*> elements() { return Queue; }
  451. iterator find(SUnit *SU) { return llvm::find(Queue, SU); }
  452. void push(SUnit *SU) {
  453. Queue.push_back(SU);
  454. SU->NodeQueueId |= ID;
  455. }
  456. iterator remove(iterator I) {
  457. (*I)->NodeQueueId &= ~ID;
  458. *I = Queue.back();
  459. unsigned idx = I - Queue.begin();
  460. Queue.pop_back();
  461. return Queue.begin() + idx;
  462. }
  463. void dump() const;
  464. };
  465. /// Summarize the unscheduled region.
  466. struct SchedRemainder {
  467. // Critical path through the DAG in expected latency.
  468. unsigned CriticalPath;
  469. unsigned CyclicCritPath;
  470. // Scaled count of micro-ops left to schedule.
  471. unsigned RemIssueCount;
  472. bool IsAcyclicLatencyLimited;
  473. // Unscheduled resources
  474. SmallVector<unsigned, 16> RemainingCounts;
  475. SchedRemainder() { reset(); }
  476. void reset() {
  477. CriticalPath = 0;
  478. CyclicCritPath = 0;
  479. RemIssueCount = 0;
  480. IsAcyclicLatencyLimited = false;
  481. RemainingCounts.clear();
  482. }
  483. void init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel);
  484. };
  485. /// Each Scheduling boundary is associated with ready queues. It tracks the
  486. /// current cycle in the direction of movement, and maintains the state
  487. /// of "hazards" and other interlocks at the current cycle.
  488. class SchedBoundary {
  489. public:
  490. /// SUnit::NodeQueueId: 0 (none), 1 (top), 2 (bot), 3 (both)
  491. enum {
  492. TopQID = 1,
  493. BotQID = 2,
  494. LogMaxQID = 2
  495. };
  496. ScheduleDAGMI *DAG = nullptr;
  497. const TargetSchedModel *SchedModel = nullptr;
  498. SchedRemainder *Rem = nullptr;
  499. ReadyQueue Available;
  500. ReadyQueue Pending;
  501. ScheduleHazardRecognizer *HazardRec = nullptr;
  502. private:
  503. /// True if the pending Q should be checked/updated before scheduling another
  504. /// instruction.
  505. bool CheckPending;
  506. /// Number of cycles it takes to issue the instructions scheduled in this
  507. /// zone. It is defined as: scheduled-micro-ops / issue-width + stalls.
  508. /// See getStalls().
  509. unsigned CurrCycle;
  510. /// Micro-ops issued in the current cycle
  511. unsigned CurrMOps;
  512. /// MinReadyCycle - Cycle of the soonest available instruction.
  513. unsigned MinReadyCycle;
  514. // The expected latency of the critical path in this scheduled zone.
  515. unsigned ExpectedLatency;
  516. // The latency of dependence chains leading into this zone.
  517. // For each node scheduled bottom-up: DLat = max DLat, N.Depth.
  518. // For each cycle scheduled: DLat -= 1.
  519. unsigned DependentLatency;
  520. /// Count the scheduled (issued) micro-ops that can be retired by
  521. /// time=CurrCycle assuming the first scheduled instr is retired at time=0.
  522. unsigned RetiredMOps;
  523. // Count scheduled resources that have been executed. Resources are
  524. // considered executed if they become ready in the time that it takes to
  525. // saturate any resource including the one in question. Counts are scaled
  526. // for direct comparison with other resources. Counts can be compared with
  527. // MOps * getMicroOpFactor and Latency * getLatencyFactor.
  528. SmallVector<unsigned, 16> ExecutedResCounts;
  529. /// Cache the max count for a single resource.
  530. unsigned MaxExecutedResCount;
  531. // Cache the critical resources ID in this scheduled zone.
  532. unsigned ZoneCritResIdx;
  533. // Is the scheduled region resource limited vs. latency limited.
  534. bool IsResourceLimited;
  535. // Record the highest cycle at which each resource has been reserved by a
  536. // scheduled instruction.
  537. SmallVector<unsigned, 16> ReservedCycles;
  538. // For each PIdx, stores first index into ReservedCycles that corresponds to
  539. // it.
  540. SmallVector<unsigned, 16> ReservedCyclesIndex;
  541. // For each PIdx, stores the resource group IDs of its subunits
  542. SmallVector<APInt, 16> ResourceGroupSubUnitMasks;
  543. #ifndef NDEBUG
  544. // Remember the greatest possible stall as an upper bound on the number of
  545. // times we should retry the pending queue because of a hazard.
  546. unsigned MaxObservedStall;
  547. #endif
  548. public:
  549. /// Pending queues extend the ready queues with the same ID and the
  550. /// PendingFlag set.
  551. SchedBoundary(unsigned ID, const Twine &Name):
  552. Available(ID, Name+".A"), Pending(ID << LogMaxQID, Name+".P") {
  553. reset();
  554. }
  555. ~SchedBoundary();
  556. void reset();
  557. void init(ScheduleDAGMI *dag, const TargetSchedModel *smodel,
  558. SchedRemainder *rem);
  559. bool isTop() const {
  560. return Available.getID() == TopQID;
  561. }
  562. /// Number of cycles to issue the instructions scheduled in this zone.
  563. unsigned getCurrCycle() const { return CurrCycle; }
  564. /// Micro-ops issued in the current cycle
  565. unsigned getCurrMOps() const { return CurrMOps; }
  566. // The latency of dependence chains leading into this zone.
  567. unsigned getDependentLatency() const { return DependentLatency; }
  568. /// Get the number of latency cycles "covered" by the scheduled
  569. /// instructions. This is the larger of the critical path within the zone
  570. /// and the number of cycles required to issue the instructions.
  571. unsigned getScheduledLatency() const {
  572. return std::max(ExpectedLatency, CurrCycle);
  573. }
  574. unsigned getUnscheduledLatency(SUnit *SU) const {
  575. return isTop() ? SU->getHeight() : SU->getDepth();
  576. }
  577. unsigned getResourceCount(unsigned ResIdx) const {
  578. return ExecutedResCounts[ResIdx];
  579. }
  580. /// Get the scaled count of scheduled micro-ops and resources, including
  581. /// executed resources.
  582. unsigned getCriticalCount() const {
  583. if (!ZoneCritResIdx)
  584. return RetiredMOps * SchedModel->getMicroOpFactor();
  585. return getResourceCount(ZoneCritResIdx);
  586. }
  587. /// Get a scaled count for the minimum execution time of the scheduled
  588. /// micro-ops that are ready to execute by getExecutedCount. Notice the
  589. /// feedback loop.
  590. unsigned getExecutedCount() const {
  591. return std::max(CurrCycle * SchedModel->getLatencyFactor(),
  592. MaxExecutedResCount);
  593. }
  594. unsigned getZoneCritResIdx() const { return ZoneCritResIdx; }
  595. // Is the scheduled region resource limited vs. latency limited.
  596. bool isResourceLimited() const { return IsResourceLimited; }
  597. /// Get the difference between the given SUnit's ready time and the current
  598. /// cycle.
  599. unsigned getLatencyStallCycles(SUnit *SU);
  600. unsigned getNextResourceCycleByInstance(unsigned InstanceIndex,
  601. unsigned Cycles);
  602. std::pair<unsigned, unsigned> getNextResourceCycle(const MCSchedClassDesc *SC,
  603. unsigned PIdx,
  604. unsigned Cycles);
  605. bool isUnbufferedGroup(unsigned PIdx) const {
  606. return SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin &&
  607. !SchedModel->getProcResource(PIdx)->BufferSize;
  608. }
  609. bool checkHazard(SUnit *SU);
  610. unsigned findMaxLatency(ArrayRef<SUnit*> ReadySUs);
  611. unsigned getOtherResourceCount(unsigned &OtherCritIdx);
  612. /// Release SU to make it ready. If it's not in hazard, remove it from
  613. /// pending queue (if already in) and push into available queue.
  614. /// Otherwise, push the SU into pending queue.
  615. ///
  616. /// @param SU The unit to be released.
  617. /// @param ReadyCycle Until which cycle the unit is ready.
  618. /// @param InPQueue Whether SU is already in pending queue.
  619. /// @param Idx Position offset in pending queue (if in it).
  620. void releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
  621. unsigned Idx = 0);
  622. void bumpCycle(unsigned NextCycle);
  623. void incExecutedResources(unsigned PIdx, unsigned Count);
  624. unsigned countResource(const MCSchedClassDesc *SC, unsigned PIdx,
  625. unsigned Cycles, unsigned ReadyCycle);
  626. void bumpNode(SUnit *SU);
  627. void releasePending();
  628. void removeReady(SUnit *SU);
  629. /// Call this before applying any other heuristics to the Available queue.
  630. /// Updates the Available/Pending Q's if necessary and returns the single
  631. /// available instruction, or NULL if there are multiple candidates.
  632. SUnit *pickOnlyChoice();
  633. void dumpScheduledState() const;
  634. };
  635. /// Base class for GenericScheduler. This class maintains information about
  636. /// scheduling candidates based on TargetSchedModel making it easy to implement
  637. /// heuristics for either preRA or postRA scheduling.
  638. class GenericSchedulerBase : public MachineSchedStrategy {
  639. public:
  640. /// Represent the type of SchedCandidate found within a single queue.
  641. /// pickNodeBidirectional depends on these listed by decreasing priority.
  642. enum CandReason : uint8_t {
  643. NoCand, Only1, PhysReg, RegExcess, RegCritical, Stall, Cluster, Weak,
  644. RegMax, ResourceReduce, ResourceDemand, BotHeightReduce, BotPathReduce,
  645. TopDepthReduce, TopPathReduce, NextDefUse, NodeOrder};
  646. #ifndef NDEBUG
  647. static const char *getReasonStr(GenericSchedulerBase::CandReason Reason);
  648. #endif
  649. /// Policy for scheduling the next instruction in the candidate's zone.
  650. struct CandPolicy {
  651. bool ReduceLatency = false;
  652. unsigned ReduceResIdx = 0;
  653. unsigned DemandResIdx = 0;
  654. CandPolicy() = default;
  655. bool operator==(const CandPolicy &RHS) const {
  656. return ReduceLatency == RHS.ReduceLatency &&
  657. ReduceResIdx == RHS.ReduceResIdx &&
  658. DemandResIdx == RHS.DemandResIdx;
  659. }
  660. bool operator!=(const CandPolicy &RHS) const {
  661. return !(*this == RHS);
  662. }
  663. };
  664. /// Status of an instruction's critical resource consumption.
  665. struct SchedResourceDelta {
  666. // Count critical resources in the scheduled region required by SU.
  667. unsigned CritResources = 0;
  668. // Count critical resources from another region consumed by SU.
  669. unsigned DemandedResources = 0;
  670. SchedResourceDelta() = default;
  671. bool operator==(const SchedResourceDelta &RHS) const {
  672. return CritResources == RHS.CritResources
  673. && DemandedResources == RHS.DemandedResources;
  674. }
  675. bool operator!=(const SchedResourceDelta &RHS) const {
  676. return !operator==(RHS);
  677. }
  678. };
  679. /// Store the state used by GenericScheduler heuristics, required for the
  680. /// lifetime of one invocation of pickNode().
  681. struct SchedCandidate {
  682. CandPolicy Policy;
  683. // The best SUnit candidate.
  684. SUnit *SU;
  685. // The reason for this candidate.
  686. CandReason Reason;
  687. // Whether this candidate should be scheduled at top/bottom.
  688. bool AtTop;
  689. // Register pressure values for the best candidate.
  690. RegPressureDelta RPDelta;
  691. // Critical resource consumption of the best candidate.
  692. SchedResourceDelta ResDelta;
  693. SchedCandidate() { reset(CandPolicy()); }
  694. SchedCandidate(const CandPolicy &Policy) { reset(Policy); }
  695. void reset(const CandPolicy &NewPolicy) {
  696. Policy = NewPolicy;
  697. SU = nullptr;
  698. Reason = NoCand;
  699. AtTop = false;
  700. RPDelta = RegPressureDelta();
  701. ResDelta = SchedResourceDelta();
  702. }
  703. bool isValid() const { return SU; }
  704. // Copy the status of another candidate without changing policy.
  705. void setBest(SchedCandidate &Best) {
  706. assert(Best.Reason != NoCand && "uninitialized Sched candidate");
  707. SU = Best.SU;
  708. Reason = Best.Reason;
  709. AtTop = Best.AtTop;
  710. RPDelta = Best.RPDelta;
  711. ResDelta = Best.ResDelta;
  712. }
  713. void initResourceDelta(const ScheduleDAGMI *DAG,
  714. const TargetSchedModel *SchedModel);
  715. };
  716. protected:
  717. const MachineSchedContext *Context;
  718. const TargetSchedModel *SchedModel = nullptr;
  719. const TargetRegisterInfo *TRI = nullptr;
  720. SchedRemainder Rem;
  721. GenericSchedulerBase(const MachineSchedContext *C) : Context(C) {}
  722. void setPolicy(CandPolicy &Policy, bool IsPostRA, SchedBoundary &CurrZone,
  723. SchedBoundary *OtherZone);
  724. #ifndef NDEBUG
  725. void traceCandidate(const SchedCandidate &Cand);
  726. #endif
  727. private:
  728. bool shouldReduceLatency(const CandPolicy &Policy, SchedBoundary &CurrZone,
  729. bool ComputeRemLatency, unsigned &RemLatency) const;
  730. };
  731. // Utility functions used by heuristics in tryCandidate().
  732. bool tryLess(int TryVal, int CandVal,
  733. GenericSchedulerBase::SchedCandidate &TryCand,
  734. GenericSchedulerBase::SchedCandidate &Cand,
  735. GenericSchedulerBase::CandReason Reason);
  736. bool tryGreater(int TryVal, int CandVal,
  737. GenericSchedulerBase::SchedCandidate &TryCand,
  738. GenericSchedulerBase::SchedCandidate &Cand,
  739. GenericSchedulerBase::CandReason Reason);
  740. bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
  741. GenericSchedulerBase::SchedCandidate &Cand,
  742. SchedBoundary &Zone);
  743. bool tryPressure(const PressureChange &TryP,
  744. const PressureChange &CandP,
  745. GenericSchedulerBase::SchedCandidate &TryCand,
  746. GenericSchedulerBase::SchedCandidate &Cand,
  747. GenericSchedulerBase::CandReason Reason,
  748. const TargetRegisterInfo *TRI,
  749. const MachineFunction &MF);
  750. unsigned getWeakLeft(const SUnit *SU, bool isTop);
  751. int biasPhysReg(const SUnit *SU, bool isTop);
  752. /// GenericScheduler shrinks the unscheduled zone using heuristics to balance
  753. /// the schedule.
  754. class GenericScheduler : public GenericSchedulerBase {
  755. public:
  756. GenericScheduler(const MachineSchedContext *C):
  757. GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ"),
  758. Bot(SchedBoundary::BotQID, "BotQ") {}
  759. void initPolicy(MachineBasicBlock::iterator Begin,
  760. MachineBasicBlock::iterator End,
  761. unsigned NumRegionInstrs) override;
  762. void dumpPolicy() const override;
  763. bool shouldTrackPressure() const override {
  764. return RegionPolicy.ShouldTrackPressure;
  765. }
  766. bool shouldTrackLaneMasks() const override {
  767. return RegionPolicy.ShouldTrackLaneMasks;
  768. }
  769. void initialize(ScheduleDAGMI *dag) override;
  770. SUnit *pickNode(bool &IsTopNode) override;
  771. void schedNode(SUnit *SU, bool IsTopNode) override;
  772. void releaseTopNode(SUnit *SU) override {
  773. if (SU->isScheduled)
  774. return;
  775. Top.releaseNode(SU, SU->TopReadyCycle, false);
  776. TopCand.SU = nullptr;
  777. }
  778. void releaseBottomNode(SUnit *SU) override {
  779. if (SU->isScheduled)
  780. return;
  781. Bot.releaseNode(SU, SU->BotReadyCycle, false);
  782. BotCand.SU = nullptr;
  783. }
  784. void registerRoots() override;
  785. protected:
  786. ScheduleDAGMILive *DAG = nullptr;
  787. MachineSchedPolicy RegionPolicy;
  788. // State of the top and bottom scheduled instruction boundaries.
  789. SchedBoundary Top;
  790. SchedBoundary Bot;
  791. /// Candidate last picked from Top boundary.
  792. SchedCandidate TopCand;
  793. /// Candidate last picked from Bot boundary.
  794. SchedCandidate BotCand;
  795. void checkAcyclicLatency();
  796. void initCandidate(SchedCandidate &Cand, SUnit *SU, bool AtTop,
  797. const RegPressureTracker &RPTracker,
  798. RegPressureTracker &TempTracker);
  799. virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand,
  800. SchedBoundary *Zone) const;
  801. SUnit *pickNodeBidirectional(bool &IsTopNode);
  802. void pickNodeFromQueue(SchedBoundary &Zone,
  803. const CandPolicy &ZonePolicy,
  804. const RegPressureTracker &RPTracker,
  805. SchedCandidate &Candidate);
  806. void reschedulePhysReg(SUnit *SU, bool isTop);
  807. };
  808. /// PostGenericScheduler - Interface to the scheduling algorithm used by
  809. /// ScheduleDAGMI.
  810. ///
  811. /// Callbacks from ScheduleDAGMI:
  812. /// initPolicy -> initialize(DAG) -> registerRoots -> pickNode ...
  813. class PostGenericScheduler : public GenericSchedulerBase {
  814. protected:
  815. ScheduleDAGMI *DAG = nullptr;
  816. SchedBoundary Top;
  817. SmallVector<SUnit*, 8> BotRoots;
  818. public:
  819. PostGenericScheduler(const MachineSchedContext *C):
  820. GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {}
  821. ~PostGenericScheduler() override = default;
  822. void initPolicy(MachineBasicBlock::iterator Begin,
  823. MachineBasicBlock::iterator End,
  824. unsigned NumRegionInstrs) override {
  825. /* no configurable policy */
  826. }
  827. /// PostRA scheduling does not track pressure.
  828. bool shouldTrackPressure() const override { return false; }
  829. void initialize(ScheduleDAGMI *Dag) override;
  830. void registerRoots() override;
  831. SUnit *pickNode(bool &IsTopNode) override;
  832. void scheduleTree(unsigned SubtreeID) override {
  833. llvm_unreachable("PostRA scheduler does not support subtree analysis.");
  834. }
  835. void schedNode(SUnit *SU, bool IsTopNode) override;
  836. void releaseTopNode(SUnit *SU) override {
  837. if (SU->isScheduled)
  838. return;
  839. Top.releaseNode(SU, SU->TopReadyCycle, false);
  840. }
  841. // Only called for roots.
  842. void releaseBottomNode(SUnit *SU) override {
  843. BotRoots.push_back(SU);
  844. }
  845. protected:
  846. virtual bool tryCandidate(SchedCandidate &Cand, SchedCandidate &TryCand);
  847. void pickNodeFromQueue(SchedCandidate &Cand);
  848. };
  849. /// Create the standard converging machine scheduler. This will be used as the
  850. /// default scheduler if the target does not set a default.
  851. /// Adds default DAG mutations.
  852. ScheduleDAGMILive *createGenericSchedLive(MachineSchedContext *C);
  853. /// Create a generic scheduler with no vreg liveness or DAG mutation passes.
  854. ScheduleDAGMI *createGenericSchedPostRA(MachineSchedContext *C);
  855. std::unique_ptr<ScheduleDAGMutation>
  856. createLoadClusterDAGMutation(const TargetInstrInfo *TII,
  857. const TargetRegisterInfo *TRI);
  858. std::unique_ptr<ScheduleDAGMutation>
  859. createStoreClusterDAGMutation(const TargetInstrInfo *TII,
  860. const TargetRegisterInfo *TRI);
  861. std::unique_ptr<ScheduleDAGMutation>
  862. createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
  863. const TargetRegisterInfo *TRI);
  864. } // end namespace llvm
  865. #endif // LLVM_CODEGEN_MACHINESCHEDULER_H
  866. #ifdef __GNUC__
  867. #pragma GCC diagnostic pop
  868. #endif