xref: /openbsd-src/gnu/llvm/llvm/lib/CodeGen/MachineScheduler.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- MachineScheduler.cpp - Machine Instruction Scheduler ---------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // MachineScheduler schedules machine instructions after phi elimination. It
1009467b48Spatrick // preserves LiveIntervals so it can be invoked before register allocation.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "llvm/CodeGen/MachineScheduler.h"
1509467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1609467b48Spatrick #include "llvm/ADT/BitVector.h"
1709467b48Spatrick #include "llvm/ADT/DenseMap.h"
1809467b48Spatrick #include "llvm/ADT/PriorityQueue.h"
1909467b48Spatrick #include "llvm/ADT/STLExtras.h"
2009467b48Spatrick #include "llvm/ADT/SmallVector.h"
2173471bf0Spatrick #include "llvm/ADT/Statistic.h"
2209467b48Spatrick #include "llvm/ADT/iterator_range.h"
2309467b48Spatrick #include "llvm/Analysis/AliasAnalysis.h"
2409467b48Spatrick #include "llvm/CodeGen/LiveInterval.h"
2509467b48Spatrick #include "llvm/CodeGen/LiveIntervals.h"
2609467b48Spatrick #include "llvm/CodeGen/MachineBasicBlock.h"
2709467b48Spatrick #include "llvm/CodeGen/MachineDominators.h"
2809467b48Spatrick #include "llvm/CodeGen/MachineFunction.h"
2909467b48Spatrick #include "llvm/CodeGen/MachineFunctionPass.h"
3009467b48Spatrick #include "llvm/CodeGen/MachineInstr.h"
3109467b48Spatrick #include "llvm/CodeGen/MachineLoopInfo.h"
3209467b48Spatrick #include "llvm/CodeGen/MachineOperand.h"
3309467b48Spatrick #include "llvm/CodeGen/MachinePassRegistry.h"
3409467b48Spatrick #include "llvm/CodeGen/MachineRegisterInfo.h"
3509467b48Spatrick #include "llvm/CodeGen/RegisterClassInfo.h"
3609467b48Spatrick #include "llvm/CodeGen/RegisterPressure.h"
3709467b48Spatrick #include "llvm/CodeGen/ScheduleDAG.h"
3809467b48Spatrick #include "llvm/CodeGen/ScheduleDAGInstrs.h"
3909467b48Spatrick #include "llvm/CodeGen/ScheduleDAGMutation.h"
4009467b48Spatrick #include "llvm/CodeGen/ScheduleDFS.h"
4109467b48Spatrick #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
4209467b48Spatrick #include "llvm/CodeGen/SlotIndexes.h"
4309467b48Spatrick #include "llvm/CodeGen/TargetFrameLowering.h"
4409467b48Spatrick #include "llvm/CodeGen/TargetInstrInfo.h"
4509467b48Spatrick #include "llvm/CodeGen/TargetLowering.h"
4609467b48Spatrick #include "llvm/CodeGen/TargetPassConfig.h"
4709467b48Spatrick #include "llvm/CodeGen/TargetRegisterInfo.h"
4809467b48Spatrick #include "llvm/CodeGen/TargetSchedule.h"
4909467b48Spatrick #include "llvm/CodeGen/TargetSubtargetInfo.h"
5009467b48Spatrick #include "llvm/Config/llvm-config.h"
5109467b48Spatrick #include "llvm/InitializePasses.h"
5209467b48Spatrick #include "llvm/MC/LaneBitmask.h"
5309467b48Spatrick #include "llvm/Pass.h"
5409467b48Spatrick #include "llvm/Support/CommandLine.h"
5509467b48Spatrick #include "llvm/Support/Compiler.h"
5609467b48Spatrick #include "llvm/Support/Debug.h"
5709467b48Spatrick #include "llvm/Support/ErrorHandling.h"
5809467b48Spatrick #include "llvm/Support/GraphWriter.h"
5909467b48Spatrick #include "llvm/Support/MachineValueType.h"
6009467b48Spatrick #include "llvm/Support/raw_ostream.h"
6109467b48Spatrick #include <algorithm>
6209467b48Spatrick #include <cassert>
6309467b48Spatrick #include <cstdint>
6409467b48Spatrick #include <iterator>
6509467b48Spatrick #include <limits>
6609467b48Spatrick #include <memory>
6709467b48Spatrick #include <string>
6809467b48Spatrick #include <tuple>
6909467b48Spatrick #include <utility>
7009467b48Spatrick #include <vector>
7109467b48Spatrick 
7209467b48Spatrick using namespace llvm;
7309467b48Spatrick 
7409467b48Spatrick #define DEBUG_TYPE "machine-scheduler"
7509467b48Spatrick 
7673471bf0Spatrick STATISTIC(NumClustered, "Number of load/store pairs clustered");
7773471bf0Spatrick 
7809467b48Spatrick namespace llvm {
7909467b48Spatrick 
8009467b48Spatrick cl::opt<bool> ForceTopDown("misched-topdown", cl::Hidden,
8109467b48Spatrick                            cl::desc("Force top-down list scheduling"));
8209467b48Spatrick cl::opt<bool> ForceBottomUp("misched-bottomup", cl::Hidden,
8309467b48Spatrick                             cl::desc("Force bottom-up list scheduling"));
8409467b48Spatrick cl::opt<bool>
8509467b48Spatrick DumpCriticalPathLength("misched-dcpl", cl::Hidden,
8609467b48Spatrick                        cl::desc("Print critical path length to stdout"));
8709467b48Spatrick 
8809467b48Spatrick cl::opt<bool> VerifyScheduling(
8909467b48Spatrick     "verify-misched", cl::Hidden,
9009467b48Spatrick     cl::desc("Verify machine instrs before and after machine scheduling"));
9109467b48Spatrick 
92*d415bd75Srobert #ifndef NDEBUG
93*d415bd75Srobert cl::opt<bool> ViewMISchedDAGs(
94*d415bd75Srobert     "view-misched-dags", cl::Hidden,
95*d415bd75Srobert     cl::desc("Pop up a window to show MISched dags after they are processed"));
96*d415bd75Srobert cl::opt<bool> PrintDAGs("misched-print-dags", cl::Hidden,
97*d415bd75Srobert                         cl::desc("Print schedule DAGs"));
98*d415bd75Srobert cl::opt<bool> MISchedDumpReservedCycles(
99*d415bd75Srobert     "misched-dump-reserved-cycles", cl::Hidden, cl::init(false),
100*d415bd75Srobert     cl::desc("Dump resource usage at schedule boundary."));
101*d415bd75Srobert #else
102*d415bd75Srobert const bool ViewMISchedDAGs = false;
103*d415bd75Srobert const bool PrintDAGs = false;
104*d415bd75Srobert #ifdef LLVM_ENABLE_DUMP
105*d415bd75Srobert const bool MISchedDumpReservedCycles = false;
106*d415bd75Srobert #endif // LLVM_ENABLE_DUMP
107*d415bd75Srobert #endif // NDEBUG
108*d415bd75Srobert 
10909467b48Spatrick } // end namespace llvm
11009467b48Spatrick 
11109467b48Spatrick #ifndef NDEBUG
11209467b48Spatrick /// In some situations a few uninteresting nodes depend on nearly all other
11309467b48Spatrick /// nodes in the graph, provide a cutoff to hide them.
11409467b48Spatrick static cl::opt<unsigned> ViewMISchedCutoff("view-misched-cutoff", cl::Hidden,
11509467b48Spatrick   cl::desc("Hide nodes with more predecessor/successor than cutoff"));
11609467b48Spatrick 
11709467b48Spatrick static cl::opt<unsigned> MISchedCutoff("misched-cutoff", cl::Hidden,
11809467b48Spatrick   cl::desc("Stop scheduling after N instructions"), cl::init(~0U));
11909467b48Spatrick 
12009467b48Spatrick static cl::opt<std::string> SchedOnlyFunc("misched-only-func", cl::Hidden,
12109467b48Spatrick   cl::desc("Only schedule this function"));
12209467b48Spatrick static cl::opt<unsigned> SchedOnlyBlock("misched-only-block", cl::Hidden,
12309467b48Spatrick                                         cl::desc("Only schedule this MBB#"));
12409467b48Spatrick #endif // NDEBUG
12509467b48Spatrick 
12609467b48Spatrick /// Avoid quadratic complexity in unusually large basic blocks by limiting the
12709467b48Spatrick /// size of the ready lists.
12809467b48Spatrick static cl::opt<unsigned> ReadyListLimit("misched-limit", cl::Hidden,
12909467b48Spatrick   cl::desc("Limit ready list to N instructions"), cl::init(256));
13009467b48Spatrick 
13109467b48Spatrick static cl::opt<bool> EnableRegPressure("misched-regpressure", cl::Hidden,
13209467b48Spatrick   cl::desc("Enable register pressure scheduling."), cl::init(true));
13309467b48Spatrick 
13409467b48Spatrick static cl::opt<bool> EnableCyclicPath("misched-cyclicpath", cl::Hidden,
13509467b48Spatrick   cl::desc("Enable cyclic critical path analysis."), cl::init(true));
13609467b48Spatrick 
13709467b48Spatrick static cl::opt<bool> EnableMemOpCluster("misched-cluster", cl::Hidden,
13809467b48Spatrick                                         cl::desc("Enable memop clustering."),
13909467b48Spatrick                                         cl::init(true));
14073471bf0Spatrick static cl::opt<bool>
14173471bf0Spatrick     ForceFastCluster("force-fast-cluster", cl::Hidden,
14273471bf0Spatrick                      cl::desc("Switch to fast cluster algorithm with the lost "
14373471bf0Spatrick                               "of some fusion opportunities"),
14473471bf0Spatrick                      cl::init(false));
14573471bf0Spatrick static cl::opt<unsigned>
14673471bf0Spatrick     FastClusterThreshold("fast-cluster-threshold", cl::Hidden,
14773471bf0Spatrick                          cl::desc("The threshold for fast cluster"),
14873471bf0Spatrick                          cl::init(1000));
14909467b48Spatrick 
15009467b48Spatrick // DAG subtrees must have at least this many nodes.
15109467b48Spatrick static const unsigned MinSubtreeSize = 8;
15209467b48Spatrick 
15309467b48Spatrick // Pin the vtables to this file.
anchor()15409467b48Spatrick void MachineSchedStrategy::anchor() {}
15509467b48Spatrick 
anchor()15609467b48Spatrick void ScheduleDAGMutation::anchor() {}
15709467b48Spatrick 
15809467b48Spatrick //===----------------------------------------------------------------------===//
15909467b48Spatrick // Machine Instruction Scheduling Pass and Registry
16009467b48Spatrick //===----------------------------------------------------------------------===//
16109467b48Spatrick 
MachineSchedContext()16209467b48Spatrick MachineSchedContext::MachineSchedContext() {
16309467b48Spatrick   RegClassInfo = new RegisterClassInfo();
16409467b48Spatrick }
16509467b48Spatrick 
~MachineSchedContext()16609467b48Spatrick MachineSchedContext::~MachineSchedContext() {
16709467b48Spatrick   delete RegClassInfo;
16809467b48Spatrick }
16909467b48Spatrick 
17009467b48Spatrick namespace {
17109467b48Spatrick 
17209467b48Spatrick /// Base class for a machine scheduler class that can run at any point.
17309467b48Spatrick class MachineSchedulerBase : public MachineSchedContext,
17409467b48Spatrick                              public MachineFunctionPass {
17509467b48Spatrick public:
MachineSchedulerBase(char & ID)17609467b48Spatrick   MachineSchedulerBase(char &ID): MachineFunctionPass(ID) {}
17709467b48Spatrick 
17809467b48Spatrick   void print(raw_ostream &O, const Module* = nullptr) const override;
17909467b48Spatrick 
18009467b48Spatrick protected:
18109467b48Spatrick   void scheduleRegions(ScheduleDAGInstrs &Scheduler, bool FixKillFlags);
18209467b48Spatrick };
18309467b48Spatrick 
18409467b48Spatrick /// MachineScheduler runs after coalescing and before register allocation.
18509467b48Spatrick class MachineScheduler : public MachineSchedulerBase {
18609467b48Spatrick public:
18709467b48Spatrick   MachineScheduler();
18809467b48Spatrick 
18909467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override;
19009467b48Spatrick 
19109467b48Spatrick   bool runOnMachineFunction(MachineFunction&) override;
19209467b48Spatrick 
19309467b48Spatrick   static char ID; // Class identification, replacement for typeinfo
19409467b48Spatrick 
19509467b48Spatrick protected:
19609467b48Spatrick   ScheduleDAGInstrs *createMachineScheduler();
19709467b48Spatrick };
19809467b48Spatrick 
19909467b48Spatrick /// PostMachineScheduler runs after shortly before code emission.
20009467b48Spatrick class PostMachineScheduler : public MachineSchedulerBase {
20109467b48Spatrick public:
20209467b48Spatrick   PostMachineScheduler();
20309467b48Spatrick 
20409467b48Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override;
20509467b48Spatrick 
20609467b48Spatrick   bool runOnMachineFunction(MachineFunction&) override;
20709467b48Spatrick 
20809467b48Spatrick   static char ID; // Class identification, replacement for typeinfo
20909467b48Spatrick 
21009467b48Spatrick protected:
21109467b48Spatrick   ScheduleDAGInstrs *createPostMachineScheduler();
21209467b48Spatrick };
21309467b48Spatrick 
21409467b48Spatrick } // end anonymous namespace
21509467b48Spatrick 
21609467b48Spatrick char MachineScheduler::ID = 0;
21709467b48Spatrick 
21809467b48Spatrick char &llvm::MachineSchedulerID = MachineScheduler::ID;
21909467b48Spatrick 
22009467b48Spatrick INITIALIZE_PASS_BEGIN(MachineScheduler, DEBUG_TYPE,
22109467b48Spatrick                       "Machine Instruction Scheduler", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)22209467b48Spatrick INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
22309467b48Spatrick INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
22409467b48Spatrick INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
22509467b48Spatrick INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
22609467b48Spatrick INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
22709467b48Spatrick INITIALIZE_PASS_END(MachineScheduler, DEBUG_TYPE,
22809467b48Spatrick                     "Machine Instruction Scheduler", false, false)
22909467b48Spatrick 
23009467b48Spatrick MachineScheduler::MachineScheduler() : MachineSchedulerBase(ID) {
23109467b48Spatrick   initializeMachineSchedulerPass(*PassRegistry::getPassRegistry());
23209467b48Spatrick }
23309467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const23409467b48Spatrick void MachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const {
23509467b48Spatrick   AU.setPreservesCFG();
23609467b48Spatrick   AU.addRequired<MachineDominatorTree>();
23709467b48Spatrick   AU.addRequired<MachineLoopInfo>();
23809467b48Spatrick   AU.addRequired<AAResultsWrapperPass>();
23909467b48Spatrick   AU.addRequired<TargetPassConfig>();
24009467b48Spatrick   AU.addRequired<SlotIndexes>();
24109467b48Spatrick   AU.addPreserved<SlotIndexes>();
24209467b48Spatrick   AU.addRequired<LiveIntervals>();
24309467b48Spatrick   AU.addPreserved<LiveIntervals>();
24409467b48Spatrick   MachineFunctionPass::getAnalysisUsage(AU);
24509467b48Spatrick }
24609467b48Spatrick 
24709467b48Spatrick char PostMachineScheduler::ID = 0;
24809467b48Spatrick 
24909467b48Spatrick char &llvm::PostMachineSchedulerID = PostMachineScheduler::ID;
25009467b48Spatrick 
25173471bf0Spatrick INITIALIZE_PASS_BEGIN(PostMachineScheduler, "postmisched",
25273471bf0Spatrick                       "PostRA Machine Instruction Scheduler", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)25373471bf0Spatrick INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
25473471bf0Spatrick INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
25573471bf0Spatrick INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
25673471bf0Spatrick INITIALIZE_PASS_END(PostMachineScheduler, "postmisched",
25709467b48Spatrick                     "PostRA Machine Instruction Scheduler", false, false)
25809467b48Spatrick 
25909467b48Spatrick PostMachineScheduler::PostMachineScheduler() : MachineSchedulerBase(ID) {
26009467b48Spatrick   initializePostMachineSchedulerPass(*PassRegistry::getPassRegistry());
26109467b48Spatrick }
26209467b48Spatrick 
getAnalysisUsage(AnalysisUsage & AU) const26309467b48Spatrick void PostMachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const {
26409467b48Spatrick   AU.setPreservesCFG();
26509467b48Spatrick   AU.addRequired<MachineDominatorTree>();
26609467b48Spatrick   AU.addRequired<MachineLoopInfo>();
26709467b48Spatrick   AU.addRequired<AAResultsWrapperPass>();
26809467b48Spatrick   AU.addRequired<TargetPassConfig>();
26909467b48Spatrick   MachineFunctionPass::getAnalysisUsage(AU);
27009467b48Spatrick }
27109467b48Spatrick 
27209467b48Spatrick MachinePassRegistry<MachineSchedRegistry::ScheduleDAGCtor>
27309467b48Spatrick     MachineSchedRegistry::Registry;
27409467b48Spatrick 
27509467b48Spatrick /// A dummy default scheduler factory indicates whether the scheduler
27609467b48Spatrick /// is overridden on the command line.
useDefaultMachineSched(MachineSchedContext * C)27709467b48Spatrick static ScheduleDAGInstrs *useDefaultMachineSched(MachineSchedContext *C) {
27809467b48Spatrick   return nullptr;
27909467b48Spatrick }
28009467b48Spatrick 
28109467b48Spatrick /// MachineSchedOpt allows command line selection of the scheduler.
28209467b48Spatrick static cl::opt<MachineSchedRegistry::ScheduleDAGCtor, false,
28309467b48Spatrick                RegisterPassParser<MachineSchedRegistry>>
28409467b48Spatrick MachineSchedOpt("misched",
28509467b48Spatrick                 cl::init(&useDefaultMachineSched), cl::Hidden,
28609467b48Spatrick                 cl::desc("Machine instruction scheduler to use"));
28709467b48Spatrick 
28809467b48Spatrick static MachineSchedRegistry
28909467b48Spatrick DefaultSchedRegistry("default", "Use the target's default scheduler choice.",
29009467b48Spatrick                      useDefaultMachineSched);
29109467b48Spatrick 
29209467b48Spatrick static cl::opt<bool> EnableMachineSched(
29309467b48Spatrick     "enable-misched",
29409467b48Spatrick     cl::desc("Enable the machine instruction scheduling pass."), cl::init(true),
29509467b48Spatrick     cl::Hidden);
29609467b48Spatrick 
29709467b48Spatrick static cl::opt<bool> EnablePostRAMachineSched(
29809467b48Spatrick     "enable-post-misched",
29909467b48Spatrick     cl::desc("Enable the post-ra machine instruction scheduling pass."),
30009467b48Spatrick     cl::init(true), cl::Hidden);
30109467b48Spatrick 
30209467b48Spatrick /// Decrement this iterator until reaching the top or a non-debug instr.
30309467b48Spatrick static MachineBasicBlock::const_iterator
priorNonDebug(MachineBasicBlock::const_iterator I,MachineBasicBlock::const_iterator Beg)30409467b48Spatrick priorNonDebug(MachineBasicBlock::const_iterator I,
30509467b48Spatrick               MachineBasicBlock::const_iterator Beg) {
30609467b48Spatrick   assert(I != Beg && "reached the top of the region, cannot decrement");
30709467b48Spatrick   while (--I != Beg) {
30873471bf0Spatrick     if (!I->isDebugOrPseudoInstr())
30909467b48Spatrick       break;
31009467b48Spatrick   }
31109467b48Spatrick   return I;
31209467b48Spatrick }
31309467b48Spatrick 
31409467b48Spatrick /// Non-const version.
31509467b48Spatrick static MachineBasicBlock::iterator
priorNonDebug(MachineBasicBlock::iterator I,MachineBasicBlock::const_iterator Beg)31609467b48Spatrick priorNonDebug(MachineBasicBlock::iterator I,
31709467b48Spatrick               MachineBasicBlock::const_iterator Beg) {
31809467b48Spatrick   return priorNonDebug(MachineBasicBlock::const_iterator(I), Beg)
31909467b48Spatrick       .getNonConstIterator();
32009467b48Spatrick }
32109467b48Spatrick 
32209467b48Spatrick /// If this iterator is a debug value, increment until reaching the End or a
32309467b48Spatrick /// non-debug instruction.
32409467b48Spatrick static MachineBasicBlock::const_iterator
nextIfDebug(MachineBasicBlock::const_iterator I,MachineBasicBlock::const_iterator End)32509467b48Spatrick nextIfDebug(MachineBasicBlock::const_iterator I,
32609467b48Spatrick             MachineBasicBlock::const_iterator End) {
32709467b48Spatrick   for(; I != End; ++I) {
32873471bf0Spatrick     if (!I->isDebugOrPseudoInstr())
32909467b48Spatrick       break;
33009467b48Spatrick   }
33109467b48Spatrick   return I;
33209467b48Spatrick }
33309467b48Spatrick 
33409467b48Spatrick /// Non-const version.
33509467b48Spatrick static MachineBasicBlock::iterator
nextIfDebug(MachineBasicBlock::iterator I,MachineBasicBlock::const_iterator End)33609467b48Spatrick nextIfDebug(MachineBasicBlock::iterator I,
33709467b48Spatrick             MachineBasicBlock::const_iterator End) {
33809467b48Spatrick   return nextIfDebug(MachineBasicBlock::const_iterator(I), End)
33909467b48Spatrick       .getNonConstIterator();
34009467b48Spatrick }
34109467b48Spatrick 
34209467b48Spatrick /// Instantiate a ScheduleDAGInstrs that will be owned by the caller.
createMachineScheduler()34309467b48Spatrick ScheduleDAGInstrs *MachineScheduler::createMachineScheduler() {
34409467b48Spatrick   // Select the scheduler, or set the default.
34509467b48Spatrick   MachineSchedRegistry::ScheduleDAGCtor Ctor = MachineSchedOpt;
34609467b48Spatrick   if (Ctor != useDefaultMachineSched)
34709467b48Spatrick     return Ctor(this);
34809467b48Spatrick 
34909467b48Spatrick   // Get the default scheduler set by the target for this function.
35009467b48Spatrick   ScheduleDAGInstrs *Scheduler = PassConfig->createMachineScheduler(this);
35109467b48Spatrick   if (Scheduler)
35209467b48Spatrick     return Scheduler;
35309467b48Spatrick 
35409467b48Spatrick   // Default to GenericScheduler.
35509467b48Spatrick   return createGenericSchedLive(this);
35609467b48Spatrick }
35709467b48Spatrick 
35809467b48Spatrick /// Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by
35909467b48Spatrick /// the caller. We don't have a command line option to override the postRA
36009467b48Spatrick /// scheduler. The Target must configure it.
createPostMachineScheduler()36109467b48Spatrick ScheduleDAGInstrs *PostMachineScheduler::createPostMachineScheduler() {
36209467b48Spatrick   // Get the postRA scheduler set by the target for this function.
36309467b48Spatrick   ScheduleDAGInstrs *Scheduler = PassConfig->createPostMachineScheduler(this);
36409467b48Spatrick   if (Scheduler)
36509467b48Spatrick     return Scheduler;
36609467b48Spatrick 
36709467b48Spatrick   // Default to GenericScheduler.
36809467b48Spatrick   return createGenericSchedPostRA(this);
36909467b48Spatrick }
37009467b48Spatrick 
37109467b48Spatrick /// Top-level MachineScheduler pass driver.
37209467b48Spatrick ///
37309467b48Spatrick /// Visit blocks in function order. Divide each block into scheduling regions
37409467b48Spatrick /// and visit them bottom-up. Visiting regions bottom-up is not required, but is
37509467b48Spatrick /// consistent with the DAG builder, which traverses the interior of the
37609467b48Spatrick /// scheduling regions bottom-up.
37709467b48Spatrick ///
37809467b48Spatrick /// This design avoids exposing scheduling boundaries to the DAG builder,
37909467b48Spatrick /// simplifying the DAG builder's support for "special" target instructions.
38009467b48Spatrick /// At the same time the design allows target schedulers to operate across
38109467b48Spatrick /// scheduling boundaries, for example to bundle the boundary instructions
38209467b48Spatrick /// without reordering them. This creates complexity, because the target
38309467b48Spatrick /// scheduler must update the RegionBegin and RegionEnd positions cached by
38409467b48Spatrick /// ScheduleDAGInstrs whenever adding or removing instructions. A much simpler
38509467b48Spatrick /// design would be to split blocks at scheduling boundaries, but LLVM has a
38609467b48Spatrick /// general bias against block splitting purely for implementation simplicity.
runOnMachineFunction(MachineFunction & mf)38709467b48Spatrick bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
38809467b48Spatrick   if (skipFunction(mf.getFunction()))
38909467b48Spatrick     return false;
39009467b48Spatrick 
39109467b48Spatrick   if (EnableMachineSched.getNumOccurrences()) {
39209467b48Spatrick     if (!EnableMachineSched)
39309467b48Spatrick       return false;
39409467b48Spatrick   } else if (!mf.getSubtarget().enableMachineScheduler())
39509467b48Spatrick     return false;
39609467b48Spatrick 
39709467b48Spatrick   LLVM_DEBUG(dbgs() << "Before MISched:\n"; mf.print(dbgs()));
39809467b48Spatrick 
39909467b48Spatrick   // Initialize the context of the pass.
40009467b48Spatrick   MF = &mf;
40109467b48Spatrick   MLI = &getAnalysis<MachineLoopInfo>();
40209467b48Spatrick   MDT = &getAnalysis<MachineDominatorTree>();
40309467b48Spatrick   PassConfig = &getAnalysis<TargetPassConfig>();
40409467b48Spatrick   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
40509467b48Spatrick 
40609467b48Spatrick   LIS = &getAnalysis<LiveIntervals>();
40709467b48Spatrick 
40809467b48Spatrick   if (VerifyScheduling) {
40909467b48Spatrick     LLVM_DEBUG(LIS->dump());
41009467b48Spatrick     MF->verify(this, "Before machine scheduling.");
41109467b48Spatrick   }
41209467b48Spatrick   RegClassInfo->runOnMachineFunction(*MF);
41309467b48Spatrick 
41409467b48Spatrick   // Instantiate the selected scheduler for this target, function, and
41509467b48Spatrick   // optimization level.
41609467b48Spatrick   std::unique_ptr<ScheduleDAGInstrs> Scheduler(createMachineScheduler());
41709467b48Spatrick   scheduleRegions(*Scheduler, false);
41809467b48Spatrick 
41909467b48Spatrick   LLVM_DEBUG(LIS->dump());
42009467b48Spatrick   if (VerifyScheduling)
42109467b48Spatrick     MF->verify(this, "After machine scheduling.");
42209467b48Spatrick   return true;
42309467b48Spatrick }
42409467b48Spatrick 
runOnMachineFunction(MachineFunction & mf)42509467b48Spatrick bool PostMachineScheduler::runOnMachineFunction(MachineFunction &mf) {
42609467b48Spatrick   if (skipFunction(mf.getFunction()))
42709467b48Spatrick     return false;
42809467b48Spatrick 
42909467b48Spatrick   if (EnablePostRAMachineSched.getNumOccurrences()) {
43009467b48Spatrick     if (!EnablePostRAMachineSched)
43109467b48Spatrick       return false;
43209467b48Spatrick   } else if (!mf.getSubtarget().enablePostRAMachineScheduler()) {
43309467b48Spatrick     LLVM_DEBUG(dbgs() << "Subtarget disables post-MI-sched.\n");
43409467b48Spatrick     return false;
43509467b48Spatrick   }
43609467b48Spatrick   LLVM_DEBUG(dbgs() << "Before post-MI-sched:\n"; mf.print(dbgs()));
43709467b48Spatrick 
43809467b48Spatrick   // Initialize the context of the pass.
43909467b48Spatrick   MF = &mf;
44009467b48Spatrick   MLI = &getAnalysis<MachineLoopInfo>();
44109467b48Spatrick   PassConfig = &getAnalysis<TargetPassConfig>();
44209467b48Spatrick   AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
44309467b48Spatrick 
44409467b48Spatrick   if (VerifyScheduling)
44509467b48Spatrick     MF->verify(this, "Before post machine scheduling.");
44609467b48Spatrick 
44709467b48Spatrick   // Instantiate the selected scheduler for this target, function, and
44809467b48Spatrick   // optimization level.
44909467b48Spatrick   std::unique_ptr<ScheduleDAGInstrs> Scheduler(createPostMachineScheduler());
45009467b48Spatrick   scheduleRegions(*Scheduler, true);
45109467b48Spatrick 
45209467b48Spatrick   if (VerifyScheduling)
45309467b48Spatrick     MF->verify(this, "After post machine scheduling.");
45409467b48Spatrick   return true;
45509467b48Spatrick }
45609467b48Spatrick 
45709467b48Spatrick /// Return true of the given instruction should not be included in a scheduling
45809467b48Spatrick /// region.
45909467b48Spatrick ///
46009467b48Spatrick /// MachineScheduler does not currently support scheduling across calls. To
46109467b48Spatrick /// handle calls, the DAG builder needs to be modified to create register
46209467b48Spatrick /// anti/output dependencies on the registers clobbered by the call's regmask
46309467b48Spatrick /// operand. In PreRA scheduling, the stack pointer adjustment already prevents
46409467b48Spatrick /// scheduling across calls. In PostRA scheduling, we need the isCall to enforce
46509467b48Spatrick /// the boundary, but there would be no benefit to postRA scheduling across
46609467b48Spatrick /// calls this late anyway.
isSchedBoundary(MachineBasicBlock::iterator MI,MachineBasicBlock * MBB,MachineFunction * MF,const TargetInstrInfo * TII)46709467b48Spatrick static bool isSchedBoundary(MachineBasicBlock::iterator MI,
46809467b48Spatrick                             MachineBasicBlock *MBB,
46909467b48Spatrick                             MachineFunction *MF,
47009467b48Spatrick                             const TargetInstrInfo *TII) {
47109467b48Spatrick   return MI->isCall() || TII->isSchedulingBoundary(*MI, MBB, *MF);
47209467b48Spatrick }
47309467b48Spatrick 
47409467b48Spatrick /// A region of an MBB for scheduling.
47509467b48Spatrick namespace {
47609467b48Spatrick struct SchedRegion {
47709467b48Spatrick   /// RegionBegin is the first instruction in the scheduling region, and
47809467b48Spatrick   /// RegionEnd is either MBB->end() or the scheduling boundary after the
47909467b48Spatrick   /// last instruction in the scheduling region. These iterators cannot refer
48009467b48Spatrick   /// to instructions outside of the identified scheduling region because
48109467b48Spatrick   /// those may be reordered before scheduling this region.
48209467b48Spatrick   MachineBasicBlock::iterator RegionBegin;
48309467b48Spatrick   MachineBasicBlock::iterator RegionEnd;
48409467b48Spatrick   unsigned NumRegionInstrs;
48509467b48Spatrick 
SchedRegion__anonf2be975f0211::SchedRegion48609467b48Spatrick   SchedRegion(MachineBasicBlock::iterator B, MachineBasicBlock::iterator E,
48709467b48Spatrick               unsigned N) :
48809467b48Spatrick     RegionBegin(B), RegionEnd(E), NumRegionInstrs(N) {}
48909467b48Spatrick };
49009467b48Spatrick } // end anonymous namespace
49109467b48Spatrick 
49209467b48Spatrick using MBBRegionsVector = SmallVector<SchedRegion, 16>;
49309467b48Spatrick 
49409467b48Spatrick static void
getSchedRegions(MachineBasicBlock * MBB,MBBRegionsVector & Regions,bool RegionsTopDown)49509467b48Spatrick getSchedRegions(MachineBasicBlock *MBB,
49609467b48Spatrick                 MBBRegionsVector &Regions,
49709467b48Spatrick                 bool RegionsTopDown) {
49809467b48Spatrick   MachineFunction *MF = MBB->getParent();
49909467b48Spatrick   const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
50009467b48Spatrick 
50109467b48Spatrick   MachineBasicBlock::iterator I = nullptr;
50209467b48Spatrick   for(MachineBasicBlock::iterator RegionEnd = MBB->end();
50309467b48Spatrick       RegionEnd != MBB->begin(); RegionEnd = I) {
50409467b48Spatrick 
50509467b48Spatrick     // Avoid decrementing RegionEnd for blocks with no terminator.
50609467b48Spatrick     if (RegionEnd != MBB->end() ||
50709467b48Spatrick         isSchedBoundary(&*std::prev(RegionEnd), &*MBB, MF, TII)) {
50809467b48Spatrick       --RegionEnd;
50909467b48Spatrick     }
51009467b48Spatrick 
51109467b48Spatrick     // The next region starts above the previous region. Look backward in the
51209467b48Spatrick     // instruction stream until we find the nearest boundary.
51309467b48Spatrick     unsigned NumRegionInstrs = 0;
51409467b48Spatrick     I = RegionEnd;
51509467b48Spatrick     for (;I != MBB->begin(); --I) {
51609467b48Spatrick       MachineInstr &MI = *std::prev(I);
51709467b48Spatrick       if (isSchedBoundary(&MI, &*MBB, MF, TII))
51809467b48Spatrick         break;
51973471bf0Spatrick       if (!MI.isDebugOrPseudoInstr()) {
52009467b48Spatrick         // MBB::size() uses instr_iterator to count. Here we need a bundle to
52109467b48Spatrick         // count as a single instruction.
52209467b48Spatrick         ++NumRegionInstrs;
52309467b48Spatrick       }
52409467b48Spatrick     }
52509467b48Spatrick 
52609467b48Spatrick     // It's possible we found a scheduling region that only has debug
52709467b48Spatrick     // instructions. Don't bother scheduling these.
52809467b48Spatrick     if (NumRegionInstrs != 0)
52909467b48Spatrick       Regions.push_back(SchedRegion(I, RegionEnd, NumRegionInstrs));
53009467b48Spatrick   }
53109467b48Spatrick 
53209467b48Spatrick   if (RegionsTopDown)
53309467b48Spatrick     std::reverse(Regions.begin(), Regions.end());
53409467b48Spatrick }
53509467b48Spatrick 
53609467b48Spatrick /// Main driver for both MachineScheduler and PostMachineScheduler.
scheduleRegions(ScheduleDAGInstrs & Scheduler,bool FixKillFlags)53709467b48Spatrick void MachineSchedulerBase::scheduleRegions(ScheduleDAGInstrs &Scheduler,
53809467b48Spatrick                                            bool FixKillFlags) {
53909467b48Spatrick   // Visit all machine basic blocks.
54009467b48Spatrick   //
54109467b48Spatrick   // TODO: Visit blocks in global postorder or postorder within the bottom-up
54209467b48Spatrick   // loop tree. Then we can optionally compute global RegPressure.
54309467b48Spatrick   for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end();
54409467b48Spatrick        MBB != MBBEnd; ++MBB) {
54509467b48Spatrick 
54609467b48Spatrick     Scheduler.startBlock(&*MBB);
54709467b48Spatrick 
54809467b48Spatrick #ifndef NDEBUG
54909467b48Spatrick     if (SchedOnlyFunc.getNumOccurrences() && SchedOnlyFunc != MF->getName())
55009467b48Spatrick       continue;
55109467b48Spatrick     if (SchedOnlyBlock.getNumOccurrences()
55209467b48Spatrick         && (int)SchedOnlyBlock != MBB->getNumber())
55309467b48Spatrick       continue;
55409467b48Spatrick #endif
55509467b48Spatrick 
55609467b48Spatrick     // Break the block into scheduling regions [I, RegionEnd). RegionEnd
55709467b48Spatrick     // points to the scheduling boundary at the bottom of the region. The DAG
55809467b48Spatrick     // does not include RegionEnd, but the region does (i.e. the next
55909467b48Spatrick     // RegionEnd is above the previous RegionBegin). If the current block has
56009467b48Spatrick     // no terminator then RegionEnd == MBB->end() for the bottom region.
56109467b48Spatrick     //
56209467b48Spatrick     // All the regions of MBB are first found and stored in MBBRegions, which
56309467b48Spatrick     // will be processed (MBB) top-down if initialized with true.
56409467b48Spatrick     //
56509467b48Spatrick     // The Scheduler may insert instructions during either schedule() or
56609467b48Spatrick     // exitRegion(), even for empty regions. So the local iterators 'I' and
56709467b48Spatrick     // 'RegionEnd' are invalid across these calls. Instructions must not be
56809467b48Spatrick     // added to other regions than the current one without updating MBBRegions.
56909467b48Spatrick 
57009467b48Spatrick     MBBRegionsVector MBBRegions;
57109467b48Spatrick     getSchedRegions(&*MBB, MBBRegions, Scheduler.doMBBSchedRegionsTopDown());
572*d415bd75Srobert     for (const SchedRegion &R : MBBRegions) {
573*d415bd75Srobert       MachineBasicBlock::iterator I = R.RegionBegin;
574*d415bd75Srobert       MachineBasicBlock::iterator RegionEnd = R.RegionEnd;
575*d415bd75Srobert       unsigned NumRegionInstrs = R.NumRegionInstrs;
57609467b48Spatrick 
57709467b48Spatrick       // Notify the scheduler of the region, even if we may skip scheduling
57809467b48Spatrick       // it. Perhaps it still needs to be bundled.
57909467b48Spatrick       Scheduler.enterRegion(&*MBB, I, RegionEnd, NumRegionInstrs);
58009467b48Spatrick 
58109467b48Spatrick       // Skip empty scheduling regions (0 or 1 schedulable instructions).
58209467b48Spatrick       if (I == RegionEnd || I == std::prev(RegionEnd)) {
58309467b48Spatrick         // Close the current region. Bundle the terminator if needed.
58409467b48Spatrick         // This invalidates 'RegionEnd' and 'I'.
58509467b48Spatrick         Scheduler.exitRegion();
58609467b48Spatrick         continue;
58709467b48Spatrick       }
58809467b48Spatrick       LLVM_DEBUG(dbgs() << "********** MI Scheduling **********\n");
58909467b48Spatrick       LLVM_DEBUG(dbgs() << MF->getName() << ":" << printMBBReference(*MBB)
59009467b48Spatrick                         << " " << MBB->getName() << "\n  From: " << *I
59109467b48Spatrick                         << "    To: ";
59209467b48Spatrick                  if (RegionEnd != MBB->end()) dbgs() << *RegionEnd;
593*d415bd75Srobert                  else dbgs() << "End\n";
59409467b48Spatrick                  dbgs() << " RegionInstrs: " << NumRegionInstrs << '\n');
59509467b48Spatrick       if (DumpCriticalPathLength) {
59609467b48Spatrick         errs() << MF->getName();
59709467b48Spatrick         errs() << ":%bb. " << MBB->getNumber();
59809467b48Spatrick         errs() << " " << MBB->getName() << " \n";
59909467b48Spatrick       }
60009467b48Spatrick 
60109467b48Spatrick       // Schedule a region: possibly reorder instructions.
60209467b48Spatrick       // This invalidates the original region iterators.
60309467b48Spatrick       Scheduler.schedule();
60409467b48Spatrick 
60509467b48Spatrick       // Close the current region.
60609467b48Spatrick       Scheduler.exitRegion();
60709467b48Spatrick     }
60809467b48Spatrick     Scheduler.finishBlock();
60909467b48Spatrick     // FIXME: Ideally, no further passes should rely on kill flags. However,
61009467b48Spatrick     // thumb2 size reduction is currently an exception, so the PostMIScheduler
61109467b48Spatrick     // needs to do this.
61209467b48Spatrick     if (FixKillFlags)
61309467b48Spatrick       Scheduler.fixupKills(*MBB);
61409467b48Spatrick   }
61509467b48Spatrick   Scheduler.finalizeSchedule();
61609467b48Spatrick }
61709467b48Spatrick 
print(raw_ostream & O,const Module * m) const61809467b48Spatrick void MachineSchedulerBase::print(raw_ostream &O, const Module* m) const {
61909467b48Spatrick   // unimplemented
62009467b48Spatrick }
62109467b48Spatrick 
62209467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const62309467b48Spatrick LLVM_DUMP_METHOD void ReadyQueue::dump() const {
62409467b48Spatrick   dbgs() << "Queue " << Name << ": ";
62509467b48Spatrick   for (const SUnit *SU : Queue)
62609467b48Spatrick     dbgs() << SU->NodeNum << " ";
62709467b48Spatrick   dbgs() << "\n";
62809467b48Spatrick }
62909467b48Spatrick #endif
63009467b48Spatrick 
63109467b48Spatrick //===----------------------------------------------------------------------===//
63209467b48Spatrick // ScheduleDAGMI - Basic machine instruction scheduling. This is
63309467b48Spatrick // independent of PreRA/PostRA scheduling and involves no extra book-keeping for
63409467b48Spatrick // virtual registers.
63509467b48Spatrick // ===----------------------------------------------------------------------===/
63609467b48Spatrick 
63709467b48Spatrick // Provide a vtable anchor.
63809467b48Spatrick ScheduleDAGMI::~ScheduleDAGMI() = default;
63909467b48Spatrick 
64009467b48Spatrick /// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When
64109467b48Spatrick /// NumPredsLeft reaches zero, release the successor node.
64209467b48Spatrick ///
64309467b48Spatrick /// FIXME: Adjust SuccSU height based on MinLatency.
releaseSucc(SUnit * SU,SDep * SuccEdge)64409467b48Spatrick void ScheduleDAGMI::releaseSucc(SUnit *SU, SDep *SuccEdge) {
64509467b48Spatrick   SUnit *SuccSU = SuccEdge->getSUnit();
64609467b48Spatrick 
64709467b48Spatrick   if (SuccEdge->isWeak()) {
64809467b48Spatrick     --SuccSU->WeakPredsLeft;
64909467b48Spatrick     if (SuccEdge->isCluster())
65009467b48Spatrick       NextClusterSucc = SuccSU;
65109467b48Spatrick     return;
65209467b48Spatrick   }
65309467b48Spatrick #ifndef NDEBUG
65409467b48Spatrick   if (SuccSU->NumPredsLeft == 0) {
65509467b48Spatrick     dbgs() << "*** Scheduling failed! ***\n";
65609467b48Spatrick     dumpNode(*SuccSU);
65709467b48Spatrick     dbgs() << " has been released too many times!\n";
65809467b48Spatrick     llvm_unreachable(nullptr);
65909467b48Spatrick   }
66009467b48Spatrick #endif
66109467b48Spatrick   // SU->TopReadyCycle was set to CurrCycle when it was scheduled. However,
66209467b48Spatrick   // CurrCycle may have advanced since then.
66309467b48Spatrick   if (SuccSU->TopReadyCycle < SU->TopReadyCycle + SuccEdge->getLatency())
66409467b48Spatrick     SuccSU->TopReadyCycle = SU->TopReadyCycle + SuccEdge->getLatency();
66509467b48Spatrick 
66609467b48Spatrick   --SuccSU->NumPredsLeft;
66709467b48Spatrick   if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
66809467b48Spatrick     SchedImpl->releaseTopNode(SuccSU);
66909467b48Spatrick }
67009467b48Spatrick 
67109467b48Spatrick /// releaseSuccessors - Call releaseSucc on each of SU's successors.
releaseSuccessors(SUnit * SU)67209467b48Spatrick void ScheduleDAGMI::releaseSuccessors(SUnit *SU) {
67309467b48Spatrick   for (SDep &Succ : SU->Succs)
67409467b48Spatrick     releaseSucc(SU, &Succ);
67509467b48Spatrick }
67609467b48Spatrick 
67709467b48Spatrick /// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. When
67809467b48Spatrick /// NumSuccsLeft reaches zero, release the predecessor node.
67909467b48Spatrick ///
68009467b48Spatrick /// FIXME: Adjust PredSU height based on MinLatency.
releasePred(SUnit * SU,SDep * PredEdge)68109467b48Spatrick void ScheduleDAGMI::releasePred(SUnit *SU, SDep *PredEdge) {
68209467b48Spatrick   SUnit *PredSU = PredEdge->getSUnit();
68309467b48Spatrick 
68409467b48Spatrick   if (PredEdge->isWeak()) {
68509467b48Spatrick     --PredSU->WeakSuccsLeft;
68609467b48Spatrick     if (PredEdge->isCluster())
68709467b48Spatrick       NextClusterPred = PredSU;
68809467b48Spatrick     return;
68909467b48Spatrick   }
69009467b48Spatrick #ifndef NDEBUG
69109467b48Spatrick   if (PredSU->NumSuccsLeft == 0) {
69209467b48Spatrick     dbgs() << "*** Scheduling failed! ***\n";
69309467b48Spatrick     dumpNode(*PredSU);
69409467b48Spatrick     dbgs() << " has been released too many times!\n";
69509467b48Spatrick     llvm_unreachable(nullptr);
69609467b48Spatrick   }
69709467b48Spatrick #endif
69809467b48Spatrick   // SU->BotReadyCycle was set to CurrCycle when it was scheduled. However,
69909467b48Spatrick   // CurrCycle may have advanced since then.
70009467b48Spatrick   if (PredSU->BotReadyCycle < SU->BotReadyCycle + PredEdge->getLatency())
70109467b48Spatrick     PredSU->BotReadyCycle = SU->BotReadyCycle + PredEdge->getLatency();
70209467b48Spatrick 
70309467b48Spatrick   --PredSU->NumSuccsLeft;
70409467b48Spatrick   if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU)
70509467b48Spatrick     SchedImpl->releaseBottomNode(PredSU);
70609467b48Spatrick }
70709467b48Spatrick 
70809467b48Spatrick /// releasePredecessors - Call releasePred on each of SU's predecessors.
releasePredecessors(SUnit * SU)70909467b48Spatrick void ScheduleDAGMI::releasePredecessors(SUnit *SU) {
71009467b48Spatrick   for (SDep &Pred : SU->Preds)
71109467b48Spatrick     releasePred(SU, &Pred);
71209467b48Spatrick }
71309467b48Spatrick 
startBlock(MachineBasicBlock * bb)71409467b48Spatrick void ScheduleDAGMI::startBlock(MachineBasicBlock *bb) {
71509467b48Spatrick   ScheduleDAGInstrs::startBlock(bb);
71609467b48Spatrick   SchedImpl->enterMBB(bb);
71709467b48Spatrick }
71809467b48Spatrick 
finishBlock()71909467b48Spatrick void ScheduleDAGMI::finishBlock() {
72009467b48Spatrick   SchedImpl->leaveMBB();
72109467b48Spatrick   ScheduleDAGInstrs::finishBlock();
72209467b48Spatrick }
72309467b48Spatrick 
72409467b48Spatrick /// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
72509467b48Spatrick /// crossing a scheduling boundary. [begin, end) includes all instructions in
72609467b48Spatrick /// the region, including the boundary itself and single-instruction regions
72709467b48Spatrick /// that don't get scheduled.
enterRegion(MachineBasicBlock * bb,MachineBasicBlock::iterator begin,MachineBasicBlock::iterator end,unsigned regioninstrs)72809467b48Spatrick void ScheduleDAGMI::enterRegion(MachineBasicBlock *bb,
72909467b48Spatrick                                      MachineBasicBlock::iterator begin,
73009467b48Spatrick                                      MachineBasicBlock::iterator end,
73109467b48Spatrick                                      unsigned regioninstrs)
73209467b48Spatrick {
73309467b48Spatrick   ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
73409467b48Spatrick 
73509467b48Spatrick   SchedImpl->initPolicy(begin, end, regioninstrs);
73609467b48Spatrick }
73709467b48Spatrick 
73809467b48Spatrick /// This is normally called from the main scheduler loop but may also be invoked
73909467b48Spatrick /// by the scheduling strategy to perform additional code motion.
moveInstruction(MachineInstr * MI,MachineBasicBlock::iterator InsertPos)74009467b48Spatrick void ScheduleDAGMI::moveInstruction(
74109467b48Spatrick   MachineInstr *MI, MachineBasicBlock::iterator InsertPos) {
74209467b48Spatrick   // Advance RegionBegin if the first instruction moves down.
74309467b48Spatrick   if (&*RegionBegin == MI)
74409467b48Spatrick     ++RegionBegin;
74509467b48Spatrick 
74609467b48Spatrick   // Update the instruction stream.
74709467b48Spatrick   BB->splice(InsertPos, BB, MI);
74809467b48Spatrick 
74909467b48Spatrick   // Update LiveIntervals
75009467b48Spatrick   if (LIS)
75109467b48Spatrick     LIS->handleMove(*MI, /*UpdateFlags=*/true);
75209467b48Spatrick 
75309467b48Spatrick   // Recede RegionBegin if an instruction moves above the first.
75409467b48Spatrick   if (RegionBegin == InsertPos)
75509467b48Spatrick     RegionBegin = MI;
75609467b48Spatrick }
75709467b48Spatrick 
checkSchedLimit()75809467b48Spatrick bool ScheduleDAGMI::checkSchedLimit() {
759*d415bd75Srobert #if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)
76009467b48Spatrick   if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
76109467b48Spatrick     CurrentTop = CurrentBottom;
76209467b48Spatrick     return false;
76309467b48Spatrick   }
76409467b48Spatrick   ++NumInstrsScheduled;
76509467b48Spatrick #endif
76609467b48Spatrick   return true;
76709467b48Spatrick }
76809467b48Spatrick 
76909467b48Spatrick /// Per-region scheduling driver, called back from
77009467b48Spatrick /// MachineScheduler::runOnMachineFunction. This is a simplified driver that
77109467b48Spatrick /// does not consider liveness or register pressure. It is useful for PostRA
77209467b48Spatrick /// scheduling and potentially other custom schedulers.
schedule()77309467b48Spatrick void ScheduleDAGMI::schedule() {
77409467b48Spatrick   LLVM_DEBUG(dbgs() << "ScheduleDAGMI::schedule starting\n");
77509467b48Spatrick   LLVM_DEBUG(SchedImpl->dumpPolicy());
77609467b48Spatrick 
77709467b48Spatrick   // Build the DAG.
77809467b48Spatrick   buildSchedGraph(AA);
77909467b48Spatrick 
78009467b48Spatrick   postprocessDAG();
78109467b48Spatrick 
78209467b48Spatrick   SmallVector<SUnit*, 8> TopRoots, BotRoots;
78309467b48Spatrick   findRootsAndBiasEdges(TopRoots, BotRoots);
78409467b48Spatrick 
78509467b48Spatrick   LLVM_DEBUG(dump());
78609467b48Spatrick   if (PrintDAGs) dump();
78709467b48Spatrick   if (ViewMISchedDAGs) viewGraph();
78809467b48Spatrick 
78909467b48Spatrick   // Initialize the strategy before modifying the DAG.
79009467b48Spatrick   // This may initialize a DFSResult to be used for queue priority.
79109467b48Spatrick   SchedImpl->initialize(this);
79209467b48Spatrick 
79309467b48Spatrick   // Initialize ready queues now that the DAG and priority data are finalized.
79409467b48Spatrick   initQueues(TopRoots, BotRoots);
79509467b48Spatrick 
79609467b48Spatrick   bool IsTopNode = false;
79709467b48Spatrick   while (true) {
79809467b48Spatrick     LLVM_DEBUG(dbgs() << "** ScheduleDAGMI::schedule picking next node\n");
79909467b48Spatrick     SUnit *SU = SchedImpl->pickNode(IsTopNode);
80009467b48Spatrick     if (!SU) break;
80109467b48Spatrick 
80209467b48Spatrick     assert(!SU->isScheduled && "Node already scheduled");
80309467b48Spatrick     if (!checkSchedLimit())
80409467b48Spatrick       break;
80509467b48Spatrick 
80609467b48Spatrick     MachineInstr *MI = SU->getInstr();
80709467b48Spatrick     if (IsTopNode) {
80809467b48Spatrick       assert(SU->isTopReady() && "node still has unscheduled dependencies");
80909467b48Spatrick       if (&*CurrentTop == MI)
81009467b48Spatrick         CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
81109467b48Spatrick       else
81209467b48Spatrick         moveInstruction(MI, CurrentTop);
81309467b48Spatrick     } else {
81409467b48Spatrick       assert(SU->isBottomReady() && "node still has unscheduled dependencies");
81509467b48Spatrick       MachineBasicBlock::iterator priorII =
81609467b48Spatrick         priorNonDebug(CurrentBottom, CurrentTop);
81709467b48Spatrick       if (&*priorII == MI)
81809467b48Spatrick         CurrentBottom = priorII;
81909467b48Spatrick       else {
82009467b48Spatrick         if (&*CurrentTop == MI)
82109467b48Spatrick           CurrentTop = nextIfDebug(++CurrentTop, priorII);
82209467b48Spatrick         moveInstruction(MI, CurrentBottom);
82309467b48Spatrick         CurrentBottom = MI;
82409467b48Spatrick       }
82509467b48Spatrick     }
82609467b48Spatrick     // Notify the scheduling strategy before updating the DAG.
82709467b48Spatrick     // This sets the scheduled node's ReadyCycle to CurrCycle. When updateQueues
82809467b48Spatrick     // runs, it can then use the accurate ReadyCycle time to determine whether
82909467b48Spatrick     // newly released nodes can move to the readyQ.
83009467b48Spatrick     SchedImpl->schedNode(SU, IsTopNode);
83109467b48Spatrick 
83209467b48Spatrick     updateQueues(SU, IsTopNode);
83309467b48Spatrick   }
83409467b48Spatrick   assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
83509467b48Spatrick 
83609467b48Spatrick   placeDebugValues();
83709467b48Spatrick 
83809467b48Spatrick   LLVM_DEBUG({
83909467b48Spatrick     dbgs() << "*** Final schedule for "
84009467b48Spatrick            << printMBBReference(*begin()->getParent()) << " ***\n";
84109467b48Spatrick     dumpSchedule();
84209467b48Spatrick     dbgs() << '\n';
84309467b48Spatrick   });
84409467b48Spatrick }
84509467b48Spatrick 
84609467b48Spatrick /// Apply each ScheduleDAGMutation step in order.
postprocessDAG()84709467b48Spatrick void ScheduleDAGMI::postprocessDAG() {
84809467b48Spatrick   for (auto &m : Mutations)
84909467b48Spatrick     m->apply(this);
85009467b48Spatrick }
85109467b48Spatrick 
85209467b48Spatrick void ScheduleDAGMI::
findRootsAndBiasEdges(SmallVectorImpl<SUnit * > & TopRoots,SmallVectorImpl<SUnit * > & BotRoots)85309467b48Spatrick findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
85409467b48Spatrick                       SmallVectorImpl<SUnit*> &BotRoots) {
85509467b48Spatrick   for (SUnit &SU : SUnits) {
85609467b48Spatrick     assert(!SU.isBoundaryNode() && "Boundary node should not be in SUnits");
85709467b48Spatrick 
85809467b48Spatrick     // Order predecessors so DFSResult follows the critical path.
85909467b48Spatrick     SU.biasCriticalPath();
86009467b48Spatrick 
86109467b48Spatrick     // A SUnit is ready to top schedule if it has no predecessors.
86209467b48Spatrick     if (!SU.NumPredsLeft)
86309467b48Spatrick       TopRoots.push_back(&SU);
86409467b48Spatrick     // A SUnit is ready to bottom schedule if it has no successors.
86509467b48Spatrick     if (!SU.NumSuccsLeft)
86609467b48Spatrick       BotRoots.push_back(&SU);
86709467b48Spatrick   }
86809467b48Spatrick   ExitSU.biasCriticalPath();
86909467b48Spatrick }
87009467b48Spatrick 
87109467b48Spatrick /// Identify DAG roots and setup scheduler queues.
initQueues(ArrayRef<SUnit * > TopRoots,ArrayRef<SUnit * > BotRoots)87209467b48Spatrick void ScheduleDAGMI::initQueues(ArrayRef<SUnit*> TopRoots,
87309467b48Spatrick                                ArrayRef<SUnit*> BotRoots) {
87409467b48Spatrick   NextClusterSucc = nullptr;
87509467b48Spatrick   NextClusterPred = nullptr;
87609467b48Spatrick 
87709467b48Spatrick   // Release all DAG roots for scheduling, not including EntrySU/ExitSU.
87809467b48Spatrick   //
87909467b48Spatrick   // Nodes with unreleased weak edges can still be roots.
88009467b48Spatrick   // Release top roots in forward order.
88109467b48Spatrick   for (SUnit *SU : TopRoots)
88209467b48Spatrick     SchedImpl->releaseTopNode(SU);
88309467b48Spatrick 
88409467b48Spatrick   // Release bottom roots in reverse order so the higher priority nodes appear
88509467b48Spatrick   // first. This is more natural and slightly more efficient.
88609467b48Spatrick   for (SmallVectorImpl<SUnit*>::const_reverse_iterator
88709467b48Spatrick          I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I) {
88809467b48Spatrick     SchedImpl->releaseBottomNode(*I);
88909467b48Spatrick   }
89009467b48Spatrick 
89109467b48Spatrick   releaseSuccessors(&EntrySU);
89209467b48Spatrick   releasePredecessors(&ExitSU);
89309467b48Spatrick 
89409467b48Spatrick   SchedImpl->registerRoots();
89509467b48Spatrick 
89609467b48Spatrick   // Advance past initial DebugValues.
89709467b48Spatrick   CurrentTop = nextIfDebug(RegionBegin, RegionEnd);
89809467b48Spatrick   CurrentBottom = RegionEnd;
89909467b48Spatrick }
90009467b48Spatrick 
90109467b48Spatrick /// Update scheduler queues after scheduling an instruction.
updateQueues(SUnit * SU,bool IsTopNode)90209467b48Spatrick void ScheduleDAGMI::updateQueues(SUnit *SU, bool IsTopNode) {
90309467b48Spatrick   // Release dependent instructions for scheduling.
90409467b48Spatrick   if (IsTopNode)
90509467b48Spatrick     releaseSuccessors(SU);
90609467b48Spatrick   else
90709467b48Spatrick     releasePredecessors(SU);
90809467b48Spatrick 
90909467b48Spatrick   SU->isScheduled = true;
91009467b48Spatrick }
91109467b48Spatrick 
91209467b48Spatrick /// Reinsert any remaining debug_values, just like the PostRA scheduler.
placeDebugValues()91309467b48Spatrick void ScheduleDAGMI::placeDebugValues() {
91409467b48Spatrick   // If first instruction was a DBG_VALUE then put it back.
91509467b48Spatrick   if (FirstDbgValue) {
91609467b48Spatrick     BB->splice(RegionBegin, BB, FirstDbgValue);
91709467b48Spatrick     RegionBegin = FirstDbgValue;
91809467b48Spatrick   }
91909467b48Spatrick 
92009467b48Spatrick   for (std::vector<std::pair<MachineInstr *, MachineInstr *>>::iterator
92109467b48Spatrick          DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
92209467b48Spatrick     std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
92309467b48Spatrick     MachineInstr *DbgValue = P.first;
92409467b48Spatrick     MachineBasicBlock::iterator OrigPrevMI = P.second;
92509467b48Spatrick     if (&*RegionBegin == DbgValue)
92609467b48Spatrick       ++RegionBegin;
927*d415bd75Srobert     BB->splice(std::next(OrigPrevMI), BB, DbgValue);
928*d415bd75Srobert     if (RegionEnd != BB->end() && OrigPrevMI == &*RegionEnd)
92909467b48Spatrick       RegionEnd = DbgValue;
93009467b48Spatrick   }
93109467b48Spatrick }
93209467b48Spatrick 
93309467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dumpSchedule() const93409467b48Spatrick LLVM_DUMP_METHOD void ScheduleDAGMI::dumpSchedule() const {
93573471bf0Spatrick   for (MachineInstr &MI : *this) {
93673471bf0Spatrick     if (SUnit *SU = getSUnit(&MI))
93709467b48Spatrick       dumpNode(*SU);
93809467b48Spatrick     else
93909467b48Spatrick       dbgs() << "Missing SUnit\n";
94009467b48Spatrick   }
94109467b48Spatrick }
94209467b48Spatrick #endif
94309467b48Spatrick 
94409467b48Spatrick //===----------------------------------------------------------------------===//
94509467b48Spatrick // ScheduleDAGMILive - Base class for MachineInstr scheduling with LiveIntervals
94609467b48Spatrick // preservation.
94709467b48Spatrick //===----------------------------------------------------------------------===//
94809467b48Spatrick 
~ScheduleDAGMILive()94909467b48Spatrick ScheduleDAGMILive::~ScheduleDAGMILive() {
95009467b48Spatrick   delete DFSResult;
95109467b48Spatrick }
95209467b48Spatrick 
collectVRegUses(SUnit & SU)95309467b48Spatrick void ScheduleDAGMILive::collectVRegUses(SUnit &SU) {
95409467b48Spatrick   const MachineInstr &MI = *SU.getInstr();
95509467b48Spatrick   for (const MachineOperand &MO : MI.operands()) {
95609467b48Spatrick     if (!MO.isReg())
95709467b48Spatrick       continue;
95809467b48Spatrick     if (!MO.readsReg())
95909467b48Spatrick       continue;
96009467b48Spatrick     if (TrackLaneMasks && !MO.isUse())
96109467b48Spatrick       continue;
96209467b48Spatrick 
96309467b48Spatrick     Register Reg = MO.getReg();
964*d415bd75Srobert     if (!Reg.isVirtual())
96509467b48Spatrick       continue;
96609467b48Spatrick 
96709467b48Spatrick     // Ignore re-defs.
96809467b48Spatrick     if (TrackLaneMasks) {
96909467b48Spatrick       bool FoundDef = false;
97009467b48Spatrick       for (const MachineOperand &MO2 : MI.operands()) {
97109467b48Spatrick         if (MO2.isReg() && MO2.isDef() && MO2.getReg() == Reg && !MO2.isDead()) {
97209467b48Spatrick           FoundDef = true;
97309467b48Spatrick           break;
97409467b48Spatrick         }
97509467b48Spatrick       }
97609467b48Spatrick       if (FoundDef)
97709467b48Spatrick         continue;
97809467b48Spatrick     }
97909467b48Spatrick 
98009467b48Spatrick     // Record this local VReg use.
98109467b48Spatrick     VReg2SUnitMultiMap::iterator UI = VRegUses.find(Reg);
98209467b48Spatrick     for (; UI != VRegUses.end(); ++UI) {
98309467b48Spatrick       if (UI->SU == &SU)
98409467b48Spatrick         break;
98509467b48Spatrick     }
98609467b48Spatrick     if (UI == VRegUses.end())
98709467b48Spatrick       VRegUses.insert(VReg2SUnit(Reg, LaneBitmask::getNone(), &SU));
98809467b48Spatrick   }
98909467b48Spatrick }
99009467b48Spatrick 
99109467b48Spatrick /// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
99209467b48Spatrick /// crossing a scheduling boundary. [begin, end) includes all instructions in
99309467b48Spatrick /// the region, including the boundary itself and single-instruction regions
99409467b48Spatrick /// that don't get scheduled.
enterRegion(MachineBasicBlock * bb,MachineBasicBlock::iterator begin,MachineBasicBlock::iterator end,unsigned regioninstrs)99509467b48Spatrick void ScheduleDAGMILive::enterRegion(MachineBasicBlock *bb,
99609467b48Spatrick                                 MachineBasicBlock::iterator begin,
99709467b48Spatrick                                 MachineBasicBlock::iterator end,
99809467b48Spatrick                                 unsigned regioninstrs)
99909467b48Spatrick {
100009467b48Spatrick   // ScheduleDAGMI initializes SchedImpl's per-region policy.
100109467b48Spatrick   ScheduleDAGMI::enterRegion(bb, begin, end, regioninstrs);
100209467b48Spatrick 
100309467b48Spatrick   // For convenience remember the end of the liveness region.
100409467b48Spatrick   LiveRegionEnd = (RegionEnd == bb->end()) ? RegionEnd : std::next(RegionEnd);
100509467b48Spatrick 
100609467b48Spatrick   SUPressureDiffs.clear();
100709467b48Spatrick 
100809467b48Spatrick   ShouldTrackPressure = SchedImpl->shouldTrackPressure();
100909467b48Spatrick   ShouldTrackLaneMasks = SchedImpl->shouldTrackLaneMasks();
101009467b48Spatrick 
101109467b48Spatrick   assert((!ShouldTrackLaneMasks || ShouldTrackPressure) &&
101209467b48Spatrick          "ShouldTrackLaneMasks requires ShouldTrackPressure");
101309467b48Spatrick }
101409467b48Spatrick 
101509467b48Spatrick // Setup the register pressure trackers for the top scheduled and bottom
101609467b48Spatrick // scheduled regions.
initRegPressure()101709467b48Spatrick void ScheduleDAGMILive::initRegPressure() {
101809467b48Spatrick   VRegUses.clear();
101909467b48Spatrick   VRegUses.setUniverse(MRI.getNumVirtRegs());
102009467b48Spatrick   for (SUnit &SU : SUnits)
102109467b48Spatrick     collectVRegUses(SU);
102209467b48Spatrick 
102309467b48Spatrick   TopRPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin,
102409467b48Spatrick                     ShouldTrackLaneMasks, false);
102509467b48Spatrick   BotRPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
102609467b48Spatrick                     ShouldTrackLaneMasks, false);
102709467b48Spatrick 
102809467b48Spatrick   // Close the RPTracker to finalize live ins.
102909467b48Spatrick   RPTracker.closeRegion();
103009467b48Spatrick 
103109467b48Spatrick   LLVM_DEBUG(RPTracker.dump());
103209467b48Spatrick 
103309467b48Spatrick   // Initialize the live ins and live outs.
103409467b48Spatrick   TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
103509467b48Spatrick   BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
103609467b48Spatrick 
103709467b48Spatrick   // Close one end of the tracker so we can call
103809467b48Spatrick   // getMaxUpward/DownwardPressureDelta before advancing across any
103909467b48Spatrick   // instructions. This converts currently live regs into live ins/outs.
104009467b48Spatrick   TopRPTracker.closeTop();
104109467b48Spatrick   BotRPTracker.closeBottom();
104209467b48Spatrick 
104309467b48Spatrick   BotRPTracker.initLiveThru(RPTracker);
104409467b48Spatrick   if (!BotRPTracker.getLiveThru().empty()) {
104509467b48Spatrick     TopRPTracker.initLiveThru(BotRPTracker.getLiveThru());
104609467b48Spatrick     LLVM_DEBUG(dbgs() << "Live Thru: ";
104709467b48Spatrick                dumpRegSetPressure(BotRPTracker.getLiveThru(), TRI));
104809467b48Spatrick   };
104909467b48Spatrick 
105009467b48Spatrick   // For each live out vreg reduce the pressure change associated with other
105109467b48Spatrick   // uses of the same vreg below the live-out reaching def.
105209467b48Spatrick   updatePressureDiffs(RPTracker.getPressure().LiveOutRegs);
105309467b48Spatrick 
105409467b48Spatrick   // Account for liveness generated by the region boundary.
105509467b48Spatrick   if (LiveRegionEnd != RegionEnd) {
105609467b48Spatrick     SmallVector<RegisterMaskPair, 8> LiveUses;
105709467b48Spatrick     BotRPTracker.recede(&LiveUses);
105809467b48Spatrick     updatePressureDiffs(LiveUses);
105909467b48Spatrick   }
106009467b48Spatrick 
106109467b48Spatrick   LLVM_DEBUG(dbgs() << "Top Pressure:\n";
106209467b48Spatrick              dumpRegSetPressure(TopRPTracker.getRegSetPressureAtPos(), TRI);
106309467b48Spatrick              dbgs() << "Bottom Pressure:\n";
106409467b48Spatrick              dumpRegSetPressure(BotRPTracker.getRegSetPressureAtPos(), TRI););
106509467b48Spatrick 
106609467b48Spatrick   assert((BotRPTracker.getPos() == RegionEnd ||
106709467b48Spatrick           (RegionEnd->isDebugInstr() &&
106809467b48Spatrick            BotRPTracker.getPos() == priorNonDebug(RegionEnd, RegionBegin))) &&
106909467b48Spatrick          "Can't find the region bottom");
107009467b48Spatrick 
107109467b48Spatrick   // Cache the list of excess pressure sets in this region. This will also track
107209467b48Spatrick   // the max pressure in the scheduled code for these sets.
107309467b48Spatrick   RegionCriticalPSets.clear();
107409467b48Spatrick   const std::vector<unsigned> &RegionPressure =
107509467b48Spatrick     RPTracker.getPressure().MaxSetPressure;
107609467b48Spatrick   for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
107709467b48Spatrick     unsigned Limit = RegClassInfo->getRegPressureSetLimit(i);
107809467b48Spatrick     if (RegionPressure[i] > Limit) {
107909467b48Spatrick       LLVM_DEBUG(dbgs() << TRI->getRegPressureSetName(i) << " Limit " << Limit
108009467b48Spatrick                         << " Actual " << RegionPressure[i] << "\n");
108109467b48Spatrick       RegionCriticalPSets.push_back(PressureChange(i));
108209467b48Spatrick     }
108309467b48Spatrick   }
108409467b48Spatrick   LLVM_DEBUG(dbgs() << "Excess PSets: ";
108509467b48Spatrick              for (const PressureChange &RCPS
108609467b48Spatrick                   : RegionCriticalPSets) dbgs()
108709467b48Spatrick              << TRI->getRegPressureSetName(RCPS.getPSet()) << " ";
108809467b48Spatrick              dbgs() << "\n");
108909467b48Spatrick }
109009467b48Spatrick 
109109467b48Spatrick void ScheduleDAGMILive::
updateScheduledPressure(const SUnit * SU,const std::vector<unsigned> & NewMaxPressure)109209467b48Spatrick updateScheduledPressure(const SUnit *SU,
109309467b48Spatrick                         const std::vector<unsigned> &NewMaxPressure) {
109409467b48Spatrick   const PressureDiff &PDiff = getPressureDiff(SU);
109509467b48Spatrick   unsigned CritIdx = 0, CritEnd = RegionCriticalPSets.size();
109609467b48Spatrick   for (const PressureChange &PC : PDiff) {
109709467b48Spatrick     if (!PC.isValid())
109809467b48Spatrick       break;
109909467b48Spatrick     unsigned ID = PC.getPSet();
110009467b48Spatrick     while (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() < ID)
110109467b48Spatrick       ++CritIdx;
110209467b48Spatrick     if (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() == ID) {
110309467b48Spatrick       if ((int)NewMaxPressure[ID] > RegionCriticalPSets[CritIdx].getUnitInc()
110409467b48Spatrick           && NewMaxPressure[ID] <= (unsigned)std::numeric_limits<int16_t>::max())
110509467b48Spatrick         RegionCriticalPSets[CritIdx].setUnitInc(NewMaxPressure[ID]);
110609467b48Spatrick     }
110709467b48Spatrick     unsigned Limit = RegClassInfo->getRegPressureSetLimit(ID);
110809467b48Spatrick     if (NewMaxPressure[ID] >= Limit - 2) {
110909467b48Spatrick       LLVM_DEBUG(dbgs() << "  " << TRI->getRegPressureSetName(ID) << ": "
111009467b48Spatrick                         << NewMaxPressure[ID]
111109467b48Spatrick                         << ((NewMaxPressure[ID] > Limit) ? " > " : " <= ")
111209467b48Spatrick                         << Limit << "(+ " << BotRPTracker.getLiveThru()[ID]
111309467b48Spatrick                         << " livethru)\n");
111409467b48Spatrick     }
111509467b48Spatrick   }
111609467b48Spatrick }
111709467b48Spatrick 
111809467b48Spatrick /// Update the PressureDiff array for liveness after scheduling this
111909467b48Spatrick /// instruction.
updatePressureDiffs(ArrayRef<RegisterMaskPair> LiveUses)112009467b48Spatrick void ScheduleDAGMILive::updatePressureDiffs(
112109467b48Spatrick     ArrayRef<RegisterMaskPair> LiveUses) {
112209467b48Spatrick   for (const RegisterMaskPair &P : LiveUses) {
112373471bf0Spatrick     Register Reg = P.RegUnit;
112409467b48Spatrick     /// FIXME: Currently assuming single-use physregs.
1125*d415bd75Srobert     if (!Reg.isVirtual())
112609467b48Spatrick       continue;
112709467b48Spatrick 
112809467b48Spatrick     if (ShouldTrackLaneMasks) {
112909467b48Spatrick       // If the register has just become live then other uses won't change
113009467b48Spatrick       // this fact anymore => decrement pressure.
113109467b48Spatrick       // If the register has just become dead then other uses make it come
113209467b48Spatrick       // back to life => increment pressure.
113309467b48Spatrick       bool Decrement = P.LaneMask.any();
113409467b48Spatrick 
113509467b48Spatrick       for (const VReg2SUnit &V2SU
113609467b48Spatrick            : make_range(VRegUses.find(Reg), VRegUses.end())) {
113709467b48Spatrick         SUnit &SU = *V2SU.SU;
113809467b48Spatrick         if (SU.isScheduled || &SU == &ExitSU)
113909467b48Spatrick           continue;
114009467b48Spatrick 
114109467b48Spatrick         PressureDiff &PDiff = getPressureDiff(&SU);
114209467b48Spatrick         PDiff.addPressureChange(Reg, Decrement, &MRI);
114309467b48Spatrick         LLVM_DEBUG(dbgs() << "  UpdateRegP: SU(" << SU.NodeNum << ") "
114409467b48Spatrick                           << printReg(Reg, TRI) << ':'
114509467b48Spatrick                           << PrintLaneMask(P.LaneMask) << ' ' << *SU.getInstr();
114609467b48Spatrick                    dbgs() << "              to "; PDiff.dump(*TRI););
114709467b48Spatrick       }
114809467b48Spatrick     } else {
114909467b48Spatrick       assert(P.LaneMask.any());
115009467b48Spatrick       LLVM_DEBUG(dbgs() << "  LiveReg: " << printVRegOrUnit(Reg, TRI) << "\n");
115109467b48Spatrick       // This may be called before CurrentBottom has been initialized. However,
115209467b48Spatrick       // BotRPTracker must have a valid position. We want the value live into the
115309467b48Spatrick       // instruction or live out of the block, so ask for the previous
115409467b48Spatrick       // instruction's live-out.
115509467b48Spatrick       const LiveInterval &LI = LIS->getInterval(Reg);
115609467b48Spatrick       VNInfo *VNI;
115709467b48Spatrick       MachineBasicBlock::const_iterator I =
115809467b48Spatrick         nextIfDebug(BotRPTracker.getPos(), BB->end());
115909467b48Spatrick       if (I == BB->end())
116009467b48Spatrick         VNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
116109467b48Spatrick       else {
116209467b48Spatrick         LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*I));
116309467b48Spatrick         VNI = LRQ.valueIn();
116409467b48Spatrick       }
116509467b48Spatrick       // RegisterPressureTracker guarantees that readsReg is true for LiveUses.
116609467b48Spatrick       assert(VNI && "No live value at use.");
116709467b48Spatrick       for (const VReg2SUnit &V2SU
116809467b48Spatrick            : make_range(VRegUses.find(Reg), VRegUses.end())) {
116909467b48Spatrick         SUnit *SU = V2SU.SU;
117009467b48Spatrick         // If this use comes before the reaching def, it cannot be a last use,
117109467b48Spatrick         // so decrease its pressure change.
117209467b48Spatrick         if (!SU->isScheduled && SU != &ExitSU) {
117309467b48Spatrick           LiveQueryResult LRQ =
117409467b48Spatrick               LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
117509467b48Spatrick           if (LRQ.valueIn() == VNI) {
117609467b48Spatrick             PressureDiff &PDiff = getPressureDiff(SU);
117709467b48Spatrick             PDiff.addPressureChange(Reg, true, &MRI);
117809467b48Spatrick             LLVM_DEBUG(dbgs() << "  UpdateRegP: SU(" << SU->NodeNum << ") "
117909467b48Spatrick                               << *SU->getInstr();
118009467b48Spatrick                        dbgs() << "              to "; PDiff.dump(*TRI););
118109467b48Spatrick           }
118209467b48Spatrick         }
118309467b48Spatrick       }
118409467b48Spatrick     }
118509467b48Spatrick   }
118609467b48Spatrick }
118709467b48Spatrick 
dump() const118809467b48Spatrick void ScheduleDAGMILive::dump() const {
118909467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
119009467b48Spatrick   if (EntrySU.getInstr() != nullptr)
119109467b48Spatrick     dumpNodeAll(EntrySU);
119209467b48Spatrick   for (const SUnit &SU : SUnits) {
119309467b48Spatrick     dumpNodeAll(SU);
119409467b48Spatrick     if (ShouldTrackPressure) {
119509467b48Spatrick       dbgs() << "  Pressure Diff      : ";
119609467b48Spatrick       getPressureDiff(&SU).dump(*TRI);
119709467b48Spatrick     }
119809467b48Spatrick     dbgs() << "  Single Issue       : ";
119909467b48Spatrick     if (SchedModel.mustBeginGroup(SU.getInstr()) &&
120009467b48Spatrick         SchedModel.mustEndGroup(SU.getInstr()))
120109467b48Spatrick       dbgs() << "true;";
120209467b48Spatrick     else
120309467b48Spatrick       dbgs() << "false;";
120409467b48Spatrick     dbgs() << '\n';
120509467b48Spatrick   }
120609467b48Spatrick   if (ExitSU.getInstr() != nullptr)
120709467b48Spatrick     dumpNodeAll(ExitSU);
120809467b48Spatrick #endif
120909467b48Spatrick }
121009467b48Spatrick 
121109467b48Spatrick /// schedule - Called back from MachineScheduler::runOnMachineFunction
121209467b48Spatrick /// after setting up the current scheduling region. [RegionBegin, RegionEnd)
121309467b48Spatrick /// only includes instructions that have DAG nodes, not scheduling boundaries.
121409467b48Spatrick ///
121509467b48Spatrick /// This is a skeletal driver, with all the functionality pushed into helpers,
121609467b48Spatrick /// so that it can be easily extended by experimental schedulers. Generally,
121709467b48Spatrick /// implementing MachineSchedStrategy should be sufficient to implement a new
121809467b48Spatrick /// scheduling algorithm. However, if a scheduler further subclasses
121909467b48Spatrick /// ScheduleDAGMILive then it will want to override this virtual method in order
122009467b48Spatrick /// to update any specialized state.
schedule()122109467b48Spatrick void ScheduleDAGMILive::schedule() {
122209467b48Spatrick   LLVM_DEBUG(dbgs() << "ScheduleDAGMILive::schedule starting\n");
122309467b48Spatrick   LLVM_DEBUG(SchedImpl->dumpPolicy());
122409467b48Spatrick   buildDAGWithRegPressure();
122509467b48Spatrick 
122609467b48Spatrick   postprocessDAG();
122709467b48Spatrick 
122809467b48Spatrick   SmallVector<SUnit*, 8> TopRoots, BotRoots;
122909467b48Spatrick   findRootsAndBiasEdges(TopRoots, BotRoots);
123009467b48Spatrick 
123109467b48Spatrick   // Initialize the strategy before modifying the DAG.
123209467b48Spatrick   // This may initialize a DFSResult to be used for queue priority.
123309467b48Spatrick   SchedImpl->initialize(this);
123409467b48Spatrick 
123509467b48Spatrick   LLVM_DEBUG(dump());
123609467b48Spatrick   if (PrintDAGs) dump();
123709467b48Spatrick   if (ViewMISchedDAGs) viewGraph();
123809467b48Spatrick 
123909467b48Spatrick   // Initialize ready queues now that the DAG and priority data are finalized.
124009467b48Spatrick   initQueues(TopRoots, BotRoots);
124109467b48Spatrick 
124209467b48Spatrick   bool IsTopNode = false;
124309467b48Spatrick   while (true) {
124409467b48Spatrick     LLVM_DEBUG(dbgs() << "** ScheduleDAGMILive::schedule picking next node\n");
124509467b48Spatrick     SUnit *SU = SchedImpl->pickNode(IsTopNode);
124609467b48Spatrick     if (!SU) break;
124709467b48Spatrick 
124809467b48Spatrick     assert(!SU->isScheduled && "Node already scheduled");
124909467b48Spatrick     if (!checkSchedLimit())
125009467b48Spatrick       break;
125109467b48Spatrick 
125209467b48Spatrick     scheduleMI(SU, IsTopNode);
125309467b48Spatrick 
125409467b48Spatrick     if (DFSResult) {
125509467b48Spatrick       unsigned SubtreeID = DFSResult->getSubtreeID(SU);
125609467b48Spatrick       if (!ScheduledTrees.test(SubtreeID)) {
125709467b48Spatrick         ScheduledTrees.set(SubtreeID);
125809467b48Spatrick         DFSResult->scheduleTree(SubtreeID);
125909467b48Spatrick         SchedImpl->scheduleTree(SubtreeID);
126009467b48Spatrick       }
126109467b48Spatrick     }
126209467b48Spatrick 
126309467b48Spatrick     // Notify the scheduling strategy after updating the DAG.
126409467b48Spatrick     SchedImpl->schedNode(SU, IsTopNode);
126509467b48Spatrick 
126609467b48Spatrick     updateQueues(SU, IsTopNode);
126709467b48Spatrick   }
126809467b48Spatrick   assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
126909467b48Spatrick 
127009467b48Spatrick   placeDebugValues();
127109467b48Spatrick 
127209467b48Spatrick   LLVM_DEBUG({
127309467b48Spatrick     dbgs() << "*** Final schedule for "
127409467b48Spatrick            << printMBBReference(*begin()->getParent()) << " ***\n";
127509467b48Spatrick     dumpSchedule();
127609467b48Spatrick     dbgs() << '\n';
127709467b48Spatrick   });
127809467b48Spatrick }
127909467b48Spatrick 
128009467b48Spatrick /// Build the DAG and setup three register pressure trackers.
buildDAGWithRegPressure()128109467b48Spatrick void ScheduleDAGMILive::buildDAGWithRegPressure() {
128209467b48Spatrick   if (!ShouldTrackPressure) {
128309467b48Spatrick     RPTracker.reset();
128409467b48Spatrick     RegionCriticalPSets.clear();
128509467b48Spatrick     buildSchedGraph(AA);
128609467b48Spatrick     return;
128709467b48Spatrick   }
128809467b48Spatrick 
128909467b48Spatrick   // Initialize the register pressure tracker used by buildSchedGraph.
129009467b48Spatrick   RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
129109467b48Spatrick                  ShouldTrackLaneMasks, /*TrackUntiedDefs=*/true);
129209467b48Spatrick 
129309467b48Spatrick   // Account for liveness generate by the region boundary.
129409467b48Spatrick   if (LiveRegionEnd != RegionEnd)
129509467b48Spatrick     RPTracker.recede();
129609467b48Spatrick 
129709467b48Spatrick   // Build the DAG, and compute current register pressure.
129809467b48Spatrick   buildSchedGraph(AA, &RPTracker, &SUPressureDiffs, LIS, ShouldTrackLaneMasks);
129909467b48Spatrick 
130009467b48Spatrick   // Initialize top/bottom trackers after computing region pressure.
130109467b48Spatrick   initRegPressure();
130209467b48Spatrick }
130309467b48Spatrick 
computeDFSResult()130409467b48Spatrick void ScheduleDAGMILive::computeDFSResult() {
130509467b48Spatrick   if (!DFSResult)
130609467b48Spatrick     DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize);
130709467b48Spatrick   DFSResult->clear();
130809467b48Spatrick   ScheduledTrees.clear();
130909467b48Spatrick   DFSResult->resize(SUnits.size());
131009467b48Spatrick   DFSResult->compute(SUnits);
131109467b48Spatrick   ScheduledTrees.resize(DFSResult->getNumSubtrees());
131209467b48Spatrick }
131309467b48Spatrick 
131409467b48Spatrick /// Compute the max cyclic critical path through the DAG. The scheduling DAG
131509467b48Spatrick /// only provides the critical path for single block loops. To handle loops that
131609467b48Spatrick /// span blocks, we could use the vreg path latencies provided by
131709467b48Spatrick /// MachineTraceMetrics instead. However, MachineTraceMetrics is not currently
131809467b48Spatrick /// available for use in the scheduler.
131909467b48Spatrick ///
132009467b48Spatrick /// The cyclic path estimation identifies a def-use pair that crosses the back
132109467b48Spatrick /// edge and considers the depth and height of the nodes. For example, consider
132209467b48Spatrick /// the following instruction sequence where each instruction has unit latency
132373471bf0Spatrick /// and defines an eponymous virtual register:
132409467b48Spatrick ///
132509467b48Spatrick /// a->b(a,c)->c(b)->d(c)->exit
132609467b48Spatrick ///
132709467b48Spatrick /// The cyclic critical path is a two cycles: b->c->b
132809467b48Spatrick /// The acyclic critical path is four cycles: a->b->c->d->exit
132909467b48Spatrick /// LiveOutHeight = height(c) = len(c->d->exit) = 2
133009467b48Spatrick /// LiveOutDepth = depth(c) + 1 = len(a->b->c) + 1 = 3
133109467b48Spatrick /// LiveInHeight = height(b) + 1 = len(b->c->d->exit) + 1 = 4
133209467b48Spatrick /// LiveInDepth = depth(b) = len(a->b) = 1
133309467b48Spatrick ///
133409467b48Spatrick /// LiveOutDepth - LiveInDepth = 3 - 1 = 2
133509467b48Spatrick /// LiveInHeight - LiveOutHeight = 4 - 2 = 2
133609467b48Spatrick /// CyclicCriticalPath = min(2, 2) = 2
133709467b48Spatrick ///
133809467b48Spatrick /// This could be relevant to PostRA scheduling, but is currently implemented
133909467b48Spatrick /// assuming LiveIntervals.
computeCyclicCriticalPath()134009467b48Spatrick unsigned ScheduleDAGMILive::computeCyclicCriticalPath() {
134109467b48Spatrick   // This only applies to single block loop.
134209467b48Spatrick   if (!BB->isSuccessor(BB))
134309467b48Spatrick     return 0;
134409467b48Spatrick 
134509467b48Spatrick   unsigned MaxCyclicLatency = 0;
134609467b48Spatrick   // Visit each live out vreg def to find def/use pairs that cross iterations.
134709467b48Spatrick   for (const RegisterMaskPair &P : RPTracker.getPressure().LiveOutRegs) {
134873471bf0Spatrick     Register Reg = P.RegUnit;
1349*d415bd75Srobert     if (!Reg.isVirtual())
135009467b48Spatrick       continue;
135109467b48Spatrick     const LiveInterval &LI = LIS->getInterval(Reg);
135209467b48Spatrick     const VNInfo *DefVNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
135309467b48Spatrick     if (!DefVNI)
135409467b48Spatrick       continue;
135509467b48Spatrick 
135609467b48Spatrick     MachineInstr *DefMI = LIS->getInstructionFromIndex(DefVNI->def);
135709467b48Spatrick     const SUnit *DefSU = getSUnit(DefMI);
135809467b48Spatrick     if (!DefSU)
135909467b48Spatrick       continue;
136009467b48Spatrick 
136109467b48Spatrick     unsigned LiveOutHeight = DefSU->getHeight();
136209467b48Spatrick     unsigned LiveOutDepth = DefSU->getDepth() + DefSU->Latency;
136309467b48Spatrick     // Visit all local users of the vreg def.
136409467b48Spatrick     for (const VReg2SUnit &V2SU
136509467b48Spatrick          : make_range(VRegUses.find(Reg), VRegUses.end())) {
136609467b48Spatrick       SUnit *SU = V2SU.SU;
136709467b48Spatrick       if (SU == &ExitSU)
136809467b48Spatrick         continue;
136909467b48Spatrick 
137009467b48Spatrick       // Only consider uses of the phi.
137109467b48Spatrick       LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
137209467b48Spatrick       if (!LRQ.valueIn()->isPHIDef())
137309467b48Spatrick         continue;
137409467b48Spatrick 
137509467b48Spatrick       // Assume that a path spanning two iterations is a cycle, which could
137609467b48Spatrick       // overestimate in strange cases. This allows cyclic latency to be
137709467b48Spatrick       // estimated as the minimum slack of the vreg's depth or height.
137809467b48Spatrick       unsigned CyclicLatency = 0;
137909467b48Spatrick       if (LiveOutDepth > SU->getDepth())
138009467b48Spatrick         CyclicLatency = LiveOutDepth - SU->getDepth();
138109467b48Spatrick 
138209467b48Spatrick       unsigned LiveInHeight = SU->getHeight() + DefSU->Latency;
138309467b48Spatrick       if (LiveInHeight > LiveOutHeight) {
138409467b48Spatrick         if (LiveInHeight - LiveOutHeight < CyclicLatency)
138509467b48Spatrick           CyclicLatency = LiveInHeight - LiveOutHeight;
138609467b48Spatrick       } else
138709467b48Spatrick         CyclicLatency = 0;
138809467b48Spatrick 
138909467b48Spatrick       LLVM_DEBUG(dbgs() << "Cyclic Path: SU(" << DefSU->NodeNum << ") -> SU("
139009467b48Spatrick                         << SU->NodeNum << ") = " << CyclicLatency << "c\n");
139109467b48Spatrick       if (CyclicLatency > MaxCyclicLatency)
139209467b48Spatrick         MaxCyclicLatency = CyclicLatency;
139309467b48Spatrick     }
139409467b48Spatrick   }
139509467b48Spatrick   LLVM_DEBUG(dbgs() << "Cyclic Critical Path: " << MaxCyclicLatency << "c\n");
139609467b48Spatrick   return MaxCyclicLatency;
139709467b48Spatrick }
139809467b48Spatrick 
139909467b48Spatrick /// Release ExitSU predecessors and setup scheduler queues. Re-position
140009467b48Spatrick /// the Top RP tracker in case the region beginning has changed.
initQueues(ArrayRef<SUnit * > TopRoots,ArrayRef<SUnit * > BotRoots)140109467b48Spatrick void ScheduleDAGMILive::initQueues(ArrayRef<SUnit*> TopRoots,
140209467b48Spatrick                                    ArrayRef<SUnit*> BotRoots) {
140309467b48Spatrick   ScheduleDAGMI::initQueues(TopRoots, BotRoots);
140409467b48Spatrick   if (ShouldTrackPressure) {
140509467b48Spatrick     assert(TopRPTracker.getPos() == RegionBegin && "bad initial Top tracker");
140609467b48Spatrick     TopRPTracker.setPos(CurrentTop);
140709467b48Spatrick   }
140809467b48Spatrick }
140909467b48Spatrick 
141009467b48Spatrick /// Move an instruction and update register pressure.
scheduleMI(SUnit * SU,bool IsTopNode)141109467b48Spatrick void ScheduleDAGMILive::scheduleMI(SUnit *SU, bool IsTopNode) {
141209467b48Spatrick   // Move the instruction to its new location in the instruction stream.
141309467b48Spatrick   MachineInstr *MI = SU->getInstr();
141409467b48Spatrick 
141509467b48Spatrick   if (IsTopNode) {
141609467b48Spatrick     assert(SU->isTopReady() && "node still has unscheduled dependencies");
141709467b48Spatrick     if (&*CurrentTop == MI)
141809467b48Spatrick       CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
141909467b48Spatrick     else {
142009467b48Spatrick       moveInstruction(MI, CurrentTop);
142109467b48Spatrick       TopRPTracker.setPos(MI);
142209467b48Spatrick     }
142309467b48Spatrick 
142409467b48Spatrick     if (ShouldTrackPressure) {
142509467b48Spatrick       // Update top scheduled pressure.
142609467b48Spatrick       RegisterOperands RegOpers;
142709467b48Spatrick       RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
142809467b48Spatrick       if (ShouldTrackLaneMasks) {
142909467b48Spatrick         // Adjust liveness and add missing dead+read-undef flags.
143009467b48Spatrick         SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
143109467b48Spatrick         RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
143209467b48Spatrick       } else {
143309467b48Spatrick         // Adjust for missing dead-def flags.
143409467b48Spatrick         RegOpers.detectDeadDefs(*MI, *LIS);
143509467b48Spatrick       }
143609467b48Spatrick 
143709467b48Spatrick       TopRPTracker.advance(RegOpers);
143809467b48Spatrick       assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
143909467b48Spatrick       LLVM_DEBUG(dbgs() << "Top Pressure:\n"; dumpRegSetPressure(
144009467b48Spatrick                      TopRPTracker.getRegSetPressureAtPos(), TRI););
144109467b48Spatrick 
144209467b48Spatrick       updateScheduledPressure(SU, TopRPTracker.getPressure().MaxSetPressure);
144309467b48Spatrick     }
144409467b48Spatrick   } else {
144509467b48Spatrick     assert(SU->isBottomReady() && "node still has unscheduled dependencies");
144609467b48Spatrick     MachineBasicBlock::iterator priorII =
144709467b48Spatrick       priorNonDebug(CurrentBottom, CurrentTop);
144809467b48Spatrick     if (&*priorII == MI)
144909467b48Spatrick       CurrentBottom = priorII;
145009467b48Spatrick     else {
145109467b48Spatrick       if (&*CurrentTop == MI) {
145209467b48Spatrick         CurrentTop = nextIfDebug(++CurrentTop, priorII);
145309467b48Spatrick         TopRPTracker.setPos(CurrentTop);
145409467b48Spatrick       }
145509467b48Spatrick       moveInstruction(MI, CurrentBottom);
145609467b48Spatrick       CurrentBottom = MI;
145709467b48Spatrick       BotRPTracker.setPos(CurrentBottom);
145809467b48Spatrick     }
145909467b48Spatrick     if (ShouldTrackPressure) {
146009467b48Spatrick       RegisterOperands RegOpers;
146109467b48Spatrick       RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
146209467b48Spatrick       if (ShouldTrackLaneMasks) {
146309467b48Spatrick         // Adjust liveness and add missing dead+read-undef flags.
146409467b48Spatrick         SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
146509467b48Spatrick         RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
146609467b48Spatrick       } else {
146709467b48Spatrick         // Adjust for missing dead-def flags.
146809467b48Spatrick         RegOpers.detectDeadDefs(*MI, *LIS);
146909467b48Spatrick       }
147009467b48Spatrick 
147109467b48Spatrick       if (BotRPTracker.getPos() != CurrentBottom)
147209467b48Spatrick         BotRPTracker.recedeSkipDebugValues();
147309467b48Spatrick       SmallVector<RegisterMaskPair, 8> LiveUses;
147409467b48Spatrick       BotRPTracker.recede(RegOpers, &LiveUses);
147509467b48Spatrick       assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
147609467b48Spatrick       LLVM_DEBUG(dbgs() << "Bottom Pressure:\n"; dumpRegSetPressure(
147709467b48Spatrick                      BotRPTracker.getRegSetPressureAtPos(), TRI););
147809467b48Spatrick 
147909467b48Spatrick       updateScheduledPressure(SU, BotRPTracker.getPressure().MaxSetPressure);
148009467b48Spatrick       updatePressureDiffs(LiveUses);
148109467b48Spatrick     }
148209467b48Spatrick   }
148309467b48Spatrick }
148409467b48Spatrick 
148509467b48Spatrick //===----------------------------------------------------------------------===//
148609467b48Spatrick // BaseMemOpClusterMutation - DAG post-processing to cluster loads or stores.
148709467b48Spatrick //===----------------------------------------------------------------------===//
148809467b48Spatrick 
148909467b48Spatrick namespace {
149009467b48Spatrick 
149109467b48Spatrick /// Post-process the DAG to create cluster edges between neighboring
149209467b48Spatrick /// loads or between neighboring stores.
149309467b48Spatrick class BaseMemOpClusterMutation : public ScheduleDAGMutation {
149409467b48Spatrick   struct MemOpInfo {
149509467b48Spatrick     SUnit *SU;
1496097a140dSpatrick     SmallVector<const MachineOperand *, 4> BaseOps;
149709467b48Spatrick     int64_t Offset;
1498097a140dSpatrick     unsigned Width;
149909467b48Spatrick 
MemOpInfo__anonf2be975f0311::BaseMemOpClusterMutation::MemOpInfo1500097a140dSpatrick     MemOpInfo(SUnit *SU, ArrayRef<const MachineOperand *> BaseOps,
1501097a140dSpatrick               int64_t Offset, unsigned Width)
1502097a140dSpatrick         : SU(SU), BaseOps(BaseOps.begin(), BaseOps.end()), Offset(Offset),
1503097a140dSpatrick           Width(Width) {}
150409467b48Spatrick 
Compare__anonf2be975f0311::BaseMemOpClusterMutation::MemOpInfo1505097a140dSpatrick     static bool Compare(const MachineOperand *const &A,
1506097a140dSpatrick                         const MachineOperand *const &B) {
1507097a140dSpatrick       if (A->getType() != B->getType())
1508097a140dSpatrick         return A->getType() < B->getType();
1509097a140dSpatrick       if (A->isReg())
1510097a140dSpatrick         return A->getReg() < B->getReg();
1511097a140dSpatrick       if (A->isFI()) {
1512097a140dSpatrick         const MachineFunction &MF = *A->getParent()->getParent()->getParent();
151309467b48Spatrick         const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
151409467b48Spatrick         bool StackGrowsDown = TFI.getStackGrowthDirection() ==
151509467b48Spatrick                               TargetFrameLowering::StackGrowsDown;
1516097a140dSpatrick         return StackGrowsDown ? A->getIndex() > B->getIndex()
1517097a140dSpatrick                               : A->getIndex() < B->getIndex();
151809467b48Spatrick       }
151909467b48Spatrick 
152009467b48Spatrick       llvm_unreachable("MemOpClusterMutation only supports register or frame "
152109467b48Spatrick                        "index bases.");
152209467b48Spatrick     }
1523097a140dSpatrick 
operator <__anonf2be975f0311::BaseMemOpClusterMutation::MemOpInfo1524097a140dSpatrick     bool operator<(const MemOpInfo &RHS) const {
1525097a140dSpatrick       // FIXME: Don't compare everything twice. Maybe use C++20 three way
1526097a140dSpatrick       // comparison instead when it's available.
1527097a140dSpatrick       if (std::lexicographical_compare(BaseOps.begin(), BaseOps.end(),
1528097a140dSpatrick                                        RHS.BaseOps.begin(), RHS.BaseOps.end(),
1529097a140dSpatrick                                        Compare))
1530097a140dSpatrick         return true;
1531097a140dSpatrick       if (std::lexicographical_compare(RHS.BaseOps.begin(), RHS.BaseOps.end(),
1532097a140dSpatrick                                        BaseOps.begin(), BaseOps.end(), Compare))
1533097a140dSpatrick         return false;
1534097a140dSpatrick       if (Offset != RHS.Offset)
1535097a140dSpatrick         return Offset < RHS.Offset;
1536097a140dSpatrick       return SU->NodeNum < RHS.SU->NodeNum;
1537097a140dSpatrick     }
153809467b48Spatrick   };
153909467b48Spatrick 
154009467b48Spatrick   const TargetInstrInfo *TII;
154109467b48Spatrick   const TargetRegisterInfo *TRI;
154209467b48Spatrick   bool IsLoad;
154309467b48Spatrick 
154409467b48Spatrick public:
BaseMemOpClusterMutation(const TargetInstrInfo * tii,const TargetRegisterInfo * tri,bool IsLoad)154509467b48Spatrick   BaseMemOpClusterMutation(const TargetInstrInfo *tii,
154609467b48Spatrick                            const TargetRegisterInfo *tri, bool IsLoad)
154709467b48Spatrick       : TII(tii), TRI(tri), IsLoad(IsLoad) {}
154809467b48Spatrick 
154909467b48Spatrick   void apply(ScheduleDAGInstrs *DAGInstrs) override;
155009467b48Spatrick 
155109467b48Spatrick protected:
155273471bf0Spatrick   void clusterNeighboringMemOps(ArrayRef<MemOpInfo> MemOps, bool FastCluster,
155373471bf0Spatrick                                 ScheduleDAGInstrs *DAG);
155473471bf0Spatrick   void collectMemOpRecords(std::vector<SUnit> &SUnits,
155573471bf0Spatrick                            SmallVectorImpl<MemOpInfo> &MemOpRecords);
155673471bf0Spatrick   bool groupMemOps(ArrayRef<MemOpInfo> MemOps, ScheduleDAGInstrs *DAG,
155773471bf0Spatrick                    DenseMap<unsigned, SmallVector<MemOpInfo, 32>> &Groups);
155809467b48Spatrick };
155909467b48Spatrick 
156009467b48Spatrick class StoreClusterMutation : public BaseMemOpClusterMutation {
156109467b48Spatrick public:
StoreClusterMutation(const TargetInstrInfo * tii,const TargetRegisterInfo * tri)156209467b48Spatrick   StoreClusterMutation(const TargetInstrInfo *tii,
156309467b48Spatrick                        const TargetRegisterInfo *tri)
156409467b48Spatrick       : BaseMemOpClusterMutation(tii, tri, false) {}
156509467b48Spatrick };
156609467b48Spatrick 
156709467b48Spatrick class LoadClusterMutation : public BaseMemOpClusterMutation {
156809467b48Spatrick public:
LoadClusterMutation(const TargetInstrInfo * tii,const TargetRegisterInfo * tri)156909467b48Spatrick   LoadClusterMutation(const TargetInstrInfo *tii, const TargetRegisterInfo *tri)
157009467b48Spatrick       : BaseMemOpClusterMutation(tii, tri, true) {}
157109467b48Spatrick };
157209467b48Spatrick 
157309467b48Spatrick } // end anonymous namespace
157409467b48Spatrick 
157509467b48Spatrick namespace llvm {
157609467b48Spatrick 
157709467b48Spatrick std::unique_ptr<ScheduleDAGMutation>
createLoadClusterDAGMutation(const TargetInstrInfo * TII,const TargetRegisterInfo * TRI)157809467b48Spatrick createLoadClusterDAGMutation(const TargetInstrInfo *TII,
157909467b48Spatrick                              const TargetRegisterInfo *TRI) {
158009467b48Spatrick   return EnableMemOpCluster ? std::make_unique<LoadClusterMutation>(TII, TRI)
158109467b48Spatrick                             : nullptr;
158209467b48Spatrick }
158309467b48Spatrick 
158409467b48Spatrick std::unique_ptr<ScheduleDAGMutation>
createStoreClusterDAGMutation(const TargetInstrInfo * TII,const TargetRegisterInfo * TRI)158509467b48Spatrick createStoreClusterDAGMutation(const TargetInstrInfo *TII,
158609467b48Spatrick                               const TargetRegisterInfo *TRI) {
158709467b48Spatrick   return EnableMemOpCluster ? std::make_unique<StoreClusterMutation>(TII, TRI)
158809467b48Spatrick                             : nullptr;
158909467b48Spatrick }
159009467b48Spatrick 
159109467b48Spatrick } // end namespace llvm
159209467b48Spatrick 
159373471bf0Spatrick // Sorting all the loads/stores first, then for each load/store, checking the
159473471bf0Spatrick // following load/store one by one, until reach the first non-dependent one and
159573471bf0Spatrick // call target hook to see if they can cluster.
159673471bf0Spatrick // If FastCluster is enabled, we assume that, all the loads/stores have been
159773471bf0Spatrick // preprocessed and now, they didn't have dependencies on each other.
clusterNeighboringMemOps(ArrayRef<MemOpInfo> MemOpRecords,bool FastCluster,ScheduleDAGInstrs * DAG)159809467b48Spatrick void BaseMemOpClusterMutation::clusterNeighboringMemOps(
159973471bf0Spatrick     ArrayRef<MemOpInfo> MemOpRecords, bool FastCluster,
160073471bf0Spatrick     ScheduleDAGInstrs *DAG) {
160173471bf0Spatrick   // Keep track of the current cluster length and bytes for each SUnit.
160273471bf0Spatrick   DenseMap<unsigned, std::pair<unsigned, unsigned>> SUnit2ClusterInfo;
1603097a140dSpatrick 
1604097a140dSpatrick   // At this point, `MemOpRecords` array must hold atleast two mem ops. Try to
1605097a140dSpatrick   // cluster mem ops collected within `MemOpRecords` array.
160609467b48Spatrick   for (unsigned Idx = 0, End = MemOpRecords.size(); Idx < (End - 1); ++Idx) {
1607097a140dSpatrick     // Decision to cluster mem ops is taken based on target dependent logic
1608097a140dSpatrick     auto MemOpa = MemOpRecords[Idx];
160973471bf0Spatrick 
161073471bf0Spatrick     // Seek for the next load/store to do the cluster.
161173471bf0Spatrick     unsigned NextIdx = Idx + 1;
161273471bf0Spatrick     for (; NextIdx < End; ++NextIdx)
161373471bf0Spatrick       // Skip if MemOpb has been clustered already or has dependency with
161473471bf0Spatrick       // MemOpa.
161573471bf0Spatrick       if (!SUnit2ClusterInfo.count(MemOpRecords[NextIdx].SU->NodeNum) &&
161673471bf0Spatrick           (FastCluster ||
161773471bf0Spatrick            (!DAG->IsReachable(MemOpRecords[NextIdx].SU, MemOpa.SU) &&
161873471bf0Spatrick             !DAG->IsReachable(MemOpa.SU, MemOpRecords[NextIdx].SU))))
161973471bf0Spatrick         break;
162073471bf0Spatrick     if (NextIdx == End)
1621097a140dSpatrick       continue;
162273471bf0Spatrick 
162373471bf0Spatrick     auto MemOpb = MemOpRecords[NextIdx];
162473471bf0Spatrick     unsigned ClusterLength = 2;
162573471bf0Spatrick     unsigned CurrentClusterBytes = MemOpa.Width + MemOpb.Width;
162673471bf0Spatrick     if (SUnit2ClusterInfo.count(MemOpa.SU->NodeNum)) {
162773471bf0Spatrick       ClusterLength = SUnit2ClusterInfo[MemOpa.SU->NodeNum].first + 1;
162873471bf0Spatrick       CurrentClusterBytes =
162973471bf0Spatrick           SUnit2ClusterInfo[MemOpa.SU->NodeNum].second + MemOpb.Width;
1630097a140dSpatrick     }
1631097a140dSpatrick 
163273471bf0Spatrick     if (!TII->shouldClusterMemOps(MemOpa.BaseOps, MemOpb.BaseOps, ClusterLength,
163373471bf0Spatrick                                   CurrentClusterBytes))
163473471bf0Spatrick       continue;
163573471bf0Spatrick 
1636097a140dSpatrick     SUnit *SUa = MemOpa.SU;
1637097a140dSpatrick     SUnit *SUb = MemOpb.SU;
163809467b48Spatrick     if (SUa->NodeNum > SUb->NodeNum)
163909467b48Spatrick       std::swap(SUa, SUb);
1640097a140dSpatrick 
1641097a140dSpatrick     // FIXME: Is this check really required?
164273471bf0Spatrick     if (!DAG->addEdge(SUb, SDep(SUa, SDep::Cluster)))
1643097a140dSpatrick       continue;
1644097a140dSpatrick 
164509467b48Spatrick     LLVM_DEBUG(dbgs() << "Cluster ld/st SU(" << SUa->NodeNum << ") - SU("
164609467b48Spatrick                       << SUb->NodeNum << ")\n");
164773471bf0Spatrick     ++NumClustered;
1648097a140dSpatrick 
164973471bf0Spatrick     if (IsLoad) {
165009467b48Spatrick       // Copy successor edges from SUa to SUb. Interleaving computation
165109467b48Spatrick       // dependent on SUa can prevent load combining due to register reuse.
1652097a140dSpatrick       // Predecessor edges do not need to be copied from SUb to SUa since
1653097a140dSpatrick       // nearby loads should have effectively the same inputs.
165409467b48Spatrick       for (const SDep &Succ : SUa->Succs) {
165509467b48Spatrick         if (Succ.getSUnit() == SUb)
165609467b48Spatrick           continue;
165709467b48Spatrick         LLVM_DEBUG(dbgs() << "  Copy Succ SU(" << Succ.getSUnit()->NodeNum
165809467b48Spatrick                           << ")\n");
165909467b48Spatrick         DAG->addEdge(Succ.getSUnit(), SDep(SUb, SDep::Artificial));
166009467b48Spatrick       }
166173471bf0Spatrick     } else {
166273471bf0Spatrick       // Copy predecessor edges from SUb to SUa to avoid the SUnits that
166373471bf0Spatrick       // SUb dependent on scheduled in-between SUb and SUa. Successor edges
166473471bf0Spatrick       // do not need to be copied from SUa to SUb since no one will depend
166573471bf0Spatrick       // on stores.
166673471bf0Spatrick       // Notice that, we don't need to care about the memory dependency as
166773471bf0Spatrick       // we won't try to cluster them if they have any memory dependency.
166873471bf0Spatrick       for (const SDep &Pred : SUb->Preds) {
166973471bf0Spatrick         if (Pred.getSUnit() == SUa)
167073471bf0Spatrick           continue;
167173471bf0Spatrick         LLVM_DEBUG(dbgs() << "  Copy Pred SU(" << Pred.getSUnit()->NodeNum
167273471bf0Spatrick                           << ")\n");
167373471bf0Spatrick         DAG->addEdge(SUa, SDep(Pred.getSUnit(), SDep::Artificial));
167473471bf0Spatrick       }
167573471bf0Spatrick     }
167673471bf0Spatrick 
167773471bf0Spatrick     SUnit2ClusterInfo[MemOpb.SU->NodeNum] = {ClusterLength,
167873471bf0Spatrick                                              CurrentClusterBytes};
1679097a140dSpatrick 
1680097a140dSpatrick     LLVM_DEBUG(dbgs() << "  Curr cluster length: " << ClusterLength
1681097a140dSpatrick                       << ", Curr cluster bytes: " << CurrentClusterBytes
1682097a140dSpatrick                       << "\n");
168309467b48Spatrick   }
168409467b48Spatrick }
168509467b48Spatrick 
collectMemOpRecords(std::vector<SUnit> & SUnits,SmallVectorImpl<MemOpInfo> & MemOpRecords)168673471bf0Spatrick void BaseMemOpClusterMutation::collectMemOpRecords(
168773471bf0Spatrick     std::vector<SUnit> &SUnits, SmallVectorImpl<MemOpInfo> &MemOpRecords) {
168873471bf0Spatrick   for (auto &SU : SUnits) {
168909467b48Spatrick     if ((IsLoad && !SU.getInstr()->mayLoad()) ||
169009467b48Spatrick         (!IsLoad && !SU.getInstr()->mayStore()))
169109467b48Spatrick       continue;
169209467b48Spatrick 
169373471bf0Spatrick     const MachineInstr &MI = *SU.getInstr();
169473471bf0Spatrick     SmallVector<const MachineOperand *, 4> BaseOps;
169573471bf0Spatrick     int64_t Offset;
169673471bf0Spatrick     bool OffsetIsScalable;
169773471bf0Spatrick     unsigned Width;
169873471bf0Spatrick     if (TII->getMemOperandsWithOffsetWidth(MI, BaseOps, Offset,
169973471bf0Spatrick                                            OffsetIsScalable, Width, TRI)) {
170073471bf0Spatrick       MemOpRecords.push_back(MemOpInfo(&SU, BaseOps, Offset, Width));
170173471bf0Spatrick 
170273471bf0Spatrick       LLVM_DEBUG(dbgs() << "Num BaseOps: " << BaseOps.size() << ", Offset: "
170373471bf0Spatrick                         << Offset << ", OffsetIsScalable: " << OffsetIsScalable
170473471bf0Spatrick                         << ", Width: " << Width << "\n");
170573471bf0Spatrick     }
170673471bf0Spatrick #ifndef NDEBUG
1707*d415bd75Srobert     for (const auto *Op : BaseOps)
170873471bf0Spatrick       assert(Op);
170973471bf0Spatrick #endif
171073471bf0Spatrick   }
171173471bf0Spatrick }
171273471bf0Spatrick 
groupMemOps(ArrayRef<MemOpInfo> MemOps,ScheduleDAGInstrs * DAG,DenseMap<unsigned,SmallVector<MemOpInfo,32>> & Groups)171373471bf0Spatrick bool BaseMemOpClusterMutation::groupMemOps(
171473471bf0Spatrick     ArrayRef<MemOpInfo> MemOps, ScheduleDAGInstrs *DAG,
171573471bf0Spatrick     DenseMap<unsigned, SmallVector<MemOpInfo, 32>> &Groups) {
171673471bf0Spatrick   bool FastCluster =
171773471bf0Spatrick       ForceFastCluster ||
171873471bf0Spatrick       MemOps.size() * DAG->SUnits.size() / 1000 > FastClusterThreshold;
171973471bf0Spatrick 
172073471bf0Spatrick   for (const auto &MemOp : MemOps) {
172109467b48Spatrick     unsigned ChainPredID = DAG->SUnits.size();
172273471bf0Spatrick     if (FastCluster) {
172373471bf0Spatrick       for (const SDep &Pred : MemOp.SU->Preds) {
172473471bf0Spatrick         // We only want to cluster the mem ops that have the same ctrl(non-data)
172573471bf0Spatrick         // pred so that they didn't have ctrl dependency for each other. But for
172673471bf0Spatrick         // store instrs, we can still cluster them if the pred is load instr.
172773471bf0Spatrick         if ((Pred.isCtrl() &&
172873471bf0Spatrick              (IsLoad ||
172973471bf0Spatrick               (Pred.getSUnit() && Pred.getSUnit()->getInstr()->mayStore()))) &&
173073471bf0Spatrick             !Pred.isArtificial()) {
173109467b48Spatrick           ChainPredID = Pred.getSUnit()->NodeNum;
173209467b48Spatrick           break;
173309467b48Spatrick         }
173409467b48Spatrick       }
173573471bf0Spatrick     } else
173673471bf0Spatrick       ChainPredID = 0;
173773471bf0Spatrick 
173873471bf0Spatrick     Groups[ChainPredID].push_back(MemOp);
173973471bf0Spatrick   }
174073471bf0Spatrick   return FastCluster;
174109467b48Spatrick }
174209467b48Spatrick 
174373471bf0Spatrick /// Callback from DAG postProcessing to create cluster edges for loads/stores.
apply(ScheduleDAGInstrs * DAG)174473471bf0Spatrick void BaseMemOpClusterMutation::apply(ScheduleDAGInstrs *DAG) {
174573471bf0Spatrick   // Collect all the clusterable loads/stores
174673471bf0Spatrick   SmallVector<MemOpInfo, 32> MemOpRecords;
174773471bf0Spatrick   collectMemOpRecords(DAG->SUnits, MemOpRecords);
174873471bf0Spatrick 
174973471bf0Spatrick   if (MemOpRecords.size() < 2)
175073471bf0Spatrick     return;
175173471bf0Spatrick 
175273471bf0Spatrick   // Put the loads/stores without dependency into the same group with some
175373471bf0Spatrick   // heuristic if the DAG is too complex to avoid compiling time blow up.
175473471bf0Spatrick   // Notice that, some fusion pair could be lost with this.
175573471bf0Spatrick   DenseMap<unsigned, SmallVector<MemOpInfo, 32>> Groups;
175673471bf0Spatrick   bool FastCluster = groupMemOps(MemOpRecords, DAG, Groups);
175773471bf0Spatrick 
175873471bf0Spatrick   for (auto &Group : Groups) {
175973471bf0Spatrick     // Sorting the loads/stores, so that, we can stop the cluster as early as
176073471bf0Spatrick     // possible.
176173471bf0Spatrick     llvm::sort(Group.second);
176273471bf0Spatrick 
176373471bf0Spatrick     // Trying to cluster all the neighboring loads/stores.
176473471bf0Spatrick     clusterNeighboringMemOps(Group.second, FastCluster, DAG);
176573471bf0Spatrick   }
176609467b48Spatrick }
176709467b48Spatrick 
176809467b48Spatrick //===----------------------------------------------------------------------===//
176909467b48Spatrick // CopyConstrain - DAG post-processing to encourage copy elimination.
177009467b48Spatrick //===----------------------------------------------------------------------===//
177109467b48Spatrick 
177209467b48Spatrick namespace {
177309467b48Spatrick 
177409467b48Spatrick /// Post-process the DAG to create weak edges from all uses of a copy to
177509467b48Spatrick /// the one use that defines the copy's source vreg, most likely an induction
177609467b48Spatrick /// variable increment.
177709467b48Spatrick class CopyConstrain : public ScheduleDAGMutation {
177809467b48Spatrick   // Transient state.
177909467b48Spatrick   SlotIndex RegionBeginIdx;
178009467b48Spatrick 
178109467b48Spatrick   // RegionEndIdx is the slot index of the last non-debug instruction in the
178209467b48Spatrick   // scheduling region. So we may have RegionBeginIdx == RegionEndIdx.
178309467b48Spatrick   SlotIndex RegionEndIdx;
178409467b48Spatrick 
178509467b48Spatrick public:
CopyConstrain(const TargetInstrInfo *,const TargetRegisterInfo *)178609467b48Spatrick   CopyConstrain(const TargetInstrInfo *, const TargetRegisterInfo *) {}
178709467b48Spatrick 
178809467b48Spatrick   void apply(ScheduleDAGInstrs *DAGInstrs) override;
178909467b48Spatrick 
179009467b48Spatrick protected:
179109467b48Spatrick   void constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG);
179209467b48Spatrick };
179309467b48Spatrick 
179409467b48Spatrick } // end anonymous namespace
179509467b48Spatrick 
179609467b48Spatrick namespace llvm {
179709467b48Spatrick 
179809467b48Spatrick std::unique_ptr<ScheduleDAGMutation>
createCopyConstrainDAGMutation(const TargetInstrInfo * TII,const TargetRegisterInfo * TRI)179909467b48Spatrick createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
180009467b48Spatrick                                const TargetRegisterInfo *TRI) {
180109467b48Spatrick   return std::make_unique<CopyConstrain>(TII, TRI);
180209467b48Spatrick }
180309467b48Spatrick 
180409467b48Spatrick } // end namespace llvm
180509467b48Spatrick 
180609467b48Spatrick /// constrainLocalCopy handles two possibilities:
180709467b48Spatrick /// 1) Local src:
180809467b48Spatrick /// I0:     = dst
180909467b48Spatrick /// I1: src = ...
181009467b48Spatrick /// I2:     = dst
181109467b48Spatrick /// I3: dst = src (copy)
181209467b48Spatrick /// (create pred->succ edges I0->I1, I2->I1)
181309467b48Spatrick ///
181409467b48Spatrick /// 2) Local copy:
181509467b48Spatrick /// I0: dst = src (copy)
181609467b48Spatrick /// I1:     = dst
181709467b48Spatrick /// I2: src = ...
181809467b48Spatrick /// I3:     = dst
181909467b48Spatrick /// (create pred->succ edges I1->I2, I3->I2)
182009467b48Spatrick ///
182109467b48Spatrick /// Although the MachineScheduler is currently constrained to single blocks,
182209467b48Spatrick /// this algorithm should handle extended blocks. An EBB is a set of
182309467b48Spatrick /// contiguously numbered blocks such that the previous block in the EBB is
182409467b48Spatrick /// always the single predecessor.
constrainLocalCopy(SUnit * CopySU,ScheduleDAGMILive * DAG)182509467b48Spatrick void CopyConstrain::constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG) {
182609467b48Spatrick   LiveIntervals *LIS = DAG->getLIS();
182709467b48Spatrick   MachineInstr *Copy = CopySU->getInstr();
182809467b48Spatrick 
182909467b48Spatrick   // Check for pure vreg copies.
183009467b48Spatrick   const MachineOperand &SrcOp = Copy->getOperand(1);
183109467b48Spatrick   Register SrcReg = SrcOp.getReg();
1832*d415bd75Srobert   if (!SrcReg.isVirtual() || !SrcOp.readsReg())
183309467b48Spatrick     return;
183409467b48Spatrick 
183509467b48Spatrick   const MachineOperand &DstOp = Copy->getOperand(0);
183609467b48Spatrick   Register DstReg = DstOp.getReg();
1837*d415bd75Srobert   if (!DstReg.isVirtual() || DstOp.isDead())
183809467b48Spatrick     return;
183909467b48Spatrick 
184009467b48Spatrick   // Check if either the dest or source is local. If it's live across a back
184109467b48Spatrick   // edge, it's not local. Note that if both vregs are live across the back
184209467b48Spatrick   // edge, we cannot successfully contrain the copy without cyclic scheduling.
184309467b48Spatrick   // If both the copy's source and dest are local live intervals, then we
184409467b48Spatrick   // should treat the dest as the global for the purpose of adding
184509467b48Spatrick   // constraints. This adds edges from source's other uses to the copy.
184609467b48Spatrick   unsigned LocalReg = SrcReg;
184709467b48Spatrick   unsigned GlobalReg = DstReg;
184809467b48Spatrick   LiveInterval *LocalLI = &LIS->getInterval(LocalReg);
184909467b48Spatrick   if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx)) {
185009467b48Spatrick     LocalReg = DstReg;
185109467b48Spatrick     GlobalReg = SrcReg;
185209467b48Spatrick     LocalLI = &LIS->getInterval(LocalReg);
185309467b48Spatrick     if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx))
185409467b48Spatrick       return;
185509467b48Spatrick   }
185609467b48Spatrick   LiveInterval *GlobalLI = &LIS->getInterval(GlobalReg);
185709467b48Spatrick 
185809467b48Spatrick   // Find the global segment after the start of the local LI.
185909467b48Spatrick   LiveInterval::iterator GlobalSegment = GlobalLI->find(LocalLI->beginIndex());
186009467b48Spatrick   // If GlobalLI does not overlap LocalLI->start, then a copy directly feeds a
186109467b48Spatrick   // local live range. We could create edges from other global uses to the local
186209467b48Spatrick   // start, but the coalescer should have already eliminated these cases, so
186309467b48Spatrick   // don't bother dealing with it.
186409467b48Spatrick   if (GlobalSegment == GlobalLI->end())
186509467b48Spatrick     return;
186609467b48Spatrick 
186709467b48Spatrick   // If GlobalSegment is killed at the LocalLI->start, the call to find()
186809467b48Spatrick   // returned the next global segment. But if GlobalSegment overlaps with
186909467b48Spatrick   // LocalLI->start, then advance to the next segment. If a hole in GlobalLI
187009467b48Spatrick   // exists in LocalLI's vicinity, GlobalSegment will be the end of the hole.
187109467b48Spatrick   if (GlobalSegment->contains(LocalLI->beginIndex()))
187209467b48Spatrick     ++GlobalSegment;
187309467b48Spatrick 
187409467b48Spatrick   if (GlobalSegment == GlobalLI->end())
187509467b48Spatrick     return;
187609467b48Spatrick 
187709467b48Spatrick   // Check if GlobalLI contains a hole in the vicinity of LocalLI.
187809467b48Spatrick   if (GlobalSegment != GlobalLI->begin()) {
187909467b48Spatrick     // Two address defs have no hole.
188009467b48Spatrick     if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->end,
188109467b48Spatrick                                GlobalSegment->start)) {
188209467b48Spatrick       return;
188309467b48Spatrick     }
188409467b48Spatrick     // If the prior global segment may be defined by the same two-address
188509467b48Spatrick     // instruction that also defines LocalLI, then can't make a hole here.
188609467b48Spatrick     if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->start,
188709467b48Spatrick                                LocalLI->beginIndex())) {
188809467b48Spatrick       return;
188909467b48Spatrick     }
189009467b48Spatrick     // If GlobalLI has a prior segment, it must be live into the EBB. Otherwise
189109467b48Spatrick     // it would be a disconnected component in the live range.
189209467b48Spatrick     assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
189309467b48Spatrick            "Disconnected LRG within the scheduling region.");
189409467b48Spatrick   }
189509467b48Spatrick   MachineInstr *GlobalDef = LIS->getInstructionFromIndex(GlobalSegment->start);
189609467b48Spatrick   if (!GlobalDef)
189709467b48Spatrick     return;
189809467b48Spatrick 
189909467b48Spatrick   SUnit *GlobalSU = DAG->getSUnit(GlobalDef);
190009467b48Spatrick   if (!GlobalSU)
190109467b48Spatrick     return;
190209467b48Spatrick 
190309467b48Spatrick   // GlobalDef is the bottom of the GlobalLI hole. Open the hole by
190409467b48Spatrick   // constraining the uses of the last local def to precede GlobalDef.
190509467b48Spatrick   SmallVector<SUnit*,8> LocalUses;
190609467b48Spatrick   const VNInfo *LastLocalVN = LocalLI->getVNInfoBefore(LocalLI->endIndex());
190709467b48Spatrick   MachineInstr *LastLocalDef = LIS->getInstructionFromIndex(LastLocalVN->def);
190809467b48Spatrick   SUnit *LastLocalSU = DAG->getSUnit(LastLocalDef);
190909467b48Spatrick   for (const SDep &Succ : LastLocalSU->Succs) {
191009467b48Spatrick     if (Succ.getKind() != SDep::Data || Succ.getReg() != LocalReg)
191109467b48Spatrick       continue;
191209467b48Spatrick     if (Succ.getSUnit() == GlobalSU)
191309467b48Spatrick       continue;
191409467b48Spatrick     if (!DAG->canAddEdge(GlobalSU, Succ.getSUnit()))
191509467b48Spatrick       return;
191609467b48Spatrick     LocalUses.push_back(Succ.getSUnit());
191709467b48Spatrick   }
191809467b48Spatrick   // Open the top of the GlobalLI hole by constraining any earlier global uses
191909467b48Spatrick   // to precede the start of LocalLI.
192009467b48Spatrick   SmallVector<SUnit*,8> GlobalUses;
192109467b48Spatrick   MachineInstr *FirstLocalDef =
192209467b48Spatrick     LIS->getInstructionFromIndex(LocalLI->beginIndex());
192309467b48Spatrick   SUnit *FirstLocalSU = DAG->getSUnit(FirstLocalDef);
192409467b48Spatrick   for (const SDep &Pred : GlobalSU->Preds) {
192509467b48Spatrick     if (Pred.getKind() != SDep::Anti || Pred.getReg() != GlobalReg)
192609467b48Spatrick       continue;
192709467b48Spatrick     if (Pred.getSUnit() == FirstLocalSU)
192809467b48Spatrick       continue;
192909467b48Spatrick     if (!DAG->canAddEdge(FirstLocalSU, Pred.getSUnit()))
193009467b48Spatrick       return;
193109467b48Spatrick     GlobalUses.push_back(Pred.getSUnit());
193209467b48Spatrick   }
193309467b48Spatrick   LLVM_DEBUG(dbgs() << "Constraining copy SU(" << CopySU->NodeNum << ")\n");
193409467b48Spatrick   // Add the weak edges.
193573471bf0Spatrick   for (SUnit *LU : LocalUses) {
193673471bf0Spatrick     LLVM_DEBUG(dbgs() << "  Local use SU(" << LU->NodeNum << ") -> SU("
193709467b48Spatrick                       << GlobalSU->NodeNum << ")\n");
193873471bf0Spatrick     DAG->addEdge(GlobalSU, SDep(LU, SDep::Weak));
193909467b48Spatrick   }
194073471bf0Spatrick   for (SUnit *GU : GlobalUses) {
194173471bf0Spatrick     LLVM_DEBUG(dbgs() << "  Global use SU(" << GU->NodeNum << ") -> SU("
194209467b48Spatrick                       << FirstLocalSU->NodeNum << ")\n");
194373471bf0Spatrick     DAG->addEdge(FirstLocalSU, SDep(GU, SDep::Weak));
194409467b48Spatrick   }
194509467b48Spatrick }
194609467b48Spatrick 
194709467b48Spatrick /// Callback from DAG postProcessing to create weak edges to encourage
194809467b48Spatrick /// copy elimination.
apply(ScheduleDAGInstrs * DAGInstrs)194909467b48Spatrick void CopyConstrain::apply(ScheduleDAGInstrs *DAGInstrs) {
195009467b48Spatrick   ScheduleDAGMI *DAG = static_cast<ScheduleDAGMI*>(DAGInstrs);
195109467b48Spatrick   assert(DAG->hasVRegLiveness() && "Expect VRegs with LiveIntervals");
195209467b48Spatrick 
195309467b48Spatrick   MachineBasicBlock::iterator FirstPos = nextIfDebug(DAG->begin(), DAG->end());
195409467b48Spatrick   if (FirstPos == DAG->end())
195509467b48Spatrick     return;
195609467b48Spatrick   RegionBeginIdx = DAG->getLIS()->getInstructionIndex(*FirstPos);
195709467b48Spatrick   RegionEndIdx = DAG->getLIS()->getInstructionIndex(
195809467b48Spatrick       *priorNonDebug(DAG->end(), DAG->begin()));
195909467b48Spatrick 
196009467b48Spatrick   for (SUnit &SU : DAG->SUnits) {
196109467b48Spatrick     if (!SU.getInstr()->isCopy())
196209467b48Spatrick       continue;
196309467b48Spatrick 
196409467b48Spatrick     constrainLocalCopy(&SU, static_cast<ScheduleDAGMILive*>(DAG));
196509467b48Spatrick   }
196609467b48Spatrick }
196709467b48Spatrick 
196809467b48Spatrick //===----------------------------------------------------------------------===//
196909467b48Spatrick // MachineSchedStrategy helpers used by GenericScheduler, GenericPostScheduler
197009467b48Spatrick // and possibly other custom schedulers.
197109467b48Spatrick //===----------------------------------------------------------------------===//
197209467b48Spatrick 
197309467b48Spatrick static const unsigned InvalidCycle = ~0U;
197409467b48Spatrick 
~SchedBoundary()197509467b48Spatrick SchedBoundary::~SchedBoundary() { delete HazardRec; }
197609467b48Spatrick 
197709467b48Spatrick /// Given a Count of resource usage and a Latency value, return true if a
197809467b48Spatrick /// SchedBoundary becomes resource limited.
197909467b48Spatrick /// If we are checking after scheduling a node, we should return true when
198009467b48Spatrick /// we just reach the resource limit.
checkResourceLimit(unsigned LFactor,unsigned Count,unsigned Latency,bool AfterSchedNode)198109467b48Spatrick static bool checkResourceLimit(unsigned LFactor, unsigned Count,
198209467b48Spatrick                                unsigned Latency, bool AfterSchedNode) {
198309467b48Spatrick   int ResCntFactor = (int)(Count - (Latency * LFactor));
198409467b48Spatrick   if (AfterSchedNode)
198509467b48Spatrick     return ResCntFactor >= (int)LFactor;
198609467b48Spatrick   else
198709467b48Spatrick     return ResCntFactor > (int)LFactor;
198809467b48Spatrick }
198909467b48Spatrick 
reset()199009467b48Spatrick void SchedBoundary::reset() {
199109467b48Spatrick   // A new HazardRec is created for each DAG and owned by SchedBoundary.
199209467b48Spatrick   // Destroying and reconstructing it is very expensive though. So keep
199309467b48Spatrick   // invalid, placeholder HazardRecs.
199409467b48Spatrick   if (HazardRec && HazardRec->isEnabled()) {
199509467b48Spatrick     delete HazardRec;
199609467b48Spatrick     HazardRec = nullptr;
199709467b48Spatrick   }
199809467b48Spatrick   Available.clear();
199909467b48Spatrick   Pending.clear();
200009467b48Spatrick   CheckPending = false;
200109467b48Spatrick   CurrCycle = 0;
200209467b48Spatrick   CurrMOps = 0;
200309467b48Spatrick   MinReadyCycle = std::numeric_limits<unsigned>::max();
200409467b48Spatrick   ExpectedLatency = 0;
200509467b48Spatrick   DependentLatency = 0;
200609467b48Spatrick   RetiredMOps = 0;
200709467b48Spatrick   MaxExecutedResCount = 0;
200809467b48Spatrick   ZoneCritResIdx = 0;
200909467b48Spatrick   IsResourceLimited = false;
201009467b48Spatrick   ReservedCycles.clear();
201109467b48Spatrick   ReservedCyclesIndex.clear();
201273471bf0Spatrick   ResourceGroupSubUnitMasks.clear();
2013*d415bd75Srobert #if LLVM_ENABLE_ABI_BREAKING_CHECKS
201409467b48Spatrick   // Track the maximum number of stall cycles that could arise either from the
201509467b48Spatrick   // latency of a DAG edge or the number of cycles that a processor resource is
201609467b48Spatrick   // reserved (SchedBoundary::ReservedCycles).
201709467b48Spatrick   MaxObservedStall = 0;
201809467b48Spatrick #endif
201909467b48Spatrick   // Reserve a zero-count for invalid CritResIdx.
202009467b48Spatrick   ExecutedResCounts.resize(1);
202109467b48Spatrick   assert(!ExecutedResCounts[0] && "nonzero count for bad resource");
202209467b48Spatrick }
202309467b48Spatrick 
202409467b48Spatrick void SchedRemainder::
init(ScheduleDAGMI * DAG,const TargetSchedModel * SchedModel)202509467b48Spatrick init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel) {
202609467b48Spatrick   reset();
202709467b48Spatrick   if (!SchedModel->hasInstrSchedModel())
202809467b48Spatrick     return;
202909467b48Spatrick   RemainingCounts.resize(SchedModel->getNumProcResourceKinds());
203009467b48Spatrick   for (SUnit &SU : DAG->SUnits) {
203109467b48Spatrick     const MCSchedClassDesc *SC = DAG->getSchedClass(&SU);
203209467b48Spatrick     RemIssueCount += SchedModel->getNumMicroOps(SU.getInstr(), SC)
203309467b48Spatrick       * SchedModel->getMicroOpFactor();
203409467b48Spatrick     for (TargetSchedModel::ProcResIter
203509467b48Spatrick            PI = SchedModel->getWriteProcResBegin(SC),
203609467b48Spatrick            PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
203709467b48Spatrick       unsigned PIdx = PI->ProcResourceIdx;
203809467b48Spatrick       unsigned Factor = SchedModel->getResourceFactor(PIdx);
203909467b48Spatrick       RemainingCounts[PIdx] += (Factor * PI->Cycles);
204009467b48Spatrick     }
204109467b48Spatrick   }
204209467b48Spatrick }
204309467b48Spatrick 
204409467b48Spatrick void SchedBoundary::
init(ScheduleDAGMI * dag,const TargetSchedModel * smodel,SchedRemainder * rem)204509467b48Spatrick init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem) {
204609467b48Spatrick   reset();
204709467b48Spatrick   DAG = dag;
204809467b48Spatrick   SchedModel = smodel;
204909467b48Spatrick   Rem = rem;
205009467b48Spatrick   if (SchedModel->hasInstrSchedModel()) {
205109467b48Spatrick     unsigned ResourceCount = SchedModel->getNumProcResourceKinds();
205209467b48Spatrick     ReservedCyclesIndex.resize(ResourceCount);
205309467b48Spatrick     ExecutedResCounts.resize(ResourceCount);
205473471bf0Spatrick     ResourceGroupSubUnitMasks.resize(ResourceCount, APInt(ResourceCount, 0));
205509467b48Spatrick     unsigned NumUnits = 0;
205609467b48Spatrick 
205709467b48Spatrick     for (unsigned i = 0; i < ResourceCount; ++i) {
205809467b48Spatrick       ReservedCyclesIndex[i] = NumUnits;
205909467b48Spatrick       NumUnits += SchedModel->getProcResource(i)->NumUnits;
206073471bf0Spatrick       if (isUnbufferedGroup(i)) {
206173471bf0Spatrick         auto SubUnits = SchedModel->getProcResource(i)->SubUnitsIdxBegin;
206273471bf0Spatrick         for (unsigned U = 0, UE = SchedModel->getProcResource(i)->NumUnits;
206373471bf0Spatrick              U != UE; ++U)
206473471bf0Spatrick           ResourceGroupSubUnitMasks[i].setBit(SubUnits[U]);
206573471bf0Spatrick       }
206609467b48Spatrick     }
206709467b48Spatrick 
206809467b48Spatrick     ReservedCycles.resize(NumUnits, InvalidCycle);
206909467b48Spatrick   }
207009467b48Spatrick }
207109467b48Spatrick 
207209467b48Spatrick /// Compute the stall cycles based on this SUnit's ready time. Heuristics treat
207309467b48Spatrick /// these "soft stalls" differently than the hard stall cycles based on CPU
207409467b48Spatrick /// resources and computed by checkHazard(). A fully in-order model
207509467b48Spatrick /// (MicroOpBufferSize==0) will not make use of this since instructions are not
207609467b48Spatrick /// available for scheduling until they are ready. However, a weaker in-order
207709467b48Spatrick /// model may use this for heuristics. For example, if a processor has in-order
207809467b48Spatrick /// behavior when reading certain resources, this may come into play.
getLatencyStallCycles(SUnit * SU)207909467b48Spatrick unsigned SchedBoundary::getLatencyStallCycles(SUnit *SU) {
208009467b48Spatrick   if (!SU->isUnbuffered)
208109467b48Spatrick     return 0;
208209467b48Spatrick 
208309467b48Spatrick   unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
208409467b48Spatrick   if (ReadyCycle > CurrCycle)
208509467b48Spatrick     return ReadyCycle - CurrCycle;
208609467b48Spatrick   return 0;
208709467b48Spatrick }
208809467b48Spatrick 
208909467b48Spatrick /// Compute the next cycle at which the given processor resource unit
209009467b48Spatrick /// can be scheduled.
getNextResourceCycleByInstance(unsigned InstanceIdx,unsigned Cycles)209109467b48Spatrick unsigned SchedBoundary::getNextResourceCycleByInstance(unsigned InstanceIdx,
209209467b48Spatrick                                                        unsigned Cycles) {
209309467b48Spatrick   unsigned NextUnreserved = ReservedCycles[InstanceIdx];
209409467b48Spatrick   // If this resource has never been used, always return cycle zero.
209509467b48Spatrick   if (NextUnreserved == InvalidCycle)
209609467b48Spatrick     return 0;
209709467b48Spatrick   // For bottom-up scheduling add the cycles needed for the current operation.
209809467b48Spatrick   if (!isTop())
209909467b48Spatrick     NextUnreserved += Cycles;
210009467b48Spatrick   return NextUnreserved;
210109467b48Spatrick }
210209467b48Spatrick 
210309467b48Spatrick /// Compute the next cycle at which the given processor resource can be
210409467b48Spatrick /// scheduled.  Returns the next cycle and the index of the processor resource
210509467b48Spatrick /// instance in the reserved cycles vector.
210609467b48Spatrick std::pair<unsigned, unsigned>
getNextResourceCycle(const MCSchedClassDesc * SC,unsigned PIdx,unsigned Cycles)210773471bf0Spatrick SchedBoundary::getNextResourceCycle(const MCSchedClassDesc *SC, unsigned PIdx,
210873471bf0Spatrick                                     unsigned Cycles) {
210973471bf0Spatrick 
211009467b48Spatrick   unsigned MinNextUnreserved = InvalidCycle;
211109467b48Spatrick   unsigned InstanceIdx = 0;
211209467b48Spatrick   unsigned StartIndex = ReservedCyclesIndex[PIdx];
211309467b48Spatrick   unsigned NumberOfInstances = SchedModel->getProcResource(PIdx)->NumUnits;
211409467b48Spatrick   assert(NumberOfInstances > 0 &&
211509467b48Spatrick          "Cannot have zero instances of a ProcResource");
211609467b48Spatrick 
211773471bf0Spatrick   if (isUnbufferedGroup(PIdx)) {
211873471bf0Spatrick     // If any subunits are used by the instruction, report that the resource
211973471bf0Spatrick     // group is available at 0, effectively removing the group record from
212073471bf0Spatrick     // hazarding and basing the hazarding decisions on the subunit records.
212173471bf0Spatrick     // Otherwise, choose the first available instance from among the subunits.
212273471bf0Spatrick     // Specifications which assign cycles to both the subunits and the group or
212373471bf0Spatrick     // which use an unbuffered group with buffered subunits will appear to
212473471bf0Spatrick     // schedule strangely. In the first case, the additional cycles for the
212573471bf0Spatrick     // group will be ignored.  In the second, the group will be ignored
212673471bf0Spatrick     // entirely.
212773471bf0Spatrick     for (const MCWriteProcResEntry &PE :
212873471bf0Spatrick          make_range(SchedModel->getWriteProcResBegin(SC),
212973471bf0Spatrick                     SchedModel->getWriteProcResEnd(SC)))
213073471bf0Spatrick       if (ResourceGroupSubUnitMasks[PIdx][PE.ProcResourceIdx])
213173471bf0Spatrick         return std::make_pair(0u, StartIndex);
213273471bf0Spatrick 
213373471bf0Spatrick     auto SubUnits = SchedModel->getProcResource(PIdx)->SubUnitsIdxBegin;
213473471bf0Spatrick     for (unsigned I = 0, End = NumberOfInstances; I < End; ++I) {
213573471bf0Spatrick       unsigned NextUnreserved, NextInstanceIdx;
213673471bf0Spatrick       std::tie(NextUnreserved, NextInstanceIdx) =
213773471bf0Spatrick           getNextResourceCycle(SC, SubUnits[I], Cycles);
213873471bf0Spatrick       if (MinNextUnreserved > NextUnreserved) {
213973471bf0Spatrick         InstanceIdx = NextInstanceIdx;
214073471bf0Spatrick         MinNextUnreserved = NextUnreserved;
214173471bf0Spatrick       }
214273471bf0Spatrick     }
214373471bf0Spatrick     return std::make_pair(MinNextUnreserved, InstanceIdx);
214473471bf0Spatrick   }
214573471bf0Spatrick 
214609467b48Spatrick   for (unsigned I = StartIndex, End = StartIndex + NumberOfInstances; I < End;
214709467b48Spatrick        ++I) {
214809467b48Spatrick     unsigned NextUnreserved = getNextResourceCycleByInstance(I, Cycles);
214909467b48Spatrick     if (MinNextUnreserved > NextUnreserved) {
215009467b48Spatrick       InstanceIdx = I;
215109467b48Spatrick       MinNextUnreserved = NextUnreserved;
215209467b48Spatrick     }
215309467b48Spatrick   }
215409467b48Spatrick   return std::make_pair(MinNextUnreserved, InstanceIdx);
215509467b48Spatrick }
215609467b48Spatrick 
215709467b48Spatrick /// Does this SU have a hazard within the current instruction group.
215809467b48Spatrick ///
215909467b48Spatrick /// The scheduler supports two modes of hazard recognition. The first is the
216009467b48Spatrick /// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
216109467b48Spatrick /// supports highly complicated in-order reservation tables
216209467b48Spatrick /// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
216309467b48Spatrick ///
216409467b48Spatrick /// The second is a streamlined mechanism that checks for hazards based on
216509467b48Spatrick /// simple counters that the scheduler itself maintains. It explicitly checks
216609467b48Spatrick /// for instruction dispatch limitations, including the number of micro-ops that
216709467b48Spatrick /// can dispatch per cycle.
216809467b48Spatrick ///
216909467b48Spatrick /// TODO: Also check whether the SU must start a new group.
checkHazard(SUnit * SU)217009467b48Spatrick bool SchedBoundary::checkHazard(SUnit *SU) {
217109467b48Spatrick   if (HazardRec->isEnabled()
217209467b48Spatrick       && HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard) {
217309467b48Spatrick     return true;
217409467b48Spatrick   }
217509467b48Spatrick 
217609467b48Spatrick   unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
217709467b48Spatrick   if ((CurrMOps > 0) && (CurrMOps + uops > SchedModel->getIssueWidth())) {
217809467b48Spatrick     LLVM_DEBUG(dbgs() << "  SU(" << SU->NodeNum << ") uops="
217909467b48Spatrick                       << SchedModel->getNumMicroOps(SU->getInstr()) << '\n');
218009467b48Spatrick     return true;
218109467b48Spatrick   }
218209467b48Spatrick 
218309467b48Spatrick   if (CurrMOps > 0 &&
218409467b48Spatrick       ((isTop() && SchedModel->mustBeginGroup(SU->getInstr())) ||
218509467b48Spatrick        (!isTop() && SchedModel->mustEndGroup(SU->getInstr())))) {
218609467b48Spatrick     LLVM_DEBUG(dbgs() << "  hazard: SU(" << SU->NodeNum << ") must "
218709467b48Spatrick                       << (isTop() ? "begin" : "end") << " group\n");
218809467b48Spatrick     return true;
218909467b48Spatrick   }
219009467b48Spatrick 
219109467b48Spatrick   if (SchedModel->hasInstrSchedModel() && SU->hasReservedResource) {
219209467b48Spatrick     const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
219309467b48Spatrick     for (const MCWriteProcResEntry &PE :
219409467b48Spatrick           make_range(SchedModel->getWriteProcResBegin(SC),
219509467b48Spatrick                      SchedModel->getWriteProcResEnd(SC))) {
219609467b48Spatrick       unsigned ResIdx = PE.ProcResourceIdx;
219709467b48Spatrick       unsigned Cycles = PE.Cycles;
219809467b48Spatrick       unsigned NRCycle, InstanceIdx;
219973471bf0Spatrick       std::tie(NRCycle, InstanceIdx) = getNextResourceCycle(SC, ResIdx, Cycles);
220009467b48Spatrick       if (NRCycle > CurrCycle) {
2201*d415bd75Srobert #if LLVM_ENABLE_ABI_BREAKING_CHECKS
220209467b48Spatrick         MaxObservedStall = std::max(Cycles, MaxObservedStall);
220309467b48Spatrick #endif
220409467b48Spatrick         LLVM_DEBUG(dbgs() << "  SU(" << SU->NodeNum << ") "
220509467b48Spatrick                           << SchedModel->getResourceName(ResIdx)
220609467b48Spatrick                           << '[' << InstanceIdx - ReservedCyclesIndex[ResIdx]  << ']'
220709467b48Spatrick                           << "=" << NRCycle << "c\n");
220809467b48Spatrick         return true;
220909467b48Spatrick       }
221009467b48Spatrick     }
221109467b48Spatrick   }
221209467b48Spatrick   return false;
221309467b48Spatrick }
221409467b48Spatrick 
221509467b48Spatrick // Find the unscheduled node in ReadySUs with the highest latency.
221609467b48Spatrick unsigned SchedBoundary::
findMaxLatency(ArrayRef<SUnit * > ReadySUs)221709467b48Spatrick findMaxLatency(ArrayRef<SUnit*> ReadySUs) {
221809467b48Spatrick   SUnit *LateSU = nullptr;
221909467b48Spatrick   unsigned RemLatency = 0;
222009467b48Spatrick   for (SUnit *SU : ReadySUs) {
222109467b48Spatrick     unsigned L = getUnscheduledLatency(SU);
222209467b48Spatrick     if (L > RemLatency) {
222309467b48Spatrick       RemLatency = L;
222409467b48Spatrick       LateSU = SU;
222509467b48Spatrick     }
222609467b48Spatrick   }
222709467b48Spatrick   if (LateSU) {
222809467b48Spatrick     LLVM_DEBUG(dbgs() << Available.getName() << " RemLatency SU("
222909467b48Spatrick                       << LateSU->NodeNum << ") " << RemLatency << "c\n");
223009467b48Spatrick   }
223109467b48Spatrick   return RemLatency;
223209467b48Spatrick }
223309467b48Spatrick 
223409467b48Spatrick // Count resources in this zone and the remaining unscheduled
223509467b48Spatrick // instruction. Return the max count, scaled. Set OtherCritIdx to the critical
223609467b48Spatrick // resource index, or zero if the zone is issue limited.
223709467b48Spatrick unsigned SchedBoundary::
getOtherResourceCount(unsigned & OtherCritIdx)223809467b48Spatrick getOtherResourceCount(unsigned &OtherCritIdx) {
223909467b48Spatrick   OtherCritIdx = 0;
224009467b48Spatrick   if (!SchedModel->hasInstrSchedModel())
224109467b48Spatrick     return 0;
224209467b48Spatrick 
224309467b48Spatrick   unsigned OtherCritCount = Rem->RemIssueCount
224409467b48Spatrick     + (RetiredMOps * SchedModel->getMicroOpFactor());
224509467b48Spatrick   LLVM_DEBUG(dbgs() << "  " << Available.getName() << " + Remain MOps: "
224609467b48Spatrick                     << OtherCritCount / SchedModel->getMicroOpFactor() << '\n');
224709467b48Spatrick   for (unsigned PIdx = 1, PEnd = SchedModel->getNumProcResourceKinds();
224809467b48Spatrick        PIdx != PEnd; ++PIdx) {
224909467b48Spatrick     unsigned OtherCount = getResourceCount(PIdx) + Rem->RemainingCounts[PIdx];
225009467b48Spatrick     if (OtherCount > OtherCritCount) {
225109467b48Spatrick       OtherCritCount = OtherCount;
225209467b48Spatrick       OtherCritIdx = PIdx;
225309467b48Spatrick     }
225409467b48Spatrick   }
225509467b48Spatrick   if (OtherCritIdx) {
225609467b48Spatrick     LLVM_DEBUG(
225709467b48Spatrick         dbgs() << "  " << Available.getName() << " + Remain CritRes: "
225809467b48Spatrick                << OtherCritCount / SchedModel->getResourceFactor(OtherCritIdx)
225909467b48Spatrick                << " " << SchedModel->getResourceName(OtherCritIdx) << "\n");
226009467b48Spatrick   }
226109467b48Spatrick   return OtherCritCount;
226209467b48Spatrick }
226309467b48Spatrick 
releaseNode(SUnit * SU,unsigned ReadyCycle,bool InPQueue,unsigned Idx)226409467b48Spatrick void SchedBoundary::releaseNode(SUnit *SU, unsigned ReadyCycle, bool InPQueue,
226509467b48Spatrick                                 unsigned Idx) {
226609467b48Spatrick   assert(SU->getInstr() && "Scheduled SUnit must have instr");
226709467b48Spatrick 
2268*d415bd75Srobert #if LLVM_ENABLE_ABI_BREAKING_CHECKS
226909467b48Spatrick   // ReadyCycle was been bumped up to the CurrCycle when this node was
227009467b48Spatrick   // scheduled, but CurrCycle may have been eagerly advanced immediately after
227109467b48Spatrick   // scheduling, so may now be greater than ReadyCycle.
227209467b48Spatrick   if (ReadyCycle > CurrCycle)
227309467b48Spatrick     MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
227409467b48Spatrick #endif
227509467b48Spatrick 
227609467b48Spatrick   if (ReadyCycle < MinReadyCycle)
227709467b48Spatrick     MinReadyCycle = ReadyCycle;
227809467b48Spatrick 
227909467b48Spatrick   // Check for interlocks first. For the purpose of other heuristics, an
228009467b48Spatrick   // instruction that cannot issue appears as if it's not in the ReadyQueue.
228109467b48Spatrick   bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
228209467b48Spatrick   bool HazardDetected = (!IsBuffered && ReadyCycle > CurrCycle) ||
228309467b48Spatrick                         checkHazard(SU) || (Available.size() >= ReadyListLimit);
228409467b48Spatrick 
228509467b48Spatrick   if (!HazardDetected) {
228609467b48Spatrick     Available.push(SU);
228709467b48Spatrick 
228809467b48Spatrick     if (InPQueue)
228909467b48Spatrick       Pending.remove(Pending.begin() + Idx);
229009467b48Spatrick     return;
229109467b48Spatrick   }
229209467b48Spatrick 
229309467b48Spatrick   if (!InPQueue)
229409467b48Spatrick     Pending.push(SU);
229509467b48Spatrick }
229609467b48Spatrick 
229709467b48Spatrick /// Move the boundary of scheduled code by one cycle.
bumpCycle(unsigned NextCycle)229809467b48Spatrick void SchedBoundary::bumpCycle(unsigned NextCycle) {
229909467b48Spatrick   if (SchedModel->getMicroOpBufferSize() == 0) {
230009467b48Spatrick     assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
230109467b48Spatrick            "MinReadyCycle uninitialized");
230209467b48Spatrick     if (MinReadyCycle > NextCycle)
230309467b48Spatrick       NextCycle = MinReadyCycle;
230409467b48Spatrick   }
230509467b48Spatrick   // Update the current micro-ops, which will issue in the next cycle.
230609467b48Spatrick   unsigned DecMOps = SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
230709467b48Spatrick   CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
230809467b48Spatrick 
230909467b48Spatrick   // Decrement DependentLatency based on the next cycle.
231009467b48Spatrick   if ((NextCycle - CurrCycle) > DependentLatency)
231109467b48Spatrick     DependentLatency = 0;
231209467b48Spatrick   else
231309467b48Spatrick     DependentLatency -= (NextCycle - CurrCycle);
231409467b48Spatrick 
231509467b48Spatrick   if (!HazardRec->isEnabled()) {
231609467b48Spatrick     // Bypass HazardRec virtual calls.
231709467b48Spatrick     CurrCycle = NextCycle;
231809467b48Spatrick   } else {
231909467b48Spatrick     // Bypass getHazardType calls in case of long latency.
232009467b48Spatrick     for (; CurrCycle != NextCycle; ++CurrCycle) {
232109467b48Spatrick       if (isTop())
232209467b48Spatrick         HazardRec->AdvanceCycle();
232309467b48Spatrick       else
232409467b48Spatrick         HazardRec->RecedeCycle();
232509467b48Spatrick     }
232609467b48Spatrick   }
232709467b48Spatrick   CheckPending = true;
232809467b48Spatrick   IsResourceLimited =
232909467b48Spatrick       checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
233009467b48Spatrick                          getScheduledLatency(), true);
233109467b48Spatrick 
233209467b48Spatrick   LLVM_DEBUG(dbgs() << "Cycle: " << CurrCycle << ' ' << Available.getName()
233309467b48Spatrick                     << '\n');
233409467b48Spatrick }
233509467b48Spatrick 
incExecutedResources(unsigned PIdx,unsigned Count)233609467b48Spatrick void SchedBoundary::incExecutedResources(unsigned PIdx, unsigned Count) {
233709467b48Spatrick   ExecutedResCounts[PIdx] += Count;
233809467b48Spatrick   if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
233909467b48Spatrick     MaxExecutedResCount = ExecutedResCounts[PIdx];
234009467b48Spatrick }
234109467b48Spatrick 
234209467b48Spatrick /// Add the given processor resource to this scheduled zone.
234309467b48Spatrick ///
234409467b48Spatrick /// \param Cycles indicates the number of consecutive (non-pipelined) cycles
234509467b48Spatrick /// during which this resource is consumed.
234609467b48Spatrick ///
234709467b48Spatrick /// \return the next cycle at which the instruction may execute without
234809467b48Spatrick /// oversubscribing resources.
countResource(const MCSchedClassDesc * SC,unsigned PIdx,unsigned Cycles,unsigned NextCycle)234973471bf0Spatrick unsigned SchedBoundary::countResource(const MCSchedClassDesc *SC, unsigned PIdx,
235073471bf0Spatrick                                       unsigned Cycles, unsigned NextCycle) {
235109467b48Spatrick   unsigned Factor = SchedModel->getResourceFactor(PIdx);
235209467b48Spatrick   unsigned Count = Factor * Cycles;
235309467b48Spatrick   LLVM_DEBUG(dbgs() << "  " << SchedModel->getResourceName(PIdx) << " +"
235409467b48Spatrick                     << Cycles << "x" << Factor << "u\n");
235509467b48Spatrick 
235609467b48Spatrick   // Update Executed resources counts.
235709467b48Spatrick   incExecutedResources(PIdx, Count);
235809467b48Spatrick   assert(Rem->RemainingCounts[PIdx] >= Count && "resource double counted");
235909467b48Spatrick   Rem->RemainingCounts[PIdx] -= Count;
236009467b48Spatrick 
236109467b48Spatrick   // Check if this resource exceeds the current critical resource. If so, it
236209467b48Spatrick   // becomes the critical resource.
236309467b48Spatrick   if (ZoneCritResIdx != PIdx && (getResourceCount(PIdx) > getCriticalCount())) {
236409467b48Spatrick     ZoneCritResIdx = PIdx;
236509467b48Spatrick     LLVM_DEBUG(dbgs() << "  *** Critical resource "
236609467b48Spatrick                       << SchedModel->getResourceName(PIdx) << ": "
236709467b48Spatrick                       << getResourceCount(PIdx) / SchedModel->getLatencyFactor()
236809467b48Spatrick                       << "c\n");
236909467b48Spatrick   }
237009467b48Spatrick   // For reserved resources, record the highest cycle using the resource.
237109467b48Spatrick   unsigned NextAvailable, InstanceIdx;
237273471bf0Spatrick   std::tie(NextAvailable, InstanceIdx) = getNextResourceCycle(SC, PIdx, Cycles);
237309467b48Spatrick   if (NextAvailable > CurrCycle) {
237409467b48Spatrick     LLVM_DEBUG(dbgs() << "  Resource conflict: "
237509467b48Spatrick                       << SchedModel->getResourceName(PIdx)
237609467b48Spatrick                       << '[' << InstanceIdx - ReservedCyclesIndex[PIdx]  << ']'
237709467b48Spatrick                       << " reserved until @" << NextAvailable << "\n");
237809467b48Spatrick   }
237909467b48Spatrick   return NextAvailable;
238009467b48Spatrick }
238109467b48Spatrick 
238209467b48Spatrick /// Move the boundary of scheduled code by one SUnit.
bumpNode(SUnit * SU)238309467b48Spatrick void SchedBoundary::bumpNode(SUnit *SU) {
238409467b48Spatrick   // Update the reservation table.
238509467b48Spatrick   if (HazardRec->isEnabled()) {
238609467b48Spatrick     if (!isTop() && SU->isCall) {
238709467b48Spatrick       // Calls are scheduled with their preceding instructions. For bottom-up
238809467b48Spatrick       // scheduling, clear the pipeline state before emitting.
238909467b48Spatrick       HazardRec->Reset();
239009467b48Spatrick     }
239109467b48Spatrick     HazardRec->EmitInstruction(SU);
239209467b48Spatrick     // Scheduling an instruction may have made pending instructions available.
239309467b48Spatrick     CheckPending = true;
239409467b48Spatrick   }
239509467b48Spatrick   // checkHazard should prevent scheduling multiple instructions per cycle that
239609467b48Spatrick   // exceed the issue width.
239709467b48Spatrick   const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
239809467b48Spatrick   unsigned IncMOps = SchedModel->getNumMicroOps(SU->getInstr());
239909467b48Spatrick   assert(
240009467b48Spatrick       (CurrMOps == 0 || (CurrMOps + IncMOps) <= SchedModel->getIssueWidth()) &&
240109467b48Spatrick       "Cannot schedule this instruction's MicroOps in the current cycle.");
240209467b48Spatrick 
240309467b48Spatrick   unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
240409467b48Spatrick   LLVM_DEBUG(dbgs() << "  Ready @" << ReadyCycle << "c\n");
240509467b48Spatrick 
240609467b48Spatrick   unsigned NextCycle = CurrCycle;
240709467b48Spatrick   switch (SchedModel->getMicroOpBufferSize()) {
240809467b48Spatrick   case 0:
240909467b48Spatrick     assert(ReadyCycle <= CurrCycle && "Broken PendingQueue");
241009467b48Spatrick     break;
241109467b48Spatrick   case 1:
241209467b48Spatrick     if (ReadyCycle > NextCycle) {
241309467b48Spatrick       NextCycle = ReadyCycle;
241409467b48Spatrick       LLVM_DEBUG(dbgs() << "  *** Stall until: " << ReadyCycle << "\n");
241509467b48Spatrick     }
241609467b48Spatrick     break;
241709467b48Spatrick   default:
241809467b48Spatrick     // We don't currently model the OOO reorder buffer, so consider all
241909467b48Spatrick     // scheduled MOps to be "retired". We do loosely model in-order resource
242009467b48Spatrick     // latency. If this instruction uses an in-order resource, account for any
242109467b48Spatrick     // likely stall cycles.
242209467b48Spatrick     if (SU->isUnbuffered && ReadyCycle > NextCycle)
242309467b48Spatrick       NextCycle = ReadyCycle;
242409467b48Spatrick     break;
242509467b48Spatrick   }
242609467b48Spatrick   RetiredMOps += IncMOps;
242709467b48Spatrick 
242809467b48Spatrick   // Update resource counts and critical resource.
242909467b48Spatrick   if (SchedModel->hasInstrSchedModel()) {
243009467b48Spatrick     unsigned DecRemIssue = IncMOps * SchedModel->getMicroOpFactor();
243109467b48Spatrick     assert(Rem->RemIssueCount >= DecRemIssue && "MOps double counted");
243209467b48Spatrick     Rem->RemIssueCount -= DecRemIssue;
243309467b48Spatrick     if (ZoneCritResIdx) {
243409467b48Spatrick       // Scale scheduled micro-ops for comparing with the critical resource.
243509467b48Spatrick       unsigned ScaledMOps =
243609467b48Spatrick         RetiredMOps * SchedModel->getMicroOpFactor();
243709467b48Spatrick 
243809467b48Spatrick       // If scaled micro-ops are now more than the previous critical resource by
243909467b48Spatrick       // a full cycle, then micro-ops issue becomes critical.
244009467b48Spatrick       if ((int)(ScaledMOps - getResourceCount(ZoneCritResIdx))
244109467b48Spatrick           >= (int)SchedModel->getLatencyFactor()) {
244209467b48Spatrick         ZoneCritResIdx = 0;
244309467b48Spatrick         LLVM_DEBUG(dbgs() << "  *** Critical resource NumMicroOps: "
244409467b48Spatrick                           << ScaledMOps / SchedModel->getLatencyFactor()
244509467b48Spatrick                           << "c\n");
244609467b48Spatrick       }
244709467b48Spatrick     }
244809467b48Spatrick     for (TargetSchedModel::ProcResIter
244909467b48Spatrick            PI = SchedModel->getWriteProcResBegin(SC),
245009467b48Spatrick            PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
245109467b48Spatrick       unsigned RCycle =
245273471bf0Spatrick         countResource(SC, PI->ProcResourceIdx, PI->Cycles, NextCycle);
245309467b48Spatrick       if (RCycle > NextCycle)
245409467b48Spatrick         NextCycle = RCycle;
245509467b48Spatrick     }
245609467b48Spatrick     if (SU->hasReservedResource) {
245709467b48Spatrick       // For reserved resources, record the highest cycle using the resource.
245809467b48Spatrick       // For top-down scheduling, this is the cycle in which we schedule this
245909467b48Spatrick       // instruction plus the number of cycles the operations reserves the
246009467b48Spatrick       // resource. For bottom-up is it simply the instruction's cycle.
246109467b48Spatrick       for (TargetSchedModel::ProcResIter
246209467b48Spatrick              PI = SchedModel->getWriteProcResBegin(SC),
246309467b48Spatrick              PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
246409467b48Spatrick         unsigned PIdx = PI->ProcResourceIdx;
246509467b48Spatrick         if (SchedModel->getProcResource(PIdx)->BufferSize == 0) {
246609467b48Spatrick           unsigned ReservedUntil, InstanceIdx;
246773471bf0Spatrick           std::tie(ReservedUntil, InstanceIdx) =
246873471bf0Spatrick               getNextResourceCycle(SC, PIdx, 0);
246909467b48Spatrick           if (isTop()) {
247009467b48Spatrick             ReservedCycles[InstanceIdx] =
247109467b48Spatrick                 std::max(ReservedUntil, NextCycle + PI->Cycles);
247209467b48Spatrick           } else
247309467b48Spatrick             ReservedCycles[InstanceIdx] = NextCycle;
247409467b48Spatrick         }
247509467b48Spatrick       }
247609467b48Spatrick     }
247709467b48Spatrick   }
247809467b48Spatrick   // Update ExpectedLatency and DependentLatency.
247909467b48Spatrick   unsigned &TopLatency = isTop() ? ExpectedLatency : DependentLatency;
248009467b48Spatrick   unsigned &BotLatency = isTop() ? DependentLatency : ExpectedLatency;
248109467b48Spatrick   if (SU->getDepth() > TopLatency) {
248209467b48Spatrick     TopLatency = SU->getDepth();
248309467b48Spatrick     LLVM_DEBUG(dbgs() << "  " << Available.getName() << " TopLatency SU("
248409467b48Spatrick                       << SU->NodeNum << ") " << TopLatency << "c\n");
248509467b48Spatrick   }
248609467b48Spatrick   if (SU->getHeight() > BotLatency) {
248709467b48Spatrick     BotLatency = SU->getHeight();
248809467b48Spatrick     LLVM_DEBUG(dbgs() << "  " << Available.getName() << " BotLatency SU("
248909467b48Spatrick                       << SU->NodeNum << ") " << BotLatency << "c\n");
249009467b48Spatrick   }
249109467b48Spatrick   // If we stall for any reason, bump the cycle.
249209467b48Spatrick   if (NextCycle > CurrCycle)
249309467b48Spatrick     bumpCycle(NextCycle);
249409467b48Spatrick   else
249509467b48Spatrick     // After updating ZoneCritResIdx and ExpectedLatency, check if we're
249609467b48Spatrick     // resource limited. If a stall occurred, bumpCycle does this.
249709467b48Spatrick     IsResourceLimited =
249809467b48Spatrick         checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
249909467b48Spatrick                            getScheduledLatency(), true);
250009467b48Spatrick 
250109467b48Spatrick   // Update CurrMOps after calling bumpCycle to handle stalls, since bumpCycle
250209467b48Spatrick   // resets CurrMOps. Loop to handle instructions with more MOps than issue in
250309467b48Spatrick   // one cycle.  Since we commonly reach the max MOps here, opportunistically
250409467b48Spatrick   // bump the cycle to avoid uselessly checking everything in the readyQ.
250509467b48Spatrick   CurrMOps += IncMOps;
250609467b48Spatrick 
250709467b48Spatrick   // Bump the cycle count for issue group constraints.
250809467b48Spatrick   // This must be done after NextCycle has been adjust for all other stalls.
250909467b48Spatrick   // Calling bumpCycle(X) will reduce CurrMOps by one issue group and set
251009467b48Spatrick   // currCycle to X.
251109467b48Spatrick   if ((isTop() &&  SchedModel->mustEndGroup(SU->getInstr())) ||
251209467b48Spatrick       (!isTop() && SchedModel->mustBeginGroup(SU->getInstr()))) {
251309467b48Spatrick     LLVM_DEBUG(dbgs() << "  Bump cycle to " << (isTop() ? "end" : "begin")
251409467b48Spatrick                       << " group\n");
251509467b48Spatrick     bumpCycle(++NextCycle);
251609467b48Spatrick   }
251709467b48Spatrick 
251809467b48Spatrick   while (CurrMOps >= SchedModel->getIssueWidth()) {
251909467b48Spatrick     LLVM_DEBUG(dbgs() << "  *** Max MOps " << CurrMOps << " at cycle "
252009467b48Spatrick                       << CurrCycle << '\n');
252109467b48Spatrick     bumpCycle(++NextCycle);
252209467b48Spatrick   }
252309467b48Spatrick   LLVM_DEBUG(dumpScheduledState());
252409467b48Spatrick }
252509467b48Spatrick 
252609467b48Spatrick /// Release pending ready nodes in to the available queue. This makes them
252709467b48Spatrick /// visible to heuristics.
releasePending()252809467b48Spatrick void SchedBoundary::releasePending() {
252909467b48Spatrick   // If the available queue is empty, it is safe to reset MinReadyCycle.
253009467b48Spatrick   if (Available.empty())
253109467b48Spatrick     MinReadyCycle = std::numeric_limits<unsigned>::max();
253209467b48Spatrick 
253309467b48Spatrick   // Check to see if any of the pending instructions are ready to issue.  If
253409467b48Spatrick   // so, add them to the available queue.
253509467b48Spatrick   for (unsigned I = 0, E = Pending.size(); I < E; ++I) {
253609467b48Spatrick     SUnit *SU = *(Pending.begin() + I);
253709467b48Spatrick     unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
253809467b48Spatrick 
253909467b48Spatrick     if (ReadyCycle < MinReadyCycle)
254009467b48Spatrick       MinReadyCycle = ReadyCycle;
254109467b48Spatrick 
254209467b48Spatrick     if (Available.size() >= ReadyListLimit)
254309467b48Spatrick       break;
254409467b48Spatrick 
254509467b48Spatrick     releaseNode(SU, ReadyCycle, true, I);
254609467b48Spatrick     if (E != Pending.size()) {
254709467b48Spatrick       --I;
254809467b48Spatrick       --E;
254909467b48Spatrick     }
255009467b48Spatrick   }
255109467b48Spatrick   CheckPending = false;
255209467b48Spatrick }
255309467b48Spatrick 
255409467b48Spatrick /// Remove SU from the ready set for this boundary.
removeReady(SUnit * SU)255509467b48Spatrick void SchedBoundary::removeReady(SUnit *SU) {
255609467b48Spatrick   if (Available.isInQueue(SU))
255709467b48Spatrick     Available.remove(Available.find(SU));
255809467b48Spatrick   else {
255909467b48Spatrick     assert(Pending.isInQueue(SU) && "bad ready count");
256009467b48Spatrick     Pending.remove(Pending.find(SU));
256109467b48Spatrick   }
256209467b48Spatrick }
256309467b48Spatrick 
256409467b48Spatrick /// If this queue only has one ready candidate, return it. As a side effect,
256509467b48Spatrick /// defer any nodes that now hit a hazard, and advance the cycle until at least
256609467b48Spatrick /// one node is ready. If multiple instructions are ready, return NULL.
pickOnlyChoice()256709467b48Spatrick SUnit *SchedBoundary::pickOnlyChoice() {
256809467b48Spatrick   if (CheckPending)
256909467b48Spatrick     releasePending();
257009467b48Spatrick 
257109467b48Spatrick   // Defer any ready instrs that now have a hazard.
257209467b48Spatrick   for (ReadyQueue::iterator I = Available.begin(); I != Available.end();) {
257309467b48Spatrick     if (checkHazard(*I)) {
257409467b48Spatrick       Pending.push(*I);
257509467b48Spatrick       I = Available.remove(I);
257609467b48Spatrick       continue;
257709467b48Spatrick     }
257809467b48Spatrick     ++I;
257909467b48Spatrick   }
258009467b48Spatrick   for (unsigned i = 0; Available.empty(); ++i) {
258109467b48Spatrick //  FIXME: Re-enable assert once PR20057 is resolved.
258209467b48Spatrick //    assert(i <= (HazardRec->getMaxLookAhead() + MaxObservedStall) &&
258309467b48Spatrick //           "permanent hazard");
258409467b48Spatrick     (void)i;
258509467b48Spatrick     bumpCycle(CurrCycle + 1);
258609467b48Spatrick     releasePending();
258709467b48Spatrick   }
258809467b48Spatrick 
258909467b48Spatrick   LLVM_DEBUG(Pending.dump());
259009467b48Spatrick   LLVM_DEBUG(Available.dump());
259109467b48Spatrick 
259209467b48Spatrick   if (Available.size() == 1)
259309467b48Spatrick     return *Available.begin();
259409467b48Spatrick   return nullptr;
259509467b48Spatrick }
259609467b48Spatrick 
259709467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
2598*d415bd75Srobert 
2599*d415bd75Srobert /// Dump the content of the \ref ReservedCycles vector for the
2600*d415bd75Srobert /// resources that are used in the basic block.
2601*d415bd75Srobert ///
dumpReservedCycles() const2602*d415bd75Srobert LLVM_DUMP_METHOD void SchedBoundary::dumpReservedCycles() const {
2603*d415bd75Srobert   if (!SchedModel->hasInstrSchedModel())
2604*d415bd75Srobert     return;
2605*d415bd75Srobert 
2606*d415bd75Srobert   unsigned ResourceCount = SchedModel->getNumProcResourceKinds();
2607*d415bd75Srobert   unsigned StartIdx = 0;
2608*d415bd75Srobert 
2609*d415bd75Srobert   for (unsigned ResIdx = 0; ResIdx < ResourceCount; ++ResIdx) {
2610*d415bd75Srobert     const unsigned NumUnits = SchedModel->getProcResource(ResIdx)->NumUnits;
2611*d415bd75Srobert     std::string ResName = SchedModel->getResourceName(ResIdx);
2612*d415bd75Srobert     for (unsigned UnitIdx = 0; UnitIdx < NumUnits; ++UnitIdx) {
2613*d415bd75Srobert       dbgs() << ResName << "(" << UnitIdx
2614*d415bd75Srobert              << ") = " << ReservedCycles[StartIdx + UnitIdx] << "\n";
2615*d415bd75Srobert     }
2616*d415bd75Srobert     StartIdx += NumUnits;
2617*d415bd75Srobert   }
2618*d415bd75Srobert }
2619*d415bd75Srobert 
262009467b48Spatrick // This is useful information to dump after bumpNode.
262109467b48Spatrick // Note that the Queue contents are more useful before pickNodeFromQueue.
dumpScheduledState() const262209467b48Spatrick LLVM_DUMP_METHOD void SchedBoundary::dumpScheduledState() const {
262309467b48Spatrick   unsigned ResFactor;
262409467b48Spatrick   unsigned ResCount;
262509467b48Spatrick   if (ZoneCritResIdx) {
262609467b48Spatrick     ResFactor = SchedModel->getResourceFactor(ZoneCritResIdx);
262709467b48Spatrick     ResCount = getResourceCount(ZoneCritResIdx);
262809467b48Spatrick   } else {
262909467b48Spatrick     ResFactor = SchedModel->getMicroOpFactor();
263009467b48Spatrick     ResCount = RetiredMOps * ResFactor;
263109467b48Spatrick   }
263209467b48Spatrick   unsigned LFactor = SchedModel->getLatencyFactor();
263309467b48Spatrick   dbgs() << Available.getName() << " @" << CurrCycle << "c\n"
263409467b48Spatrick          << "  Retired: " << RetiredMOps;
263509467b48Spatrick   dbgs() << "\n  Executed: " << getExecutedCount() / LFactor << "c";
263609467b48Spatrick   dbgs() << "\n  Critical: " << ResCount / LFactor << "c, "
263709467b48Spatrick          << ResCount / ResFactor << " "
263809467b48Spatrick          << SchedModel->getResourceName(ZoneCritResIdx)
263909467b48Spatrick          << "\n  ExpectedLatency: " << ExpectedLatency << "c\n"
264009467b48Spatrick          << (IsResourceLimited ? "  - Resource" : "  - Latency")
264109467b48Spatrick          << " limited.\n";
2642*d415bd75Srobert   if (MISchedDumpReservedCycles)
2643*d415bd75Srobert     dumpReservedCycles();
264409467b48Spatrick }
264509467b48Spatrick #endif
264609467b48Spatrick 
264709467b48Spatrick //===----------------------------------------------------------------------===//
264809467b48Spatrick // GenericScheduler - Generic implementation of MachineSchedStrategy.
264909467b48Spatrick //===----------------------------------------------------------------------===//
265009467b48Spatrick 
265109467b48Spatrick void GenericSchedulerBase::SchedCandidate::
initResourceDelta(const ScheduleDAGMI * DAG,const TargetSchedModel * SchedModel)265209467b48Spatrick initResourceDelta(const ScheduleDAGMI *DAG,
265309467b48Spatrick                   const TargetSchedModel *SchedModel) {
265409467b48Spatrick   if (!Policy.ReduceResIdx && !Policy.DemandResIdx)
265509467b48Spatrick     return;
265609467b48Spatrick 
265709467b48Spatrick   const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
265809467b48Spatrick   for (TargetSchedModel::ProcResIter
265909467b48Spatrick          PI = SchedModel->getWriteProcResBegin(SC),
266009467b48Spatrick          PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
266109467b48Spatrick     if (PI->ProcResourceIdx == Policy.ReduceResIdx)
266209467b48Spatrick       ResDelta.CritResources += PI->Cycles;
266309467b48Spatrick     if (PI->ProcResourceIdx == Policy.DemandResIdx)
266409467b48Spatrick       ResDelta.DemandedResources += PI->Cycles;
266509467b48Spatrick   }
266609467b48Spatrick }
266709467b48Spatrick 
266809467b48Spatrick /// Compute remaining latency. We need this both to determine whether the
266909467b48Spatrick /// overall schedule has become latency-limited and whether the instructions
267009467b48Spatrick /// outside this zone are resource or latency limited.
267109467b48Spatrick ///
267209467b48Spatrick /// The "dependent" latency is updated incrementally during scheduling as the
267309467b48Spatrick /// max height/depth of scheduled nodes minus the cycles since it was
267409467b48Spatrick /// scheduled:
267509467b48Spatrick ///   DLat = max (N.depth - (CurrCycle - N.ReadyCycle) for N in Zone
267609467b48Spatrick ///
267709467b48Spatrick /// The "independent" latency is the max ready queue depth:
267809467b48Spatrick ///   ILat = max N.depth for N in Available|Pending
267909467b48Spatrick ///
268009467b48Spatrick /// RemainingLatency is the greater of independent and dependent latency.
268109467b48Spatrick ///
268209467b48Spatrick /// These computations are expensive, especially in DAGs with many edges, so
268309467b48Spatrick /// only do them if necessary.
computeRemLatency(SchedBoundary & CurrZone)268409467b48Spatrick static unsigned computeRemLatency(SchedBoundary &CurrZone) {
268509467b48Spatrick   unsigned RemLatency = CurrZone.getDependentLatency();
268609467b48Spatrick   RemLatency = std::max(RemLatency,
268709467b48Spatrick                         CurrZone.findMaxLatency(CurrZone.Available.elements()));
268809467b48Spatrick   RemLatency = std::max(RemLatency,
268909467b48Spatrick                         CurrZone.findMaxLatency(CurrZone.Pending.elements()));
269009467b48Spatrick   return RemLatency;
269109467b48Spatrick }
269209467b48Spatrick 
269309467b48Spatrick /// Returns true if the current cycle plus remaning latency is greater than
269409467b48Spatrick /// the critical path in the scheduling region.
shouldReduceLatency(const CandPolicy & Policy,SchedBoundary & CurrZone,bool ComputeRemLatency,unsigned & RemLatency) const269509467b48Spatrick bool GenericSchedulerBase::shouldReduceLatency(const CandPolicy &Policy,
269609467b48Spatrick                                                SchedBoundary &CurrZone,
269709467b48Spatrick                                                bool ComputeRemLatency,
269809467b48Spatrick                                                unsigned &RemLatency) const {
269909467b48Spatrick   // The current cycle is already greater than the critical path, so we are
270009467b48Spatrick   // already latency limited and don't need to compute the remaining latency.
270109467b48Spatrick   if (CurrZone.getCurrCycle() > Rem.CriticalPath)
270209467b48Spatrick     return true;
270309467b48Spatrick 
270409467b48Spatrick   // If we haven't scheduled anything yet, then we aren't latency limited.
270509467b48Spatrick   if (CurrZone.getCurrCycle() == 0)
270609467b48Spatrick     return false;
270709467b48Spatrick 
270809467b48Spatrick   if (ComputeRemLatency)
270909467b48Spatrick     RemLatency = computeRemLatency(CurrZone);
271009467b48Spatrick 
271109467b48Spatrick   return RemLatency + CurrZone.getCurrCycle() > Rem.CriticalPath;
271209467b48Spatrick }
271309467b48Spatrick 
271409467b48Spatrick /// Set the CandPolicy given a scheduling zone given the current resources and
271509467b48Spatrick /// latencies inside and outside the zone.
setPolicy(CandPolicy & Policy,bool IsPostRA,SchedBoundary & CurrZone,SchedBoundary * OtherZone)271609467b48Spatrick void GenericSchedulerBase::setPolicy(CandPolicy &Policy, bool IsPostRA,
271709467b48Spatrick                                      SchedBoundary &CurrZone,
271809467b48Spatrick                                      SchedBoundary *OtherZone) {
271909467b48Spatrick   // Apply preemptive heuristics based on the total latency and resources
272009467b48Spatrick   // inside and outside this zone. Potential stalls should be considered before
272109467b48Spatrick   // following this policy.
272209467b48Spatrick 
272309467b48Spatrick   // Compute the critical resource outside the zone.
272409467b48Spatrick   unsigned OtherCritIdx = 0;
272509467b48Spatrick   unsigned OtherCount =
272609467b48Spatrick     OtherZone ? OtherZone->getOtherResourceCount(OtherCritIdx) : 0;
272709467b48Spatrick 
272809467b48Spatrick   bool OtherResLimited = false;
272909467b48Spatrick   unsigned RemLatency = 0;
273009467b48Spatrick   bool RemLatencyComputed = false;
273109467b48Spatrick   if (SchedModel->hasInstrSchedModel() && OtherCount != 0) {
273209467b48Spatrick     RemLatency = computeRemLatency(CurrZone);
273309467b48Spatrick     RemLatencyComputed = true;
273409467b48Spatrick     OtherResLimited = checkResourceLimit(SchedModel->getLatencyFactor(),
273509467b48Spatrick                                          OtherCount, RemLatency, false);
273609467b48Spatrick   }
273709467b48Spatrick 
273809467b48Spatrick   // Schedule aggressively for latency in PostRA mode. We don't check for
273909467b48Spatrick   // acyclic latency during PostRA, and highly out-of-order processors will
274009467b48Spatrick   // skip PostRA scheduling.
274109467b48Spatrick   if (!OtherResLimited &&
274209467b48Spatrick       (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
274309467b48Spatrick                                        RemLatency))) {
274409467b48Spatrick     Policy.ReduceLatency |= true;
274509467b48Spatrick     LLVM_DEBUG(dbgs() << "  " << CurrZone.Available.getName()
274609467b48Spatrick                       << " RemainingLatency " << RemLatency << " + "
274709467b48Spatrick                       << CurrZone.getCurrCycle() << "c > CritPath "
274809467b48Spatrick                       << Rem.CriticalPath << "\n");
274909467b48Spatrick   }
275009467b48Spatrick   // If the same resource is limiting inside and outside the zone, do nothing.
275109467b48Spatrick   if (CurrZone.getZoneCritResIdx() == OtherCritIdx)
275209467b48Spatrick     return;
275309467b48Spatrick 
275409467b48Spatrick   LLVM_DEBUG(if (CurrZone.isResourceLimited()) {
275509467b48Spatrick     dbgs() << "  " << CurrZone.Available.getName() << " ResourceLimited: "
275609467b48Spatrick            << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) << "\n";
275709467b48Spatrick   } if (OtherResLimited) dbgs()
275809467b48Spatrick                  << "  RemainingLimit: "
275909467b48Spatrick                  << SchedModel->getResourceName(OtherCritIdx) << "\n";
276009467b48Spatrick              if (!CurrZone.isResourceLimited() && !OtherResLimited) dbgs()
276109467b48Spatrick              << "  Latency limited both directions.\n");
276209467b48Spatrick 
276309467b48Spatrick   if (CurrZone.isResourceLimited() && !Policy.ReduceResIdx)
276409467b48Spatrick     Policy.ReduceResIdx = CurrZone.getZoneCritResIdx();
276509467b48Spatrick 
276609467b48Spatrick   if (OtherResLimited)
276709467b48Spatrick     Policy.DemandResIdx = OtherCritIdx;
276809467b48Spatrick }
276909467b48Spatrick 
277009467b48Spatrick #ifndef NDEBUG
getReasonStr(GenericSchedulerBase::CandReason Reason)277109467b48Spatrick const char *GenericSchedulerBase::getReasonStr(
277209467b48Spatrick   GenericSchedulerBase::CandReason Reason) {
277309467b48Spatrick   switch (Reason) {
277409467b48Spatrick   case NoCand:         return "NOCAND    ";
277509467b48Spatrick   case Only1:          return "ONLY1     ";
277609467b48Spatrick   case PhysReg:        return "PHYS-REG  ";
277709467b48Spatrick   case RegExcess:      return "REG-EXCESS";
277809467b48Spatrick   case RegCritical:    return "REG-CRIT  ";
277909467b48Spatrick   case Stall:          return "STALL     ";
278009467b48Spatrick   case Cluster:        return "CLUSTER   ";
278109467b48Spatrick   case Weak:           return "WEAK      ";
278209467b48Spatrick   case RegMax:         return "REG-MAX   ";
278309467b48Spatrick   case ResourceReduce: return "RES-REDUCE";
278409467b48Spatrick   case ResourceDemand: return "RES-DEMAND";
278509467b48Spatrick   case TopDepthReduce: return "TOP-DEPTH ";
278609467b48Spatrick   case TopPathReduce:  return "TOP-PATH  ";
278709467b48Spatrick   case BotHeightReduce:return "BOT-HEIGHT";
278809467b48Spatrick   case BotPathReduce:  return "BOT-PATH  ";
278909467b48Spatrick   case NextDefUse:     return "DEF-USE   ";
279009467b48Spatrick   case NodeOrder:      return "ORDER     ";
279109467b48Spatrick   };
279209467b48Spatrick   llvm_unreachable("Unknown reason!");
279309467b48Spatrick }
279409467b48Spatrick 
traceCandidate(const SchedCandidate & Cand)279509467b48Spatrick void GenericSchedulerBase::traceCandidate(const SchedCandidate &Cand) {
279609467b48Spatrick   PressureChange P;
279709467b48Spatrick   unsigned ResIdx = 0;
279809467b48Spatrick   unsigned Latency = 0;
279909467b48Spatrick   switch (Cand.Reason) {
280009467b48Spatrick   default:
280109467b48Spatrick     break;
280209467b48Spatrick   case RegExcess:
280309467b48Spatrick     P = Cand.RPDelta.Excess;
280409467b48Spatrick     break;
280509467b48Spatrick   case RegCritical:
280609467b48Spatrick     P = Cand.RPDelta.CriticalMax;
280709467b48Spatrick     break;
280809467b48Spatrick   case RegMax:
280909467b48Spatrick     P = Cand.RPDelta.CurrentMax;
281009467b48Spatrick     break;
281109467b48Spatrick   case ResourceReduce:
281209467b48Spatrick     ResIdx = Cand.Policy.ReduceResIdx;
281309467b48Spatrick     break;
281409467b48Spatrick   case ResourceDemand:
281509467b48Spatrick     ResIdx = Cand.Policy.DemandResIdx;
281609467b48Spatrick     break;
281709467b48Spatrick   case TopDepthReduce:
281809467b48Spatrick     Latency = Cand.SU->getDepth();
281909467b48Spatrick     break;
282009467b48Spatrick   case TopPathReduce:
282109467b48Spatrick     Latency = Cand.SU->getHeight();
282209467b48Spatrick     break;
282309467b48Spatrick   case BotHeightReduce:
282409467b48Spatrick     Latency = Cand.SU->getHeight();
282509467b48Spatrick     break;
282609467b48Spatrick   case BotPathReduce:
282709467b48Spatrick     Latency = Cand.SU->getDepth();
282809467b48Spatrick     break;
282909467b48Spatrick   }
283009467b48Spatrick   dbgs() << "  Cand SU(" << Cand.SU->NodeNum << ") " << getReasonStr(Cand.Reason);
283109467b48Spatrick   if (P.isValid())
283209467b48Spatrick     dbgs() << " " << TRI->getRegPressureSetName(P.getPSet())
283309467b48Spatrick            << ":" << P.getUnitInc() << " ";
283409467b48Spatrick   else
283509467b48Spatrick     dbgs() << "      ";
283609467b48Spatrick   if (ResIdx)
283709467b48Spatrick     dbgs() << " " << SchedModel->getProcResource(ResIdx)->Name << " ";
283809467b48Spatrick   else
283909467b48Spatrick     dbgs() << "         ";
284009467b48Spatrick   if (Latency)
284109467b48Spatrick     dbgs() << " " << Latency << " cycles ";
284209467b48Spatrick   else
284309467b48Spatrick     dbgs() << "          ";
284409467b48Spatrick   dbgs() << '\n';
284509467b48Spatrick }
284609467b48Spatrick #endif
284709467b48Spatrick 
284809467b48Spatrick namespace llvm {
284909467b48Spatrick /// Return true if this heuristic determines order.
285073471bf0Spatrick /// TODO: Consider refactor return type of these functions as integer or enum,
285173471bf0Spatrick /// as we may need to differentiate whether TryCand is better than Cand.
tryLess(int TryVal,int CandVal,GenericSchedulerBase::SchedCandidate & TryCand,GenericSchedulerBase::SchedCandidate & Cand,GenericSchedulerBase::CandReason Reason)285209467b48Spatrick bool tryLess(int TryVal, int CandVal,
285309467b48Spatrick              GenericSchedulerBase::SchedCandidate &TryCand,
285409467b48Spatrick              GenericSchedulerBase::SchedCandidate &Cand,
285509467b48Spatrick              GenericSchedulerBase::CandReason Reason) {
285609467b48Spatrick   if (TryVal < CandVal) {
285709467b48Spatrick     TryCand.Reason = Reason;
285809467b48Spatrick     return true;
285909467b48Spatrick   }
286009467b48Spatrick   if (TryVal > CandVal) {
286109467b48Spatrick     if (Cand.Reason > Reason)
286209467b48Spatrick       Cand.Reason = Reason;
286309467b48Spatrick     return true;
286409467b48Spatrick   }
286509467b48Spatrick   return false;
286609467b48Spatrick }
286709467b48Spatrick 
tryGreater(int TryVal,int CandVal,GenericSchedulerBase::SchedCandidate & TryCand,GenericSchedulerBase::SchedCandidate & Cand,GenericSchedulerBase::CandReason Reason)286809467b48Spatrick bool tryGreater(int TryVal, int CandVal,
286909467b48Spatrick                 GenericSchedulerBase::SchedCandidate &TryCand,
287009467b48Spatrick                 GenericSchedulerBase::SchedCandidate &Cand,
287109467b48Spatrick                 GenericSchedulerBase::CandReason Reason) {
287209467b48Spatrick   if (TryVal > CandVal) {
287309467b48Spatrick     TryCand.Reason = Reason;
287409467b48Spatrick     return true;
287509467b48Spatrick   }
287609467b48Spatrick   if (TryVal < CandVal) {
287709467b48Spatrick     if (Cand.Reason > Reason)
287809467b48Spatrick       Cand.Reason = Reason;
287909467b48Spatrick     return true;
288009467b48Spatrick   }
288109467b48Spatrick   return false;
288209467b48Spatrick }
288309467b48Spatrick 
tryLatency(GenericSchedulerBase::SchedCandidate & TryCand,GenericSchedulerBase::SchedCandidate & Cand,SchedBoundary & Zone)288409467b48Spatrick bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
288509467b48Spatrick                 GenericSchedulerBase::SchedCandidate &Cand,
288609467b48Spatrick                 SchedBoundary &Zone) {
288709467b48Spatrick   if (Zone.isTop()) {
288873471bf0Spatrick     // Prefer the candidate with the lesser depth, but only if one of them has
288973471bf0Spatrick     // depth greater than the total latency scheduled so far, otherwise either
289073471bf0Spatrick     // of them could be scheduled now with no stall.
289173471bf0Spatrick     if (std::max(TryCand.SU->getDepth(), Cand.SU->getDepth()) >
289273471bf0Spatrick         Zone.getScheduledLatency()) {
289309467b48Spatrick       if (tryLess(TryCand.SU->getDepth(), Cand.SU->getDepth(),
289409467b48Spatrick                   TryCand, Cand, GenericSchedulerBase::TopDepthReduce))
289509467b48Spatrick         return true;
289609467b48Spatrick     }
289709467b48Spatrick     if (tryGreater(TryCand.SU->getHeight(), Cand.SU->getHeight(),
289809467b48Spatrick                    TryCand, Cand, GenericSchedulerBase::TopPathReduce))
289909467b48Spatrick       return true;
290009467b48Spatrick   } else {
290173471bf0Spatrick     // Prefer the candidate with the lesser height, but only if one of them has
290273471bf0Spatrick     // height greater than the total latency scheduled so far, otherwise either
290373471bf0Spatrick     // of them could be scheduled now with no stall.
290473471bf0Spatrick     if (std::max(TryCand.SU->getHeight(), Cand.SU->getHeight()) >
290573471bf0Spatrick         Zone.getScheduledLatency()) {
290609467b48Spatrick       if (tryLess(TryCand.SU->getHeight(), Cand.SU->getHeight(),
290709467b48Spatrick                   TryCand, Cand, GenericSchedulerBase::BotHeightReduce))
290809467b48Spatrick         return true;
290909467b48Spatrick     }
291009467b48Spatrick     if (tryGreater(TryCand.SU->getDepth(), Cand.SU->getDepth(),
291109467b48Spatrick                    TryCand, Cand, GenericSchedulerBase::BotPathReduce))
291209467b48Spatrick       return true;
291309467b48Spatrick   }
291409467b48Spatrick   return false;
291509467b48Spatrick }
291609467b48Spatrick } // end namespace llvm
291709467b48Spatrick 
tracePick(GenericSchedulerBase::CandReason Reason,bool IsTop)291809467b48Spatrick static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop) {
291909467b48Spatrick   LLVM_DEBUG(dbgs() << "Pick " << (IsTop ? "Top " : "Bot ")
292009467b48Spatrick                     << GenericSchedulerBase::getReasonStr(Reason) << '\n');
292109467b48Spatrick }
292209467b48Spatrick 
tracePick(const GenericSchedulerBase::SchedCandidate & Cand)292309467b48Spatrick static void tracePick(const GenericSchedulerBase::SchedCandidate &Cand) {
292409467b48Spatrick   tracePick(Cand.Reason, Cand.AtTop);
292509467b48Spatrick }
292609467b48Spatrick 
initialize(ScheduleDAGMI * dag)292709467b48Spatrick void GenericScheduler::initialize(ScheduleDAGMI *dag) {
292809467b48Spatrick   assert(dag->hasVRegLiveness() &&
292909467b48Spatrick          "(PreRA)GenericScheduler needs vreg liveness");
293009467b48Spatrick   DAG = static_cast<ScheduleDAGMILive*>(dag);
293109467b48Spatrick   SchedModel = DAG->getSchedModel();
293209467b48Spatrick   TRI = DAG->TRI;
293309467b48Spatrick 
2934097a140dSpatrick   if (RegionPolicy.ComputeDFSResult)
2935097a140dSpatrick     DAG->computeDFSResult();
2936097a140dSpatrick 
293709467b48Spatrick   Rem.init(DAG, SchedModel);
293809467b48Spatrick   Top.init(DAG, SchedModel, &Rem);
293909467b48Spatrick   Bot.init(DAG, SchedModel, &Rem);
294009467b48Spatrick 
294109467b48Spatrick   // Initialize resource counts.
294209467b48Spatrick 
294309467b48Spatrick   // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
294409467b48Spatrick   // are disabled, then these HazardRecs will be disabled.
294509467b48Spatrick   const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
294609467b48Spatrick   if (!Top.HazardRec) {
294709467b48Spatrick     Top.HazardRec =
294809467b48Spatrick         DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
294909467b48Spatrick             Itin, DAG);
295009467b48Spatrick   }
295109467b48Spatrick   if (!Bot.HazardRec) {
295209467b48Spatrick     Bot.HazardRec =
295309467b48Spatrick         DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
295409467b48Spatrick             Itin, DAG);
295509467b48Spatrick   }
295609467b48Spatrick   TopCand.SU = nullptr;
295709467b48Spatrick   BotCand.SU = nullptr;
295809467b48Spatrick }
295909467b48Spatrick 
296009467b48Spatrick /// Initialize the per-region scheduling policy.
initPolicy(MachineBasicBlock::iterator Begin,MachineBasicBlock::iterator End,unsigned NumRegionInstrs)296109467b48Spatrick void GenericScheduler::initPolicy(MachineBasicBlock::iterator Begin,
296209467b48Spatrick                                   MachineBasicBlock::iterator End,
296309467b48Spatrick                                   unsigned NumRegionInstrs) {
296409467b48Spatrick   const MachineFunction &MF = *Begin->getMF();
296509467b48Spatrick   const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
296609467b48Spatrick 
296709467b48Spatrick   // Avoid setting up the register pressure tracker for small regions to save
296809467b48Spatrick   // compile time. As a rough heuristic, only track pressure when the number of
296909467b48Spatrick   // schedulable instructions exceeds half the integer register file.
297009467b48Spatrick   RegionPolicy.ShouldTrackPressure = true;
297109467b48Spatrick   for (unsigned VT = MVT::i32; VT > (unsigned)MVT::i1; --VT) {
297209467b48Spatrick     MVT::SimpleValueType LegalIntVT = (MVT::SimpleValueType)VT;
297309467b48Spatrick     if (TLI->isTypeLegal(LegalIntVT)) {
297409467b48Spatrick       unsigned NIntRegs = Context->RegClassInfo->getNumAllocatableRegs(
297509467b48Spatrick         TLI->getRegClassFor(LegalIntVT));
297609467b48Spatrick       RegionPolicy.ShouldTrackPressure = NumRegionInstrs > (NIntRegs / 2);
297709467b48Spatrick     }
297809467b48Spatrick   }
297909467b48Spatrick 
298009467b48Spatrick   // For generic targets, we default to bottom-up, because it's simpler and more
298109467b48Spatrick   // compile-time optimizations have been implemented in that direction.
298209467b48Spatrick   RegionPolicy.OnlyBottomUp = true;
298309467b48Spatrick 
298409467b48Spatrick   // Allow the subtarget to override default policy.
298509467b48Spatrick   MF.getSubtarget().overrideSchedPolicy(RegionPolicy, NumRegionInstrs);
298609467b48Spatrick 
298709467b48Spatrick   // After subtarget overrides, apply command line options.
298809467b48Spatrick   if (!EnableRegPressure) {
298909467b48Spatrick     RegionPolicy.ShouldTrackPressure = false;
299009467b48Spatrick     RegionPolicy.ShouldTrackLaneMasks = false;
299109467b48Spatrick   }
299209467b48Spatrick 
299309467b48Spatrick   // Check -misched-topdown/bottomup can force or unforce scheduling direction.
299409467b48Spatrick   // e.g. -misched-bottomup=false allows scheduling in both directions.
299509467b48Spatrick   assert((!ForceTopDown || !ForceBottomUp) &&
299609467b48Spatrick          "-misched-topdown incompatible with -misched-bottomup");
299709467b48Spatrick   if (ForceBottomUp.getNumOccurrences() > 0) {
299809467b48Spatrick     RegionPolicy.OnlyBottomUp = ForceBottomUp;
299909467b48Spatrick     if (RegionPolicy.OnlyBottomUp)
300009467b48Spatrick       RegionPolicy.OnlyTopDown = false;
300109467b48Spatrick   }
300209467b48Spatrick   if (ForceTopDown.getNumOccurrences() > 0) {
300309467b48Spatrick     RegionPolicy.OnlyTopDown = ForceTopDown;
300409467b48Spatrick     if (RegionPolicy.OnlyTopDown)
300509467b48Spatrick       RegionPolicy.OnlyBottomUp = false;
300609467b48Spatrick   }
300709467b48Spatrick }
300809467b48Spatrick 
dumpPolicy() const300909467b48Spatrick void GenericScheduler::dumpPolicy() const {
301009467b48Spatrick   // Cannot completely remove virtual function even in release mode.
301109467b48Spatrick #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
301209467b48Spatrick   dbgs() << "GenericScheduler RegionPolicy: "
301309467b48Spatrick          << " ShouldTrackPressure=" << RegionPolicy.ShouldTrackPressure
301409467b48Spatrick          << " OnlyTopDown=" << RegionPolicy.OnlyTopDown
301509467b48Spatrick          << " OnlyBottomUp=" << RegionPolicy.OnlyBottomUp
301609467b48Spatrick          << "\n";
301709467b48Spatrick #endif
301809467b48Spatrick }
301909467b48Spatrick 
302009467b48Spatrick /// Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic
302109467b48Spatrick /// critical path by more cycles than it takes to drain the instruction buffer.
302209467b48Spatrick /// We estimate an upper bounds on in-flight instructions as:
302309467b48Spatrick ///
302409467b48Spatrick /// CyclesPerIteration = max( CyclicPath, Loop-Resource-Height )
302509467b48Spatrick /// InFlightIterations = AcyclicPath / CyclesPerIteration
302609467b48Spatrick /// InFlightResources = InFlightIterations * LoopResources
302709467b48Spatrick ///
302809467b48Spatrick /// TODO: Check execution resources in addition to IssueCount.
checkAcyclicLatency()302909467b48Spatrick void GenericScheduler::checkAcyclicLatency() {
303009467b48Spatrick   if (Rem.CyclicCritPath == 0 || Rem.CyclicCritPath >= Rem.CriticalPath)
303109467b48Spatrick     return;
303209467b48Spatrick 
303309467b48Spatrick   // Scaled number of cycles per loop iteration.
303409467b48Spatrick   unsigned IterCount =
303509467b48Spatrick     std::max(Rem.CyclicCritPath * SchedModel->getLatencyFactor(),
303609467b48Spatrick              Rem.RemIssueCount);
303709467b48Spatrick   // Scaled acyclic critical path.
303809467b48Spatrick   unsigned AcyclicCount = Rem.CriticalPath * SchedModel->getLatencyFactor();
303909467b48Spatrick   // InFlightCount = (AcyclicPath / IterCycles) * InstrPerLoop
304009467b48Spatrick   unsigned InFlightCount =
304109467b48Spatrick     (AcyclicCount * Rem.RemIssueCount + IterCount-1) / IterCount;
304209467b48Spatrick   unsigned BufferLimit =
304309467b48Spatrick     SchedModel->getMicroOpBufferSize() * SchedModel->getMicroOpFactor();
304409467b48Spatrick 
304509467b48Spatrick   Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
304609467b48Spatrick 
304709467b48Spatrick   LLVM_DEBUG(
304809467b48Spatrick       dbgs() << "IssueCycles="
304909467b48Spatrick              << Rem.RemIssueCount / SchedModel->getLatencyFactor() << "c "
305009467b48Spatrick              << "IterCycles=" << IterCount / SchedModel->getLatencyFactor()
305109467b48Spatrick              << "c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
305209467b48Spatrick              << " InFlight=" << InFlightCount / SchedModel->getMicroOpFactor()
305309467b48Spatrick              << "m BufferLim=" << SchedModel->getMicroOpBufferSize() << "m\n";
305409467b48Spatrick       if (Rem.IsAcyclicLatencyLimited) dbgs() << "  ACYCLIC LATENCY LIMIT\n");
305509467b48Spatrick }
305609467b48Spatrick 
registerRoots()305709467b48Spatrick void GenericScheduler::registerRoots() {
305809467b48Spatrick   Rem.CriticalPath = DAG->ExitSU.getDepth();
305909467b48Spatrick 
306009467b48Spatrick   // Some roots may not feed into ExitSU. Check all of them in case.
306109467b48Spatrick   for (const SUnit *SU : Bot.Available) {
306209467b48Spatrick     if (SU->getDepth() > Rem.CriticalPath)
306309467b48Spatrick       Rem.CriticalPath = SU->getDepth();
306409467b48Spatrick   }
306509467b48Spatrick   LLVM_DEBUG(dbgs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << '\n');
306609467b48Spatrick   if (DumpCriticalPathLength) {
306709467b48Spatrick     errs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << " \n";
306809467b48Spatrick   }
306909467b48Spatrick 
307009467b48Spatrick   if (EnableCyclicPath && SchedModel->getMicroOpBufferSize() > 0) {
307109467b48Spatrick     Rem.CyclicCritPath = DAG->computeCyclicCriticalPath();
307209467b48Spatrick     checkAcyclicLatency();
307309467b48Spatrick   }
307409467b48Spatrick }
307509467b48Spatrick 
307609467b48Spatrick namespace llvm {
tryPressure(const PressureChange & TryP,const PressureChange & CandP,GenericSchedulerBase::SchedCandidate & TryCand,GenericSchedulerBase::SchedCandidate & Cand,GenericSchedulerBase::CandReason Reason,const TargetRegisterInfo * TRI,const MachineFunction & MF)307709467b48Spatrick bool tryPressure(const PressureChange &TryP,
307809467b48Spatrick                  const PressureChange &CandP,
307909467b48Spatrick                  GenericSchedulerBase::SchedCandidate &TryCand,
308009467b48Spatrick                  GenericSchedulerBase::SchedCandidate &Cand,
308109467b48Spatrick                  GenericSchedulerBase::CandReason Reason,
308209467b48Spatrick                  const TargetRegisterInfo *TRI,
308309467b48Spatrick                  const MachineFunction &MF) {
308409467b48Spatrick   // If one candidate decreases and the other increases, go with it.
308509467b48Spatrick   // Invalid candidates have UnitInc==0.
308609467b48Spatrick   if (tryGreater(TryP.getUnitInc() < 0, CandP.getUnitInc() < 0, TryCand, Cand,
308709467b48Spatrick                  Reason)) {
308809467b48Spatrick     return true;
308909467b48Spatrick   }
309009467b48Spatrick   // Do not compare the magnitude of pressure changes between top and bottom
309109467b48Spatrick   // boundary.
309209467b48Spatrick   if (Cand.AtTop != TryCand.AtTop)
309309467b48Spatrick     return false;
309409467b48Spatrick 
309509467b48Spatrick   // If both candidates affect the same set in the same boundary, go with the
309609467b48Spatrick   // smallest increase.
309709467b48Spatrick   unsigned TryPSet = TryP.getPSetOrMax();
309809467b48Spatrick   unsigned CandPSet = CandP.getPSetOrMax();
309909467b48Spatrick   if (TryPSet == CandPSet) {
310009467b48Spatrick     return tryLess(TryP.getUnitInc(), CandP.getUnitInc(), TryCand, Cand,
310109467b48Spatrick                    Reason);
310209467b48Spatrick   }
310309467b48Spatrick 
310409467b48Spatrick   int TryRank = TryP.isValid() ? TRI->getRegPressureSetScore(MF, TryPSet) :
310509467b48Spatrick                                  std::numeric_limits<int>::max();
310609467b48Spatrick 
310709467b48Spatrick   int CandRank = CandP.isValid() ? TRI->getRegPressureSetScore(MF, CandPSet) :
310809467b48Spatrick                                    std::numeric_limits<int>::max();
310909467b48Spatrick 
311009467b48Spatrick   // If the candidates are decreasing pressure, reverse priority.
311109467b48Spatrick   if (TryP.getUnitInc() < 0)
311209467b48Spatrick     std::swap(TryRank, CandRank);
311309467b48Spatrick   return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
311409467b48Spatrick }
311509467b48Spatrick 
getWeakLeft(const SUnit * SU,bool isTop)311609467b48Spatrick unsigned getWeakLeft(const SUnit *SU, bool isTop) {
311709467b48Spatrick   return (isTop) ? SU->WeakPredsLeft : SU->WeakSuccsLeft;
311809467b48Spatrick }
311909467b48Spatrick 
312009467b48Spatrick /// Minimize physical register live ranges. Regalloc wants them adjacent to
312109467b48Spatrick /// their physreg def/use.
312209467b48Spatrick ///
312309467b48Spatrick /// FIXME: This is an unnecessary check on the critical path. Most are root/leaf
312409467b48Spatrick /// copies which can be prescheduled. The rest (e.g. x86 MUL) could be bundled
312509467b48Spatrick /// with the operation that produces or consumes the physreg. We'll do this when
312609467b48Spatrick /// regalloc has support for parallel copies.
biasPhysReg(const SUnit * SU,bool isTop)312709467b48Spatrick int biasPhysReg(const SUnit *SU, bool isTop) {
312809467b48Spatrick   const MachineInstr *MI = SU->getInstr();
312909467b48Spatrick 
313009467b48Spatrick   if (MI->isCopy()) {
313109467b48Spatrick     unsigned ScheduledOper = isTop ? 1 : 0;
313209467b48Spatrick     unsigned UnscheduledOper = isTop ? 0 : 1;
313309467b48Spatrick     // If we have already scheduled the physreg produce/consumer, immediately
313409467b48Spatrick     // schedule the copy.
3135*d415bd75Srobert     if (MI->getOperand(ScheduledOper).getReg().isPhysical())
313609467b48Spatrick       return 1;
313709467b48Spatrick     // If the physreg is at the boundary, defer it. Otherwise schedule it
313809467b48Spatrick     // immediately to free the dependent. We can hoist the copy later.
313909467b48Spatrick     bool AtBoundary = isTop ? !SU->NumSuccsLeft : !SU->NumPredsLeft;
3140*d415bd75Srobert     if (MI->getOperand(UnscheduledOper).getReg().isPhysical())
314109467b48Spatrick       return AtBoundary ? -1 : 1;
314209467b48Spatrick   }
314309467b48Spatrick 
314409467b48Spatrick   if (MI->isMoveImmediate()) {
314509467b48Spatrick     // If we have a move immediate and all successors have been assigned, bias
314609467b48Spatrick     // towards scheduling this later. Make sure all register defs are to
314709467b48Spatrick     // physical registers.
314809467b48Spatrick     bool DoBias = true;
314909467b48Spatrick     for (const MachineOperand &Op : MI->defs()) {
3150*d415bd75Srobert       if (Op.isReg() && !Op.getReg().isPhysical()) {
315109467b48Spatrick         DoBias = false;
315209467b48Spatrick         break;
315309467b48Spatrick       }
315409467b48Spatrick     }
315509467b48Spatrick 
315609467b48Spatrick     if (DoBias)
315709467b48Spatrick       return isTop ? -1 : 1;
315809467b48Spatrick   }
315909467b48Spatrick 
316009467b48Spatrick   return 0;
316109467b48Spatrick }
316209467b48Spatrick } // end namespace llvm
316309467b48Spatrick 
initCandidate(SchedCandidate & Cand,SUnit * SU,bool AtTop,const RegPressureTracker & RPTracker,RegPressureTracker & TempTracker)316409467b48Spatrick void GenericScheduler::initCandidate(SchedCandidate &Cand, SUnit *SU,
316509467b48Spatrick                                      bool AtTop,
316609467b48Spatrick                                      const RegPressureTracker &RPTracker,
316709467b48Spatrick                                      RegPressureTracker &TempTracker) {
316809467b48Spatrick   Cand.SU = SU;
316909467b48Spatrick   Cand.AtTop = AtTop;
317009467b48Spatrick   if (DAG->isTrackingPressure()) {
317109467b48Spatrick     if (AtTop) {
317209467b48Spatrick       TempTracker.getMaxDownwardPressureDelta(
317309467b48Spatrick         Cand.SU->getInstr(),
317409467b48Spatrick         Cand.RPDelta,
317509467b48Spatrick         DAG->getRegionCriticalPSets(),
317609467b48Spatrick         DAG->getRegPressure().MaxSetPressure);
317709467b48Spatrick     } else {
317809467b48Spatrick       if (VerifyScheduling) {
317909467b48Spatrick         TempTracker.getMaxUpwardPressureDelta(
318009467b48Spatrick           Cand.SU->getInstr(),
318109467b48Spatrick           &DAG->getPressureDiff(Cand.SU),
318209467b48Spatrick           Cand.RPDelta,
318309467b48Spatrick           DAG->getRegionCriticalPSets(),
318409467b48Spatrick           DAG->getRegPressure().MaxSetPressure);
318509467b48Spatrick       } else {
318609467b48Spatrick         RPTracker.getUpwardPressureDelta(
318709467b48Spatrick           Cand.SU->getInstr(),
318809467b48Spatrick           DAG->getPressureDiff(Cand.SU),
318909467b48Spatrick           Cand.RPDelta,
319009467b48Spatrick           DAG->getRegionCriticalPSets(),
319109467b48Spatrick           DAG->getRegPressure().MaxSetPressure);
319209467b48Spatrick       }
319309467b48Spatrick     }
319409467b48Spatrick   }
319509467b48Spatrick   LLVM_DEBUG(if (Cand.RPDelta.Excess.isValid()) dbgs()
319609467b48Spatrick              << "  Try  SU(" << Cand.SU->NodeNum << ") "
319709467b48Spatrick              << TRI->getRegPressureSetName(Cand.RPDelta.Excess.getPSet()) << ":"
319809467b48Spatrick              << Cand.RPDelta.Excess.getUnitInc() << "\n");
319909467b48Spatrick }
320009467b48Spatrick 
320109467b48Spatrick /// Apply a set of heuristics to a new candidate. Heuristics are currently
320209467b48Spatrick /// hierarchical. This may be more efficient than a graduated cost model because
320309467b48Spatrick /// we don't need to evaluate all aspects of the model for each node in the
320409467b48Spatrick /// queue. But it's really done to make the heuristics easier to debug and
320509467b48Spatrick /// statistically analyze.
320609467b48Spatrick ///
320709467b48Spatrick /// \param Cand provides the policy and current best candidate.
320809467b48Spatrick /// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
320909467b48Spatrick /// \param Zone describes the scheduled zone that we are extending, or nullptr
321073471bf0Spatrick ///             if Cand is from a different zone than TryCand.
321173471bf0Spatrick /// \return \c true if TryCand is better than Cand (Reason is NOT NoCand)
tryCandidate(SchedCandidate & Cand,SchedCandidate & TryCand,SchedBoundary * Zone) const321273471bf0Spatrick bool GenericScheduler::tryCandidate(SchedCandidate &Cand,
321309467b48Spatrick                                     SchedCandidate &TryCand,
321409467b48Spatrick                                     SchedBoundary *Zone) const {
321509467b48Spatrick   // Initialize the candidate if needed.
321609467b48Spatrick   if (!Cand.isValid()) {
321709467b48Spatrick     TryCand.Reason = NodeOrder;
321873471bf0Spatrick     return true;
321909467b48Spatrick   }
322009467b48Spatrick 
322109467b48Spatrick   // Bias PhysReg Defs and copies to their uses and defined respectively.
322209467b48Spatrick   if (tryGreater(biasPhysReg(TryCand.SU, TryCand.AtTop),
322309467b48Spatrick                  biasPhysReg(Cand.SU, Cand.AtTop), TryCand, Cand, PhysReg))
322473471bf0Spatrick     return TryCand.Reason != NoCand;
322509467b48Spatrick 
322609467b48Spatrick   // Avoid exceeding the target's limit.
322709467b48Spatrick   if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.Excess,
322809467b48Spatrick                                                Cand.RPDelta.Excess,
322909467b48Spatrick                                                TryCand, Cand, RegExcess, TRI,
323009467b48Spatrick                                                DAG->MF))
323173471bf0Spatrick     return TryCand.Reason != NoCand;
323209467b48Spatrick 
323309467b48Spatrick   // Avoid increasing the max critical pressure in the scheduled region.
323409467b48Spatrick   if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CriticalMax,
323509467b48Spatrick                                                Cand.RPDelta.CriticalMax,
323609467b48Spatrick                                                TryCand, Cand, RegCritical, TRI,
323709467b48Spatrick                                                DAG->MF))
323873471bf0Spatrick     return TryCand.Reason != NoCand;
323909467b48Spatrick 
324009467b48Spatrick   // We only compare a subset of features when comparing nodes between
324109467b48Spatrick   // Top and Bottom boundary. Some properties are simply incomparable, in many
324209467b48Spatrick   // other instances we should only override the other boundary if something
324309467b48Spatrick   // is a clear good pick on one boundary. Skip heuristics that are more
324409467b48Spatrick   // "tie-breaking" in nature.
324509467b48Spatrick   bool SameBoundary = Zone != nullptr;
324609467b48Spatrick   if (SameBoundary) {
324709467b48Spatrick     // For loops that are acyclic path limited, aggressively schedule for
324809467b48Spatrick     // latency. Within an single cycle, whenever CurrMOps > 0, allow normal
324909467b48Spatrick     // heuristics to take precedence.
325009467b48Spatrick     if (Rem.IsAcyclicLatencyLimited && !Zone->getCurrMOps() &&
325109467b48Spatrick         tryLatency(TryCand, Cand, *Zone))
325273471bf0Spatrick       return TryCand.Reason != NoCand;
325309467b48Spatrick 
325409467b48Spatrick     // Prioritize instructions that read unbuffered resources by stall cycles.
325509467b48Spatrick     if (tryLess(Zone->getLatencyStallCycles(TryCand.SU),
325609467b48Spatrick                 Zone->getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
325773471bf0Spatrick       return TryCand.Reason != NoCand;
325809467b48Spatrick   }
325909467b48Spatrick 
326009467b48Spatrick   // Keep clustered nodes together to encourage downstream peephole
326109467b48Spatrick   // optimizations which may reduce resource requirements.
326209467b48Spatrick   //
326309467b48Spatrick   // This is a best effort to set things up for a post-RA pass. Optimizations
326409467b48Spatrick   // like generating loads of multiple registers should ideally be done within
326509467b48Spatrick   // the scheduler pass by combining the loads during DAG postprocessing.
326609467b48Spatrick   const SUnit *CandNextClusterSU =
326709467b48Spatrick     Cand.AtTop ? DAG->getNextClusterSucc() : DAG->getNextClusterPred();
326809467b48Spatrick   const SUnit *TryCandNextClusterSU =
326909467b48Spatrick     TryCand.AtTop ? DAG->getNextClusterSucc() : DAG->getNextClusterPred();
327009467b48Spatrick   if (tryGreater(TryCand.SU == TryCandNextClusterSU,
327109467b48Spatrick                  Cand.SU == CandNextClusterSU,
327209467b48Spatrick                  TryCand, Cand, Cluster))
327373471bf0Spatrick     return TryCand.Reason != NoCand;
327409467b48Spatrick 
327509467b48Spatrick   if (SameBoundary) {
327609467b48Spatrick     // Weak edges are for clustering and other constraints.
327709467b48Spatrick     if (tryLess(getWeakLeft(TryCand.SU, TryCand.AtTop),
327809467b48Spatrick                 getWeakLeft(Cand.SU, Cand.AtTop),
327909467b48Spatrick                 TryCand, Cand, Weak))
328073471bf0Spatrick       return TryCand.Reason != NoCand;
328109467b48Spatrick   }
328209467b48Spatrick 
328309467b48Spatrick   // Avoid increasing the max pressure of the entire region.
328409467b48Spatrick   if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CurrentMax,
328509467b48Spatrick                                                Cand.RPDelta.CurrentMax,
328609467b48Spatrick                                                TryCand, Cand, RegMax, TRI,
328709467b48Spatrick                                                DAG->MF))
328873471bf0Spatrick     return TryCand.Reason != NoCand;
328909467b48Spatrick 
329009467b48Spatrick   if (SameBoundary) {
329109467b48Spatrick     // Avoid critical resource consumption and balance the schedule.
329209467b48Spatrick     TryCand.initResourceDelta(DAG, SchedModel);
329309467b48Spatrick     if (tryLess(TryCand.ResDelta.CritResources, Cand.ResDelta.CritResources,
329409467b48Spatrick                 TryCand, Cand, ResourceReduce))
329573471bf0Spatrick       return TryCand.Reason != NoCand;
329609467b48Spatrick     if (tryGreater(TryCand.ResDelta.DemandedResources,
329709467b48Spatrick                    Cand.ResDelta.DemandedResources,
329809467b48Spatrick                    TryCand, Cand, ResourceDemand))
329973471bf0Spatrick       return TryCand.Reason != NoCand;
330009467b48Spatrick 
330109467b48Spatrick     // Avoid serializing long latency dependence chains.
330209467b48Spatrick     // For acyclic path limited loops, latency was already checked above.
330309467b48Spatrick     if (!RegionPolicy.DisableLatencyHeuristic && TryCand.Policy.ReduceLatency &&
330409467b48Spatrick         !Rem.IsAcyclicLatencyLimited && tryLatency(TryCand, Cand, *Zone))
330573471bf0Spatrick       return TryCand.Reason != NoCand;
330609467b48Spatrick 
330709467b48Spatrick     // Fall through to original instruction order.
330809467b48Spatrick     if ((Zone->isTop() && TryCand.SU->NodeNum < Cand.SU->NodeNum)
330909467b48Spatrick         || (!Zone->isTop() && TryCand.SU->NodeNum > Cand.SU->NodeNum)) {
331009467b48Spatrick       TryCand.Reason = NodeOrder;
331173471bf0Spatrick       return true;
331209467b48Spatrick     }
331309467b48Spatrick   }
331473471bf0Spatrick 
331573471bf0Spatrick   return false;
331609467b48Spatrick }
331709467b48Spatrick 
331809467b48Spatrick /// Pick the best candidate from the queue.
331909467b48Spatrick ///
332009467b48Spatrick /// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
332109467b48Spatrick /// DAG building. To adjust for the current scheduling location we need to
332209467b48Spatrick /// maintain the number of vreg uses remaining to be top-scheduled.
pickNodeFromQueue(SchedBoundary & Zone,const CandPolicy & ZonePolicy,const RegPressureTracker & RPTracker,SchedCandidate & Cand)332309467b48Spatrick void GenericScheduler::pickNodeFromQueue(SchedBoundary &Zone,
332409467b48Spatrick                                          const CandPolicy &ZonePolicy,
332509467b48Spatrick                                          const RegPressureTracker &RPTracker,
332609467b48Spatrick                                          SchedCandidate &Cand) {
332709467b48Spatrick   // getMaxPressureDelta temporarily modifies the tracker.
332809467b48Spatrick   RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
332909467b48Spatrick 
333009467b48Spatrick   ReadyQueue &Q = Zone.Available;
333109467b48Spatrick   for (SUnit *SU : Q) {
333209467b48Spatrick 
333309467b48Spatrick     SchedCandidate TryCand(ZonePolicy);
333409467b48Spatrick     initCandidate(TryCand, SU, Zone.isTop(), RPTracker, TempTracker);
333509467b48Spatrick     // Pass SchedBoundary only when comparing nodes from the same boundary.
333609467b48Spatrick     SchedBoundary *ZoneArg = Cand.AtTop == TryCand.AtTop ? &Zone : nullptr;
333773471bf0Spatrick     if (tryCandidate(Cand, TryCand, ZoneArg)) {
333809467b48Spatrick       // Initialize resource delta if needed in case future heuristics query it.
333909467b48Spatrick       if (TryCand.ResDelta == SchedResourceDelta())
334009467b48Spatrick         TryCand.initResourceDelta(DAG, SchedModel);
334109467b48Spatrick       Cand.setBest(TryCand);
334209467b48Spatrick       LLVM_DEBUG(traceCandidate(Cand));
334309467b48Spatrick     }
334409467b48Spatrick   }
334509467b48Spatrick }
334609467b48Spatrick 
334709467b48Spatrick /// Pick the best candidate node from either the top or bottom queue.
pickNodeBidirectional(bool & IsTopNode)334809467b48Spatrick SUnit *GenericScheduler::pickNodeBidirectional(bool &IsTopNode) {
334909467b48Spatrick   // Schedule as far as possible in the direction of no choice. This is most
335009467b48Spatrick   // efficient, but also provides the best heuristics for CriticalPSets.
335109467b48Spatrick   if (SUnit *SU = Bot.pickOnlyChoice()) {
335209467b48Spatrick     IsTopNode = false;
335309467b48Spatrick     tracePick(Only1, false);
335409467b48Spatrick     return SU;
335509467b48Spatrick   }
335609467b48Spatrick   if (SUnit *SU = Top.pickOnlyChoice()) {
335709467b48Spatrick     IsTopNode = true;
335809467b48Spatrick     tracePick(Only1, true);
335909467b48Spatrick     return SU;
336009467b48Spatrick   }
336109467b48Spatrick   // Set the bottom-up policy based on the state of the current bottom zone and
336209467b48Spatrick   // the instructions outside the zone, including the top zone.
336309467b48Spatrick   CandPolicy BotPolicy;
336409467b48Spatrick   setPolicy(BotPolicy, /*IsPostRA=*/false, Bot, &Top);
336509467b48Spatrick   // Set the top-down policy based on the state of the current top zone and
336609467b48Spatrick   // the instructions outside the zone, including the bottom zone.
336709467b48Spatrick   CandPolicy TopPolicy;
336809467b48Spatrick   setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot);
336909467b48Spatrick 
337009467b48Spatrick   // See if BotCand is still valid (because we previously scheduled from Top).
337109467b48Spatrick   LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
337209467b48Spatrick   if (!BotCand.isValid() || BotCand.SU->isScheduled ||
337309467b48Spatrick       BotCand.Policy != BotPolicy) {
337409467b48Spatrick     BotCand.reset(CandPolicy());
337509467b48Spatrick     pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
337609467b48Spatrick     assert(BotCand.Reason != NoCand && "failed to find the first candidate");
337709467b48Spatrick   } else {
337809467b48Spatrick     LLVM_DEBUG(traceCandidate(BotCand));
337909467b48Spatrick #ifndef NDEBUG
338009467b48Spatrick     if (VerifyScheduling) {
338109467b48Spatrick       SchedCandidate TCand;
338209467b48Spatrick       TCand.reset(CandPolicy());
338309467b48Spatrick       pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand);
338409467b48Spatrick       assert(TCand.SU == BotCand.SU &&
338509467b48Spatrick              "Last pick result should correspond to re-picking right now");
338609467b48Spatrick     }
338709467b48Spatrick #endif
338809467b48Spatrick   }
338909467b48Spatrick 
339009467b48Spatrick   // Check if the top Q has a better candidate.
339109467b48Spatrick   LLVM_DEBUG(dbgs() << "Picking from Top:\n");
339209467b48Spatrick   if (!TopCand.isValid() || TopCand.SU->isScheduled ||
339309467b48Spatrick       TopCand.Policy != TopPolicy) {
339409467b48Spatrick     TopCand.reset(CandPolicy());
339509467b48Spatrick     pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
339609467b48Spatrick     assert(TopCand.Reason != NoCand && "failed to find the first candidate");
339709467b48Spatrick   } else {
339809467b48Spatrick     LLVM_DEBUG(traceCandidate(TopCand));
339909467b48Spatrick #ifndef NDEBUG
340009467b48Spatrick     if (VerifyScheduling) {
340109467b48Spatrick       SchedCandidate TCand;
340209467b48Spatrick       TCand.reset(CandPolicy());
340309467b48Spatrick       pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand);
340409467b48Spatrick       assert(TCand.SU == TopCand.SU &&
340509467b48Spatrick            "Last pick result should correspond to re-picking right now");
340609467b48Spatrick     }
340709467b48Spatrick #endif
340809467b48Spatrick   }
340909467b48Spatrick 
341009467b48Spatrick   // Pick best from BotCand and TopCand.
341109467b48Spatrick   assert(BotCand.isValid());
341209467b48Spatrick   assert(TopCand.isValid());
341309467b48Spatrick   SchedCandidate Cand = BotCand;
341409467b48Spatrick   TopCand.Reason = NoCand;
341573471bf0Spatrick   if (tryCandidate(Cand, TopCand, nullptr)) {
341609467b48Spatrick     Cand.setBest(TopCand);
341709467b48Spatrick     LLVM_DEBUG(traceCandidate(Cand));
341809467b48Spatrick   }
341909467b48Spatrick 
342009467b48Spatrick   IsTopNode = Cand.AtTop;
342109467b48Spatrick   tracePick(Cand);
342209467b48Spatrick   return Cand.SU;
342309467b48Spatrick }
342409467b48Spatrick 
342509467b48Spatrick /// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
pickNode(bool & IsTopNode)342609467b48Spatrick SUnit *GenericScheduler::pickNode(bool &IsTopNode) {
342709467b48Spatrick   if (DAG->top() == DAG->bottom()) {
342809467b48Spatrick     assert(Top.Available.empty() && Top.Pending.empty() &&
342909467b48Spatrick            Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
343009467b48Spatrick     return nullptr;
343109467b48Spatrick   }
343209467b48Spatrick   SUnit *SU;
343309467b48Spatrick   do {
343409467b48Spatrick     if (RegionPolicy.OnlyTopDown) {
343509467b48Spatrick       SU = Top.pickOnlyChoice();
343609467b48Spatrick       if (!SU) {
343709467b48Spatrick         CandPolicy NoPolicy;
343809467b48Spatrick         TopCand.reset(NoPolicy);
343909467b48Spatrick         pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
344009467b48Spatrick         assert(TopCand.Reason != NoCand && "failed to find a candidate");
344109467b48Spatrick         tracePick(TopCand);
344209467b48Spatrick         SU = TopCand.SU;
344309467b48Spatrick       }
344409467b48Spatrick       IsTopNode = true;
344509467b48Spatrick     } else if (RegionPolicy.OnlyBottomUp) {
344609467b48Spatrick       SU = Bot.pickOnlyChoice();
344709467b48Spatrick       if (!SU) {
344809467b48Spatrick         CandPolicy NoPolicy;
344909467b48Spatrick         BotCand.reset(NoPolicy);
345009467b48Spatrick         pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
345109467b48Spatrick         assert(BotCand.Reason != NoCand && "failed to find a candidate");
345209467b48Spatrick         tracePick(BotCand);
345309467b48Spatrick         SU = BotCand.SU;
345409467b48Spatrick       }
345509467b48Spatrick       IsTopNode = false;
345609467b48Spatrick     } else {
345709467b48Spatrick       SU = pickNodeBidirectional(IsTopNode);
345809467b48Spatrick     }
345909467b48Spatrick   } while (SU->isScheduled);
346009467b48Spatrick 
346109467b48Spatrick   if (SU->isTopReady())
346209467b48Spatrick     Top.removeReady(SU);
346309467b48Spatrick   if (SU->isBottomReady())
346409467b48Spatrick     Bot.removeReady(SU);
346509467b48Spatrick 
346609467b48Spatrick   LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
346709467b48Spatrick                     << *SU->getInstr());
346809467b48Spatrick   return SU;
346909467b48Spatrick }
347009467b48Spatrick 
reschedulePhysReg(SUnit * SU,bool isTop)347109467b48Spatrick void GenericScheduler::reschedulePhysReg(SUnit *SU, bool isTop) {
347209467b48Spatrick   MachineBasicBlock::iterator InsertPos = SU->getInstr();
347309467b48Spatrick   if (!isTop)
347409467b48Spatrick     ++InsertPos;
347509467b48Spatrick   SmallVectorImpl<SDep> &Deps = isTop ? SU->Preds : SU->Succs;
347609467b48Spatrick 
347709467b48Spatrick   // Find already scheduled copies with a single physreg dependence and move
347809467b48Spatrick   // them just above the scheduled instruction.
347909467b48Spatrick   for (SDep &Dep : Deps) {
348009467b48Spatrick     if (Dep.getKind() != SDep::Data ||
348109467b48Spatrick         !Register::isPhysicalRegister(Dep.getReg()))
348209467b48Spatrick       continue;
348309467b48Spatrick     SUnit *DepSU = Dep.getSUnit();
348409467b48Spatrick     if (isTop ? DepSU->Succs.size() > 1 : DepSU->Preds.size() > 1)
348509467b48Spatrick       continue;
348609467b48Spatrick     MachineInstr *Copy = DepSU->getInstr();
348709467b48Spatrick     if (!Copy->isCopy() && !Copy->isMoveImmediate())
348809467b48Spatrick       continue;
348909467b48Spatrick     LLVM_DEBUG(dbgs() << "  Rescheduling physreg copy ";
349009467b48Spatrick                DAG->dumpNode(*Dep.getSUnit()));
349109467b48Spatrick     DAG->moveInstruction(Copy, InsertPos);
349209467b48Spatrick   }
349309467b48Spatrick }
349409467b48Spatrick 
349509467b48Spatrick /// Update the scheduler's state after scheduling a node. This is the same node
349609467b48Spatrick /// that was just returned by pickNode(). However, ScheduleDAGMILive needs to
349709467b48Spatrick /// update it's state based on the current cycle before MachineSchedStrategy
349809467b48Spatrick /// does.
349909467b48Spatrick ///
350009467b48Spatrick /// FIXME: Eventually, we may bundle physreg copies rather than rescheduling
350109467b48Spatrick /// them here. See comments in biasPhysReg.
schedNode(SUnit * SU,bool IsTopNode)350209467b48Spatrick void GenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
350309467b48Spatrick   if (IsTopNode) {
350409467b48Spatrick     SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
350509467b48Spatrick     Top.bumpNode(SU);
350609467b48Spatrick     if (SU->hasPhysRegUses)
350709467b48Spatrick       reschedulePhysReg(SU, true);
350809467b48Spatrick   } else {
350909467b48Spatrick     SU->BotReadyCycle = std::max(SU->BotReadyCycle, Bot.getCurrCycle());
351009467b48Spatrick     Bot.bumpNode(SU);
351109467b48Spatrick     if (SU->hasPhysRegDefs)
351209467b48Spatrick       reschedulePhysReg(SU, false);
351309467b48Spatrick   }
351409467b48Spatrick }
351509467b48Spatrick 
351609467b48Spatrick /// Create the standard converging machine scheduler. This will be used as the
351709467b48Spatrick /// default scheduler if the target does not set a default.
createGenericSchedLive(MachineSchedContext * C)351809467b48Spatrick ScheduleDAGMILive *llvm::createGenericSchedLive(MachineSchedContext *C) {
351909467b48Spatrick   ScheduleDAGMILive *DAG =
352009467b48Spatrick       new ScheduleDAGMILive(C, std::make_unique<GenericScheduler>(C));
352109467b48Spatrick   // Register DAG post-processors.
352209467b48Spatrick   //
352309467b48Spatrick   // FIXME: extend the mutation API to allow earlier mutations to instantiate
352409467b48Spatrick   // data and pass it to later mutations. Have a single mutation that gathers
352509467b48Spatrick   // the interesting nodes in one pass.
352609467b48Spatrick   DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI));
352709467b48Spatrick   return DAG;
352809467b48Spatrick }
352909467b48Spatrick 
createConvergingSched(MachineSchedContext * C)353073471bf0Spatrick static ScheduleDAGInstrs *createConvergingSched(MachineSchedContext *C) {
353109467b48Spatrick   return createGenericSchedLive(C);
353209467b48Spatrick }
353309467b48Spatrick 
353409467b48Spatrick static MachineSchedRegistry
353509467b48Spatrick GenericSchedRegistry("converge", "Standard converging scheduler.",
353673471bf0Spatrick                      createConvergingSched);
353709467b48Spatrick 
353809467b48Spatrick //===----------------------------------------------------------------------===//
353909467b48Spatrick // PostGenericScheduler - Generic PostRA implementation of MachineSchedStrategy.
354009467b48Spatrick //===----------------------------------------------------------------------===//
354109467b48Spatrick 
initialize(ScheduleDAGMI * Dag)354209467b48Spatrick void PostGenericScheduler::initialize(ScheduleDAGMI *Dag) {
354309467b48Spatrick   DAG = Dag;
354409467b48Spatrick   SchedModel = DAG->getSchedModel();
354509467b48Spatrick   TRI = DAG->TRI;
354609467b48Spatrick 
354709467b48Spatrick   Rem.init(DAG, SchedModel);
354809467b48Spatrick   Top.init(DAG, SchedModel, &Rem);
354909467b48Spatrick   BotRoots.clear();
355009467b48Spatrick 
355109467b48Spatrick   // Initialize the HazardRecognizers. If itineraries don't exist, are empty,
355209467b48Spatrick   // or are disabled, then these HazardRecs will be disabled.
355309467b48Spatrick   const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
355409467b48Spatrick   if (!Top.HazardRec) {
355509467b48Spatrick     Top.HazardRec =
355609467b48Spatrick         DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
355709467b48Spatrick             Itin, DAG);
355809467b48Spatrick   }
355909467b48Spatrick }
356009467b48Spatrick 
registerRoots()356109467b48Spatrick void PostGenericScheduler::registerRoots() {
356209467b48Spatrick   Rem.CriticalPath = DAG->ExitSU.getDepth();
356309467b48Spatrick 
356409467b48Spatrick   // Some roots may not feed into ExitSU. Check all of them in case.
356509467b48Spatrick   for (const SUnit *SU : BotRoots) {
356609467b48Spatrick     if (SU->getDepth() > Rem.CriticalPath)
356709467b48Spatrick       Rem.CriticalPath = SU->getDepth();
356809467b48Spatrick   }
356909467b48Spatrick   LLVM_DEBUG(dbgs() << "Critical Path: (PGS-RR) " << Rem.CriticalPath << '\n');
357009467b48Spatrick   if (DumpCriticalPathLength) {
357109467b48Spatrick     errs() << "Critical Path(PGS-RR ): " << Rem.CriticalPath << " \n";
357209467b48Spatrick   }
357309467b48Spatrick }
357409467b48Spatrick 
357509467b48Spatrick /// Apply a set of heuristics to a new candidate for PostRA scheduling.
357609467b48Spatrick ///
357709467b48Spatrick /// \param Cand provides the policy and current best candidate.
357809467b48Spatrick /// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
357973471bf0Spatrick /// \return \c true if TryCand is better than Cand (Reason is NOT NoCand)
tryCandidate(SchedCandidate & Cand,SchedCandidate & TryCand)358073471bf0Spatrick bool PostGenericScheduler::tryCandidate(SchedCandidate &Cand,
358109467b48Spatrick                                         SchedCandidate &TryCand) {
358209467b48Spatrick   // Initialize the candidate if needed.
358309467b48Spatrick   if (!Cand.isValid()) {
358409467b48Spatrick     TryCand.Reason = NodeOrder;
358573471bf0Spatrick     return true;
358609467b48Spatrick   }
358709467b48Spatrick 
358809467b48Spatrick   // Prioritize instructions that read unbuffered resources by stall cycles.
358909467b48Spatrick   if (tryLess(Top.getLatencyStallCycles(TryCand.SU),
359009467b48Spatrick               Top.getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
359173471bf0Spatrick     return TryCand.Reason != NoCand;
359209467b48Spatrick 
359309467b48Spatrick   // Keep clustered nodes together.
359409467b48Spatrick   if (tryGreater(TryCand.SU == DAG->getNextClusterSucc(),
359509467b48Spatrick                  Cand.SU == DAG->getNextClusterSucc(),
359609467b48Spatrick                  TryCand, Cand, Cluster))
359773471bf0Spatrick     return TryCand.Reason != NoCand;
359809467b48Spatrick 
359909467b48Spatrick   // Avoid critical resource consumption and balance the schedule.
360009467b48Spatrick   if (tryLess(TryCand.ResDelta.CritResources, Cand.ResDelta.CritResources,
360109467b48Spatrick               TryCand, Cand, ResourceReduce))
360273471bf0Spatrick     return TryCand.Reason != NoCand;
360309467b48Spatrick   if (tryGreater(TryCand.ResDelta.DemandedResources,
360409467b48Spatrick                  Cand.ResDelta.DemandedResources,
360509467b48Spatrick                  TryCand, Cand, ResourceDemand))
360673471bf0Spatrick     return TryCand.Reason != NoCand;
360709467b48Spatrick 
360809467b48Spatrick   // Avoid serializing long latency dependence chains.
360909467b48Spatrick   if (Cand.Policy.ReduceLatency && tryLatency(TryCand, Cand, Top)) {
361073471bf0Spatrick     return TryCand.Reason != NoCand;
361109467b48Spatrick   }
361209467b48Spatrick 
361309467b48Spatrick   // Fall through to original instruction order.
361473471bf0Spatrick   if (TryCand.SU->NodeNum < Cand.SU->NodeNum) {
361509467b48Spatrick     TryCand.Reason = NodeOrder;
361673471bf0Spatrick     return true;
361773471bf0Spatrick   }
361873471bf0Spatrick 
361973471bf0Spatrick   return false;
362009467b48Spatrick }
362109467b48Spatrick 
pickNodeFromQueue(SchedCandidate & Cand)362209467b48Spatrick void PostGenericScheduler::pickNodeFromQueue(SchedCandidate &Cand) {
362309467b48Spatrick   ReadyQueue &Q = Top.Available;
362409467b48Spatrick   for (SUnit *SU : Q) {
362509467b48Spatrick     SchedCandidate TryCand(Cand.Policy);
362609467b48Spatrick     TryCand.SU = SU;
362709467b48Spatrick     TryCand.AtTop = true;
362809467b48Spatrick     TryCand.initResourceDelta(DAG, SchedModel);
362973471bf0Spatrick     if (tryCandidate(Cand, TryCand)) {
363009467b48Spatrick       Cand.setBest(TryCand);
363109467b48Spatrick       LLVM_DEBUG(traceCandidate(Cand));
363209467b48Spatrick     }
363309467b48Spatrick   }
363409467b48Spatrick }
363509467b48Spatrick 
363609467b48Spatrick /// Pick the next node to schedule.
pickNode(bool & IsTopNode)363709467b48Spatrick SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) {
363809467b48Spatrick   if (DAG->top() == DAG->bottom()) {
363909467b48Spatrick     assert(Top.Available.empty() && Top.Pending.empty() && "ReadyQ garbage");
364009467b48Spatrick     return nullptr;
364109467b48Spatrick   }
364209467b48Spatrick   SUnit *SU;
364309467b48Spatrick   do {
364409467b48Spatrick     SU = Top.pickOnlyChoice();
364509467b48Spatrick     if (SU) {
364609467b48Spatrick       tracePick(Only1, true);
364709467b48Spatrick     } else {
364809467b48Spatrick       CandPolicy NoPolicy;
364909467b48Spatrick       SchedCandidate TopCand(NoPolicy);
365009467b48Spatrick       // Set the top-down policy based on the state of the current top zone and
365109467b48Spatrick       // the instructions outside the zone, including the bottom zone.
365209467b48Spatrick       setPolicy(TopCand.Policy, /*IsPostRA=*/true, Top, nullptr);
365309467b48Spatrick       pickNodeFromQueue(TopCand);
365409467b48Spatrick       assert(TopCand.Reason != NoCand && "failed to find a candidate");
365509467b48Spatrick       tracePick(TopCand);
365609467b48Spatrick       SU = TopCand.SU;
365709467b48Spatrick     }
365809467b48Spatrick   } while (SU->isScheduled);
365909467b48Spatrick 
366009467b48Spatrick   IsTopNode = true;
366109467b48Spatrick   Top.removeReady(SU);
366209467b48Spatrick 
366309467b48Spatrick   LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
366409467b48Spatrick                     << *SU->getInstr());
366509467b48Spatrick   return SU;
366609467b48Spatrick }
366709467b48Spatrick 
366809467b48Spatrick /// Called after ScheduleDAGMI has scheduled an instruction and updated
366909467b48Spatrick /// scheduled/remaining flags in the DAG nodes.
schedNode(SUnit * SU,bool IsTopNode)367009467b48Spatrick void PostGenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
367109467b48Spatrick   SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
367209467b48Spatrick   Top.bumpNode(SU);
367309467b48Spatrick }
367409467b48Spatrick 
createGenericSchedPostRA(MachineSchedContext * C)367509467b48Spatrick ScheduleDAGMI *llvm::createGenericSchedPostRA(MachineSchedContext *C) {
367609467b48Spatrick   return new ScheduleDAGMI(C, std::make_unique<PostGenericScheduler>(C),
367709467b48Spatrick                            /*RemoveKillFlags=*/true);
367809467b48Spatrick }
367909467b48Spatrick 
368009467b48Spatrick //===----------------------------------------------------------------------===//
368109467b48Spatrick // ILP Scheduler. Currently for experimental analysis of heuristics.
368209467b48Spatrick //===----------------------------------------------------------------------===//
368309467b48Spatrick 
368409467b48Spatrick namespace {
368509467b48Spatrick 
368609467b48Spatrick /// Order nodes by the ILP metric.
368709467b48Spatrick struct ILPOrder {
368809467b48Spatrick   const SchedDFSResult *DFSResult = nullptr;
368909467b48Spatrick   const BitVector *ScheduledTrees = nullptr;
369009467b48Spatrick   bool MaximizeILP;
369109467b48Spatrick 
ILPOrder__anonf2be975f0511::ILPOrder369209467b48Spatrick   ILPOrder(bool MaxILP) : MaximizeILP(MaxILP) {}
369309467b48Spatrick 
369409467b48Spatrick   /// Apply a less-than relation on node priority.
369509467b48Spatrick   ///
369609467b48Spatrick   /// (Return true if A comes after B in the Q.)
operator ()__anonf2be975f0511::ILPOrder369709467b48Spatrick   bool operator()(const SUnit *A, const SUnit *B) const {
369809467b48Spatrick     unsigned SchedTreeA = DFSResult->getSubtreeID(A);
369909467b48Spatrick     unsigned SchedTreeB = DFSResult->getSubtreeID(B);
370009467b48Spatrick     if (SchedTreeA != SchedTreeB) {
370109467b48Spatrick       // Unscheduled trees have lower priority.
370209467b48Spatrick       if (ScheduledTrees->test(SchedTreeA) != ScheduledTrees->test(SchedTreeB))
370309467b48Spatrick         return ScheduledTrees->test(SchedTreeB);
370409467b48Spatrick 
370509467b48Spatrick       // Trees with shallower connections have have lower priority.
370609467b48Spatrick       if (DFSResult->getSubtreeLevel(SchedTreeA)
370709467b48Spatrick           != DFSResult->getSubtreeLevel(SchedTreeB)) {
370809467b48Spatrick         return DFSResult->getSubtreeLevel(SchedTreeA)
370909467b48Spatrick           < DFSResult->getSubtreeLevel(SchedTreeB);
371009467b48Spatrick       }
371109467b48Spatrick     }
371209467b48Spatrick     if (MaximizeILP)
371309467b48Spatrick       return DFSResult->getILP(A) < DFSResult->getILP(B);
371409467b48Spatrick     else
371509467b48Spatrick       return DFSResult->getILP(A) > DFSResult->getILP(B);
371609467b48Spatrick   }
371709467b48Spatrick };
371809467b48Spatrick 
371909467b48Spatrick /// Schedule based on the ILP metric.
372009467b48Spatrick class ILPScheduler : public MachineSchedStrategy {
372109467b48Spatrick   ScheduleDAGMILive *DAG = nullptr;
372209467b48Spatrick   ILPOrder Cmp;
372309467b48Spatrick 
372409467b48Spatrick   std::vector<SUnit*> ReadyQ;
372509467b48Spatrick 
372609467b48Spatrick public:
ILPScheduler(bool MaximizeILP)372709467b48Spatrick   ILPScheduler(bool MaximizeILP) : Cmp(MaximizeILP) {}
372809467b48Spatrick 
initialize(ScheduleDAGMI * dag)372909467b48Spatrick   void initialize(ScheduleDAGMI *dag) override {
373009467b48Spatrick     assert(dag->hasVRegLiveness() && "ILPScheduler needs vreg liveness");
373109467b48Spatrick     DAG = static_cast<ScheduleDAGMILive*>(dag);
373209467b48Spatrick     DAG->computeDFSResult();
373309467b48Spatrick     Cmp.DFSResult = DAG->getDFSResult();
373409467b48Spatrick     Cmp.ScheduledTrees = &DAG->getScheduledTrees();
373509467b48Spatrick     ReadyQ.clear();
373609467b48Spatrick   }
373709467b48Spatrick 
registerRoots()373809467b48Spatrick   void registerRoots() override {
373909467b48Spatrick     // Restore the heap in ReadyQ with the updated DFS results.
374009467b48Spatrick     std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
374109467b48Spatrick   }
374209467b48Spatrick 
374309467b48Spatrick   /// Implement MachineSchedStrategy interface.
374409467b48Spatrick   /// -----------------------------------------
374509467b48Spatrick 
374609467b48Spatrick   /// Callback to select the highest priority node from the ready Q.
pickNode(bool & IsTopNode)374709467b48Spatrick   SUnit *pickNode(bool &IsTopNode) override {
374809467b48Spatrick     if (ReadyQ.empty()) return nullptr;
374909467b48Spatrick     std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
375009467b48Spatrick     SUnit *SU = ReadyQ.back();
375109467b48Spatrick     ReadyQ.pop_back();
375209467b48Spatrick     IsTopNode = false;
375309467b48Spatrick     LLVM_DEBUG(dbgs() << "Pick node "
375409467b48Spatrick                       << "SU(" << SU->NodeNum << ") "
375509467b48Spatrick                       << " ILP: " << DAG->getDFSResult()->getILP(SU)
375609467b48Spatrick                       << " Tree: " << DAG->getDFSResult()->getSubtreeID(SU)
375709467b48Spatrick                       << " @"
375809467b48Spatrick                       << DAG->getDFSResult()->getSubtreeLevel(
375909467b48Spatrick                              DAG->getDFSResult()->getSubtreeID(SU))
376009467b48Spatrick                       << '\n'
376109467b48Spatrick                       << "Scheduling " << *SU->getInstr());
376209467b48Spatrick     return SU;
376309467b48Spatrick   }
376409467b48Spatrick 
376509467b48Spatrick   /// Scheduler callback to notify that a new subtree is scheduled.
scheduleTree(unsigned SubtreeID)376609467b48Spatrick   void scheduleTree(unsigned SubtreeID) override {
376709467b48Spatrick     std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
376809467b48Spatrick   }
376909467b48Spatrick 
377009467b48Spatrick   /// Callback after a node is scheduled. Mark a newly scheduled tree, notify
377109467b48Spatrick   /// DFSResults, and resort the priority Q.
schedNode(SUnit * SU,bool IsTopNode)377209467b48Spatrick   void schedNode(SUnit *SU, bool IsTopNode) override {
377309467b48Spatrick     assert(!IsTopNode && "SchedDFSResult needs bottom-up");
377409467b48Spatrick   }
377509467b48Spatrick 
releaseTopNode(SUnit *)377609467b48Spatrick   void releaseTopNode(SUnit *) override { /*only called for top roots*/ }
377709467b48Spatrick 
releaseBottomNode(SUnit * SU)377809467b48Spatrick   void releaseBottomNode(SUnit *SU) override {
377909467b48Spatrick     ReadyQ.push_back(SU);
378009467b48Spatrick     std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
378109467b48Spatrick   }
378209467b48Spatrick };
378309467b48Spatrick 
378409467b48Spatrick } // end anonymous namespace
378509467b48Spatrick 
createILPMaxScheduler(MachineSchedContext * C)378609467b48Spatrick static ScheduleDAGInstrs *createILPMaxScheduler(MachineSchedContext *C) {
378709467b48Spatrick   return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(true));
378809467b48Spatrick }
createILPMinScheduler(MachineSchedContext * C)378909467b48Spatrick static ScheduleDAGInstrs *createILPMinScheduler(MachineSchedContext *C) {
379009467b48Spatrick   return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(false));
379109467b48Spatrick }
379209467b48Spatrick 
379309467b48Spatrick static MachineSchedRegistry ILPMaxRegistry(
379409467b48Spatrick   "ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler);
379509467b48Spatrick static MachineSchedRegistry ILPMinRegistry(
379609467b48Spatrick   "ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler);
379709467b48Spatrick 
379809467b48Spatrick //===----------------------------------------------------------------------===//
379909467b48Spatrick // Machine Instruction Shuffler for Correctness Testing
380009467b48Spatrick //===----------------------------------------------------------------------===//
380109467b48Spatrick 
380209467b48Spatrick #ifndef NDEBUG
380309467b48Spatrick namespace {
380409467b48Spatrick 
380509467b48Spatrick /// Apply a less-than relation on the node order, which corresponds to the
380609467b48Spatrick /// instruction order prior to scheduling. IsReverse implements greater-than.
380709467b48Spatrick template<bool IsReverse>
380809467b48Spatrick struct SUnitOrder {
operator ()__anonf2be975f0611::SUnitOrder380909467b48Spatrick   bool operator()(SUnit *A, SUnit *B) const {
381009467b48Spatrick     if (IsReverse)
381109467b48Spatrick       return A->NodeNum > B->NodeNum;
381209467b48Spatrick     else
381309467b48Spatrick       return A->NodeNum < B->NodeNum;
381409467b48Spatrick   }
381509467b48Spatrick };
381609467b48Spatrick 
381709467b48Spatrick /// Reorder instructions as much as possible.
381809467b48Spatrick class InstructionShuffler : public MachineSchedStrategy {
381909467b48Spatrick   bool IsAlternating;
382009467b48Spatrick   bool IsTopDown;
382109467b48Spatrick 
382209467b48Spatrick   // Using a less-than relation (SUnitOrder<false>) for the TopQ priority
382309467b48Spatrick   // gives nodes with a higher number higher priority causing the latest
382409467b48Spatrick   // instructions to be scheduled first.
382509467b48Spatrick   PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false>>
382609467b48Spatrick     TopQ;
382709467b48Spatrick 
382809467b48Spatrick   // When scheduling bottom-up, use greater-than as the queue priority.
382909467b48Spatrick   PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true>>
383009467b48Spatrick     BottomQ;
383109467b48Spatrick 
383209467b48Spatrick public:
InstructionShuffler(bool alternate,bool topdown)383309467b48Spatrick   InstructionShuffler(bool alternate, bool topdown)
383409467b48Spatrick     : IsAlternating(alternate), IsTopDown(topdown) {}
383509467b48Spatrick 
initialize(ScheduleDAGMI *)383609467b48Spatrick   void initialize(ScheduleDAGMI*) override {
383709467b48Spatrick     TopQ.clear();
383809467b48Spatrick     BottomQ.clear();
383909467b48Spatrick   }
384009467b48Spatrick 
384109467b48Spatrick   /// Implement MachineSchedStrategy interface.
384209467b48Spatrick   /// -----------------------------------------
384309467b48Spatrick 
pickNode(bool & IsTopNode)384409467b48Spatrick   SUnit *pickNode(bool &IsTopNode) override {
384509467b48Spatrick     SUnit *SU;
384609467b48Spatrick     if (IsTopDown) {
384709467b48Spatrick       do {
384809467b48Spatrick         if (TopQ.empty()) return nullptr;
384909467b48Spatrick         SU = TopQ.top();
385009467b48Spatrick         TopQ.pop();
385109467b48Spatrick       } while (SU->isScheduled);
385209467b48Spatrick       IsTopNode = true;
385309467b48Spatrick     } else {
385409467b48Spatrick       do {
385509467b48Spatrick         if (BottomQ.empty()) return nullptr;
385609467b48Spatrick         SU = BottomQ.top();
385709467b48Spatrick         BottomQ.pop();
385809467b48Spatrick       } while (SU->isScheduled);
385909467b48Spatrick       IsTopNode = false;
386009467b48Spatrick     }
386109467b48Spatrick     if (IsAlternating)
386209467b48Spatrick       IsTopDown = !IsTopDown;
386309467b48Spatrick     return SU;
386409467b48Spatrick   }
386509467b48Spatrick 
schedNode(SUnit * SU,bool IsTopNode)386609467b48Spatrick   void schedNode(SUnit *SU, bool IsTopNode) override {}
386709467b48Spatrick 
releaseTopNode(SUnit * SU)386809467b48Spatrick   void releaseTopNode(SUnit *SU) override {
386909467b48Spatrick     TopQ.push(SU);
387009467b48Spatrick   }
releaseBottomNode(SUnit * SU)387109467b48Spatrick   void releaseBottomNode(SUnit *SU) override {
387209467b48Spatrick     BottomQ.push(SU);
387309467b48Spatrick   }
387409467b48Spatrick };
387509467b48Spatrick 
387609467b48Spatrick } // end anonymous namespace
387709467b48Spatrick 
createInstructionShuffler(MachineSchedContext * C)387809467b48Spatrick static ScheduleDAGInstrs *createInstructionShuffler(MachineSchedContext *C) {
387909467b48Spatrick   bool Alternate = !ForceTopDown && !ForceBottomUp;
388009467b48Spatrick   bool TopDown = !ForceBottomUp;
388109467b48Spatrick   assert((TopDown || !ForceTopDown) &&
388209467b48Spatrick          "-misched-topdown incompatible with -misched-bottomup");
388309467b48Spatrick   return new ScheduleDAGMILive(
388409467b48Spatrick       C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
388509467b48Spatrick }
388609467b48Spatrick 
388709467b48Spatrick static MachineSchedRegistry ShufflerRegistry(
388809467b48Spatrick   "shuffle", "Shuffle machine instructions alternating directions",
388909467b48Spatrick   createInstructionShuffler);
389009467b48Spatrick #endif // !NDEBUG
389109467b48Spatrick 
389209467b48Spatrick //===----------------------------------------------------------------------===//
389309467b48Spatrick // GraphWriter support for ScheduleDAGMILive.
389409467b48Spatrick //===----------------------------------------------------------------------===//
389509467b48Spatrick 
389609467b48Spatrick #ifndef NDEBUG
389709467b48Spatrick namespace llvm {
389809467b48Spatrick 
389909467b48Spatrick template<> struct GraphTraits<
390009467b48Spatrick   ScheduleDAGMI*> : public GraphTraits<ScheduleDAG*> {};
390109467b48Spatrick 
390209467b48Spatrick template<>
390309467b48Spatrick struct DOTGraphTraits<ScheduleDAGMI*> : public DefaultDOTGraphTraits {
DOTGraphTraitsllvm::DOTGraphTraits390409467b48Spatrick   DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
390509467b48Spatrick 
getGraphNamellvm::DOTGraphTraits390609467b48Spatrick   static std::string getGraphName(const ScheduleDAG *G) {
3907097a140dSpatrick     return std::string(G->MF.getName());
390809467b48Spatrick   }
390909467b48Spatrick 
renderGraphFromBottomUpllvm::DOTGraphTraits391009467b48Spatrick   static bool renderGraphFromBottomUp() {
391109467b48Spatrick     return true;
391209467b48Spatrick   }
391309467b48Spatrick 
isNodeHiddenllvm::DOTGraphTraits391473471bf0Spatrick   static bool isNodeHidden(const SUnit *Node, const ScheduleDAG *G) {
391509467b48Spatrick     if (ViewMISchedCutoff == 0)
391609467b48Spatrick       return false;
391709467b48Spatrick     return (Node->Preds.size() > ViewMISchedCutoff
391809467b48Spatrick          || Node->Succs.size() > ViewMISchedCutoff);
391909467b48Spatrick   }
392009467b48Spatrick 
392109467b48Spatrick   /// If you want to override the dot attributes printed for a particular
392209467b48Spatrick   /// edge, override this method.
getEdgeAttributesllvm::DOTGraphTraits392309467b48Spatrick   static std::string getEdgeAttributes(const SUnit *Node,
392409467b48Spatrick                                        SUnitIterator EI,
392509467b48Spatrick                                        const ScheduleDAG *Graph) {
392609467b48Spatrick     if (EI.isArtificialDep())
392709467b48Spatrick       return "color=cyan,style=dashed";
392809467b48Spatrick     if (EI.isCtrlDep())
392909467b48Spatrick       return "color=blue,style=dashed";
393009467b48Spatrick     return "";
393109467b48Spatrick   }
393209467b48Spatrick 
getNodeLabelllvm::DOTGraphTraits393309467b48Spatrick   static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G) {
393409467b48Spatrick     std::string Str;
393509467b48Spatrick     raw_string_ostream SS(Str);
393609467b48Spatrick     const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
393709467b48Spatrick     const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
393809467b48Spatrick       static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
393909467b48Spatrick     SS << "SU:" << SU->NodeNum;
394009467b48Spatrick     if (DFS)
394109467b48Spatrick       SS << " I:" << DFS->getNumInstrs(SU);
394209467b48Spatrick     return SS.str();
394309467b48Spatrick   }
394409467b48Spatrick 
getNodeDescriptionllvm::DOTGraphTraits394509467b48Spatrick   static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G) {
394609467b48Spatrick     return G->getGraphNodeLabel(SU);
394709467b48Spatrick   }
394809467b48Spatrick 
getNodeAttributesllvm::DOTGraphTraits394909467b48Spatrick   static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G) {
395009467b48Spatrick     std::string Str("shape=Mrecord");
395109467b48Spatrick     const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
395209467b48Spatrick     const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
395309467b48Spatrick       static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
395409467b48Spatrick     if (DFS) {
395509467b48Spatrick       Str += ",style=filled,fillcolor=\"#";
395609467b48Spatrick       Str += DOT::getColorString(DFS->getSubtreeID(N));
395709467b48Spatrick       Str += '"';
395809467b48Spatrick     }
395909467b48Spatrick     return Str;
396009467b48Spatrick   }
396109467b48Spatrick };
396209467b48Spatrick 
396309467b48Spatrick } // end namespace llvm
396409467b48Spatrick #endif // NDEBUG
396509467b48Spatrick 
396609467b48Spatrick /// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
396709467b48Spatrick /// rendered using 'dot'.
viewGraph(const Twine & Name,const Twine & Title)396809467b48Spatrick void ScheduleDAGMI::viewGraph(const Twine &Name, const Twine &Title) {
396909467b48Spatrick #ifndef NDEBUG
397009467b48Spatrick   ViewGraph(this, Name, false, Title);
397109467b48Spatrick #else
397209467b48Spatrick   errs() << "ScheduleDAGMI::viewGraph is only available in debug builds on "
397309467b48Spatrick          << "systems with Graphviz or gv!\n";
397409467b48Spatrick #endif  // NDEBUG
397509467b48Spatrick }
397609467b48Spatrick 
397709467b48Spatrick /// Out-of-line implementation with no arguments is handy for gdb.
viewGraph()397809467b48Spatrick void ScheduleDAGMI::viewGraph() {
397909467b48Spatrick   viewGraph(getDAGName(), "Scheduling-Units Graph for " + getDAGName());
398009467b48Spatrick }
3981