blob: f0721ea3b76de20dcb34932b778dbb03d969f718 [file] [log] [blame]
Andrew Trick6a50baa2012-05-17 22:37:09 +00001//===- MachineScheduler.cpp - Machine Instruction Scheduler ---------------===//
Andrew Tricke77e84e2012-01-13 06:30:30 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Andrew Tricke77e84e2012-01-13 06:30:30 +00006//
7//===----------------------------------------------------------------------===//
8//
9// MachineScheduler schedules machine instructions after phi elimination. It
10// preserves LiveIntervals so it can be invoked before register allocation.
11//
12//===----------------------------------------------------------------------===//
13
Chandler Carruth6bda14b2017-06-06 11:49:48 +000014#include "llvm/CodeGen/MachineScheduler.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000015#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/BitVector.h"
17#include "llvm/ADT/DenseMap.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000018#include "llvm/ADT/PriorityQueue.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000019#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/iterator_range.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000022#include "llvm/Analysis/AliasAnalysis.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000023#include "llvm/CodeGen/LiveInterval.h"
Matthias Braunf8422972017-12-13 02:51:04 +000024#include "llvm/CodeGen/LiveIntervals.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000025#include "llvm/CodeGen/MachineBasicBlock.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000026#include "llvm/CodeGen/MachineDominators.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000027#include "llvm/CodeGen/MachineFunction.h"
28#include "llvm/CodeGen/MachineFunctionPass.h"
29#include "llvm/CodeGen/MachineInstr.h"
Jakub Staszakdf17ddd2013-03-10 13:11:23 +000030#include "llvm/CodeGen/MachineLoopInfo.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000031#include "llvm/CodeGen/MachineOperand.h"
32#include "llvm/CodeGen/MachinePassRegistry.h"
Andrew Trick736dd9a2013-06-21 18:32:58 +000033#include "llvm/CodeGen/MachineRegisterInfo.h"
Andrew Tricke77e84e2012-01-13 06:30:30 +000034#include "llvm/CodeGen/Passes.h"
Andrew Trick05ff4662012-06-06 20:29:31 +000035#include "llvm/CodeGen/RegisterClassInfo.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000036#include "llvm/CodeGen/RegisterPressure.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000037#include "llvm/CodeGen/ScheduleDAG.h"
38#include "llvm/CodeGen/ScheduleDAGInstrs.h"
39#include "llvm/CodeGen/ScheduleDAGMutation.h"
Andrew Trickcd1c2f92012-11-28 05:13:24 +000040#include "llvm/CodeGen/ScheduleDFS.h"
Andrew Trick61f1a272012-05-24 22:11:09 +000041#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000042#include "llvm/CodeGen/SlotIndexes.h"
Francis Visoiu Mistrih0b8dd442018-11-29 20:03:19 +000043#include "llvm/CodeGen/TargetFrameLowering.h"
David Blaikie3f833ed2017-11-08 01:01:31 +000044#include "llvm/CodeGen/TargetInstrInfo.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000045#include "llvm/CodeGen/TargetLowering.h"
Matthias Braun31d19d42016-05-10 03:21:59 +000046#include "llvm/CodeGen/TargetPassConfig.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000047#include "llvm/CodeGen/TargetRegisterInfo.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000048#include "llvm/CodeGen/TargetSchedule.h"
David Blaikieb3bde2e2017-11-17 01:07:10 +000049#include "llvm/CodeGen/TargetSubtargetInfo.h"
Nico Weber432a3882018-04-30 14:59:11 +000050#include "llvm/Config/llvm-config.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000051#include "llvm/MC/LaneBitmask.h"
52#include "llvm/Pass.h"
Andrew Tricke77e84e2012-01-13 06:30:30 +000053#include "llvm/Support/CommandLine.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000054#include "llvm/Support/Compiler.h"
Andrew Tricke77e84e2012-01-13 06:30:30 +000055#include "llvm/Support/Debug.h"
56#include "llvm/Support/ErrorHandling.h"
Andrew Trickea9fd952013-01-25 07:45:29 +000057#include "llvm/Support/GraphWriter.h"
David Blaikie13e77db2018-03-23 23:58:25 +000058#include "llvm/Support/MachineValueType.h"
Andrew Tricke77e84e2012-01-13 06:30:30 +000059#include "llvm/Support/raw_ostream.h"
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000060#include <algorithm>
61#include <cassert>
62#include <cstdint>
63#include <iterator>
64#include <limits>
65#include <memory>
66#include <string>
67#include <tuple>
68#include <utility>
69#include <vector>
Andrew Trick7ccdc5c2012-01-17 06:55:07 +000070
Andrew Tricke77e84e2012-01-13 06:30:30 +000071using namespace llvm;
72
Matthias Braun1527baa2017-05-25 21:26:32 +000073#define DEBUG_TYPE "machine-scheduler"
Chandler Carruth1b9dde02014-04-22 02:02:50 +000074
Andrew Trick7a8e1002012-09-11 00:39:15 +000075namespace llvm {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000076
Andrew Trick7a8e1002012-09-11 00:39:15 +000077cl::opt<bool> ForceTopDown("misched-topdown", cl::Hidden,
78 cl::desc("Force top-down list scheduling"));
79cl::opt<bool> ForceBottomUp("misched-bottomup", cl::Hidden,
80 cl::desc("Force bottom-up list scheduling"));
Gerolf Hoflehnerb5220dc2014-08-07 21:49:44 +000081cl::opt<bool>
82DumpCriticalPathLength("misched-dcpl", cl::Hidden,
83 cl::desc("Print critical path length to stdout"));
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000084
Jay Foade5368002019-10-01 15:45:47 +000085cl::opt<bool> VerifyScheduling(
86 "verify-misched", cl::Hidden,
87 cl::desc("Verify machine instrs before and after machine scheduling"));
88
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +000089} // end namespace llvm
Andrew Trick8823dec2012-03-14 04:00:41 +000090
Andrew Tricka5f19562012-03-07 00:18:25 +000091#ifndef NDEBUG
92static cl::opt<bool> ViewMISchedDAGs("view-misched-dags", cl::Hidden,
93 cl::desc("Pop up a window to show MISched dags after they are processed"));
Lang Hamesdd98c492012-03-19 18:38:38 +000094
Matthias Braund78ee542015-09-17 21:09:59 +000095/// In some situations a few uninteresting nodes depend on nearly all other
96/// nodes in the graph, provide a cutoff to hide them.
97static cl::opt<unsigned> ViewMISchedCutoff("view-misched-cutoff", cl::Hidden,
98 cl::desc("Hide nodes with more predecessor/successor than cutoff"));
99
Lang Hamesdd98c492012-03-19 18:38:38 +0000100static cl::opt<unsigned> MISchedCutoff("misched-cutoff", cl::Hidden,
101 cl::desc("Stop scheduling after N instructions"), cl::init(~0U));
Andrew Trick33e05d72013-12-28 21:57:02 +0000102
103static cl::opt<std::string> SchedOnlyFunc("misched-only-func", cl::Hidden,
104 cl::desc("Only schedule this function"));
105static cl::opt<unsigned> SchedOnlyBlock("misched-only-block", cl::Hidden,
Francis Visoiu Mistrih25528d62017-12-04 17:18:51 +0000106 cl::desc("Only schedule this MBB#"));
Matthias Braun3136e422018-09-19 20:50:49 +0000107static cl::opt<bool> PrintDAGs("misched-print-dags", cl::Hidden,
108 cl::desc("Print schedule DAGs"));
Andrew Tricka5f19562012-03-07 00:18:25 +0000109#else
Matthias Braun3136e422018-09-19 20:50:49 +0000110static const bool ViewMISchedDAGs = false;
111static const bool PrintDAGs = false;
Andrew Tricka5f19562012-03-07 00:18:25 +0000112#endif // NDEBUG
113
Matthias Braun6493bc22016-04-22 19:09:17 +0000114/// Avoid quadratic complexity in unusually large basic blocks by limiting the
115/// size of the ready lists.
116static cl::opt<unsigned> ReadyListLimit("misched-limit", cl::Hidden,
117 cl::desc("Limit ready list to N instructions"), cl::init(256));
118
Andrew Trickb6e74712013-09-04 20:59:59 +0000119static cl::opt<bool> EnableRegPressure("misched-regpressure", cl::Hidden,
120 cl::desc("Enable register pressure scheduling."), cl::init(true));
121
Andrew Trickc01b0042013-08-23 17:48:43 +0000122static cl::opt<bool> EnableCyclicPath("misched-cyclicpath", cl::Hidden,
Andrew Trick6c88b352013-09-09 23:31:14 +0000123 cl::desc("Enable cyclic critical path analysis."), cl::init(true));
Andrew Trickc01b0042013-08-23 17:48:43 +0000124
Jun Bum Lim4c5bd582016-04-15 14:58:38 +0000125static cl::opt<bool> EnableMemOpCluster("misched-cluster", cl::Hidden,
126 cl::desc("Enable memop clustering."),
127 cl::init(true));
Andrew Tricka7714a02012-11-12 19:40:10 +0000128
Andrew Trick44f750a2013-01-25 04:01:04 +0000129// DAG subtrees must have at least this many nodes.
130static const unsigned MinSubtreeSize = 8;
131
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +0000132// Pin the vtables to this file.
133void MachineSchedStrategy::anchor() {}
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000134
Juergen Ributzkad12ccbd2013-11-19 00:57:56 +0000135void ScheduleDAGMutation::anchor() {}
136
Andrew Trick63440872012-01-14 02:17:06 +0000137//===----------------------------------------------------------------------===//
138// Machine Instruction Scheduling Pass and Registry
139//===----------------------------------------------------------------------===//
140
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000141MachineSchedContext::MachineSchedContext() {
Andrew Trick4d4b5462012-04-24 20:36:19 +0000142 RegClassInfo = new RegisterClassInfo();
143}
144
145MachineSchedContext::~MachineSchedContext() {
146 delete RegClassInfo;
147}
148
Andrew Tricke77e84e2012-01-13 06:30:30 +0000149namespace {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000150
Andrew Trickd7f890e2013-12-28 21:56:47 +0000151/// Base class for a machine scheduler class that can run at any point.
152class MachineSchedulerBase : public MachineSchedContext,
153 public MachineFunctionPass {
154public:
155 MachineSchedulerBase(char &ID): MachineFunctionPass(ID) {}
156
Craig Topperc0196b12014-04-14 00:51:57 +0000157 void print(raw_ostream &O, const Module* = nullptr) const override;
Andrew Trickd7f890e2013-12-28 21:56:47 +0000158
159protected:
Matthias Braun93563e72015-11-03 01:53:29 +0000160 void scheduleRegions(ScheduleDAGInstrs &Scheduler, bool FixKillFlags);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000161};
162
Andrew Tricke1c034f2012-01-17 06:55:03 +0000163/// MachineScheduler runs after coalescing and before register allocation.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000164class MachineScheduler : public MachineSchedulerBase {
Andrew Tricke77e84e2012-01-13 06:30:30 +0000165public:
Andrew Tricke1c034f2012-01-17 06:55:03 +0000166 MachineScheduler();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000167
Craig Topper4584cd52014-03-07 09:26:03 +0000168 void getAnalysisUsage(AnalysisUsage &AU) const override;
Andrew Tricke77e84e2012-01-13 06:30:30 +0000169
Craig Topper4584cd52014-03-07 09:26:03 +0000170 bool runOnMachineFunction(MachineFunction&) override;
Andrew Tricke77e84e2012-01-13 06:30:30 +0000171
Andrew Tricke77e84e2012-01-13 06:30:30 +0000172 static char ID; // Class identification, replacement for typeinfo
Andrew Trick978674b2013-09-20 05:14:41 +0000173
174protected:
175 ScheduleDAGInstrs *createMachineScheduler();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000176};
Andrew Trick17080b92013-12-28 21:56:51 +0000177
178/// PostMachineScheduler runs after shortly before code emission.
179class PostMachineScheduler : public MachineSchedulerBase {
180public:
181 PostMachineScheduler();
182
Craig Topper4584cd52014-03-07 09:26:03 +0000183 void getAnalysisUsage(AnalysisUsage &AU) const override;
Andrew Trick17080b92013-12-28 21:56:51 +0000184
Craig Topper4584cd52014-03-07 09:26:03 +0000185 bool runOnMachineFunction(MachineFunction&) override;
Andrew Trick17080b92013-12-28 21:56:51 +0000186
187 static char ID; // Class identification, replacement for typeinfo
188
189protected:
190 ScheduleDAGInstrs *createPostMachineScheduler();
191};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000192
193} // end anonymous namespace
Andrew Tricke77e84e2012-01-13 06:30:30 +0000194
Andrew Tricke1c034f2012-01-17 06:55:03 +0000195char MachineScheduler::ID = 0;
Andrew Tricke77e84e2012-01-13 06:30:30 +0000196
Andrew Tricke1c034f2012-01-17 06:55:03 +0000197char &llvm::MachineSchedulerID = MachineScheduler::ID;
Andrew Tricke77e84e2012-01-13 06:30:30 +0000198
Matthias Braun1527baa2017-05-25 21:26:32 +0000199INITIALIZE_PASS_BEGIN(MachineScheduler, DEBUG_TYPE,
Andrew Tricke77e84e2012-01-13 06:30:30 +0000200 "Machine Instruction Scheduler", false, false)
Chandler Carruth7b560d42015-09-09 17:55:00 +0000201INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
Jakub Kuderski5be08ee2019-10-01 18:27:17 +0000202INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
Davide Italiano6a1209e2017-03-24 20:52:56 +0000203INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
Andrew Tricke77e84e2012-01-13 06:30:30 +0000204INITIALIZE_PASS_DEPENDENCY(SlotIndexes)
205INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
Matthias Braun1527baa2017-05-25 21:26:32 +0000206INITIALIZE_PASS_END(MachineScheduler, DEBUG_TYPE,
Andrew Tricke77e84e2012-01-13 06:30:30 +0000207 "Machine Instruction Scheduler", false, false)
208
Eugene Zelenko32a40562017-09-11 23:00:48 +0000209MachineScheduler::MachineScheduler() : MachineSchedulerBase(ID) {
Andrew Tricke1c034f2012-01-17 06:55:03 +0000210 initializeMachineSchedulerPass(*PassRegistry::getPassRegistry());
Andrew Tricke77e84e2012-01-13 06:30:30 +0000211}
212
Andrew Tricke1c034f2012-01-17 06:55:03 +0000213void MachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const {
Andrew Tricke77e84e2012-01-13 06:30:30 +0000214 AU.setPreservesCFG();
Jakub Kuderski5be08ee2019-10-01 18:27:17 +0000215 AU.addRequired<MachineDominatorTree>();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000216 AU.addRequired<MachineLoopInfo>();
Chandler Carruth7b560d42015-09-09 17:55:00 +0000217 AU.addRequired<AAResultsWrapperPass>();
Andrew Trick45300682012-03-09 00:52:20 +0000218 AU.addRequired<TargetPassConfig>();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000219 AU.addRequired<SlotIndexes>();
220 AU.addPreserved<SlotIndexes>();
221 AU.addRequired<LiveIntervals>();
222 AU.addPreserved<LiveIntervals>();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000223 MachineFunctionPass::getAnalysisUsage(AU);
224}
225
Andrew Trick17080b92013-12-28 21:56:51 +0000226char PostMachineScheduler::ID = 0;
227
228char &llvm::PostMachineSchedulerID = PostMachineScheduler::ID;
229
230INITIALIZE_PASS(PostMachineScheduler, "postmisched",
Saleem Abdulrasool7230b372013-12-28 22:47:55 +0000231 "PostRA Machine Instruction Scheduler", false, false)
Andrew Trick17080b92013-12-28 21:56:51 +0000232
Eugene Zelenko32a40562017-09-11 23:00:48 +0000233PostMachineScheduler::PostMachineScheduler() : MachineSchedulerBase(ID) {
Andrew Trick17080b92013-12-28 21:56:51 +0000234 initializePostMachineSchedulerPass(*PassRegistry::getPassRegistry());
235}
236
237void PostMachineScheduler::getAnalysisUsage(AnalysisUsage &AU) const {
238 AU.setPreservesCFG();
Jakub Kuderski5be08ee2019-10-01 18:27:17 +0000239 AU.addRequired<MachineDominatorTree>();
Andrew Trick17080b92013-12-28 21:56:51 +0000240 AU.addRequired<MachineLoopInfo>();
241 AU.addRequired<TargetPassConfig>();
242 MachineFunctionPass::getAnalysisUsage(AU);
243}
244
Serge Guelton86f8b702018-11-09 17:19:45 +0000245MachinePassRegistry<MachineSchedRegistry::ScheduleDAGCtor>
246 MachineSchedRegistry::Registry;
Andrew Tricke77e84e2012-01-13 06:30:30 +0000247
Andrew Trick45300682012-03-09 00:52:20 +0000248/// A dummy default scheduler factory indicates whether the scheduler
249/// is overridden on the command line.
250static ScheduleDAGInstrs *useDefaultMachineSched(MachineSchedContext *C) {
Craig Topperc0196b12014-04-14 00:51:57 +0000251 return nullptr;
Andrew Trick45300682012-03-09 00:52:20 +0000252}
Andrew Tricke77e84e2012-01-13 06:30:30 +0000253
254/// MachineSchedOpt allows command line selection of the scheduler.
255static cl::opt<MachineSchedRegistry::ScheduleDAGCtor, false,
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000256 RegisterPassParser<MachineSchedRegistry>>
Andrew Tricke77e84e2012-01-13 06:30:30 +0000257MachineSchedOpt("misched",
Andrew Trick45300682012-03-09 00:52:20 +0000258 cl::init(&useDefaultMachineSched), cl::Hidden,
Andrew Tricke77e84e2012-01-13 06:30:30 +0000259 cl::desc("Machine instruction scheduler to use"));
260
Andrew Trick45300682012-03-09 00:52:20 +0000261static MachineSchedRegistry
Andrew Trick8823dec2012-03-14 04:00:41 +0000262DefaultSchedRegistry("default", "Use the target's default scheduler choice.",
Andrew Trick45300682012-03-09 00:52:20 +0000263 useDefaultMachineSched);
264
Eric Christopher5f141b02015-03-11 22:56:10 +0000265static cl::opt<bool> EnableMachineSched(
266 "enable-misched",
267 cl::desc("Enable the machine instruction scheduling pass."), cl::init(true),
268 cl::Hidden);
269
Chad Rosier816a1ab2016-01-20 23:08:32 +0000270static cl::opt<bool> EnablePostRAMachineSched(
271 "enable-post-misched",
272 cl::desc("Enable the post-ra machine instruction scheduling pass."),
273 cl::init(true), cl::Hidden);
274
Andrew Trickcc45a282012-04-24 18:04:34 +0000275/// Decrement this iterator until reaching the top or a non-debug instr.
Andrew Trick2bc74c22013-08-30 04:36:57 +0000276static MachineBasicBlock::const_iterator
277priorNonDebug(MachineBasicBlock::const_iterator I,
278 MachineBasicBlock::const_iterator Beg) {
Andrew Trickcc45a282012-04-24 18:04:34 +0000279 assert(I != Beg && "reached the top of the region, cannot decrement");
280 while (--I != Beg) {
Shiva Chen801bf7e2018-05-09 02:42:00 +0000281 if (!I->isDebugInstr())
Andrew Trickcc45a282012-04-24 18:04:34 +0000282 break;
283 }
284 return I;
285}
286
Andrew Trick2bc74c22013-08-30 04:36:57 +0000287/// Non-const version.
288static MachineBasicBlock::iterator
289priorNonDebug(MachineBasicBlock::iterator I,
290 MachineBasicBlock::const_iterator Beg) {
Duncan P. N. Exon Smithdcbce9c2016-08-16 23:34:07 +0000291 return priorNonDebug(MachineBasicBlock::const_iterator(I), Beg)
292 .getNonConstIterator();
Andrew Trick2bc74c22013-08-30 04:36:57 +0000293}
294
Andrew Trickcc45a282012-04-24 18:04:34 +0000295/// If this iterator is a debug value, increment until reaching the End or a
296/// non-debug instruction.
Andrew Trick2c4f8b72013-08-31 05:17:58 +0000297static MachineBasicBlock::const_iterator
298nextIfDebug(MachineBasicBlock::const_iterator I,
299 MachineBasicBlock::const_iterator End) {
Andrew Trick463b2f12012-05-17 18:35:03 +0000300 for(; I != End; ++I) {
Shiva Chen801bf7e2018-05-09 02:42:00 +0000301 if (!I->isDebugInstr())
Andrew Trickcc45a282012-04-24 18:04:34 +0000302 break;
303 }
304 return I;
305}
306
Andrew Trick2c4f8b72013-08-31 05:17:58 +0000307/// Non-const version.
308static MachineBasicBlock::iterator
309nextIfDebug(MachineBasicBlock::iterator I,
310 MachineBasicBlock::const_iterator End) {
Duncan P. N. Exon Smithdcbce9c2016-08-16 23:34:07 +0000311 return nextIfDebug(MachineBasicBlock::const_iterator(I), End)
312 .getNonConstIterator();
Andrew Trick2c4f8b72013-08-31 05:17:58 +0000313}
314
Andrew Trickdc4c1ad2013-09-24 17:11:19 +0000315/// Instantiate a ScheduleDAGInstrs that will be owned by the caller.
Andrew Trick978674b2013-09-20 05:14:41 +0000316ScheduleDAGInstrs *MachineScheduler::createMachineScheduler() {
317 // Select the scheduler, or set the default.
318 MachineSchedRegistry::ScheduleDAGCtor Ctor = MachineSchedOpt;
319 if (Ctor != useDefaultMachineSched)
320 return Ctor(this);
321
322 // Get the default scheduler set by the target for this function.
323 ScheduleDAGInstrs *Scheduler = PassConfig->createMachineScheduler(this);
324 if (Scheduler)
325 return Scheduler;
326
327 // Default to GenericScheduler.
Andrew Trickd14d7c22013-12-28 21:56:57 +0000328 return createGenericSchedLive(this);
Andrew Trick978674b2013-09-20 05:14:41 +0000329}
330
Andrew Trick17080b92013-12-28 21:56:51 +0000331/// Instantiate a ScheduleDAGInstrs for PostRA scheduling that will be owned by
332/// the caller. We don't have a command line option to override the postRA
333/// scheduler. The Target must configure it.
334ScheduleDAGInstrs *PostMachineScheduler::createPostMachineScheduler() {
335 // Get the postRA scheduler set by the target for this function.
336 ScheduleDAGInstrs *Scheduler = PassConfig->createPostMachineScheduler(this);
337 if (Scheduler)
338 return Scheduler;
339
340 // Default to GenericScheduler.
Andrew Trickd14d7c22013-12-28 21:56:57 +0000341 return createGenericSchedPostRA(this);
Andrew Trick17080b92013-12-28 21:56:51 +0000342}
343
Andrew Trick72515be2012-03-14 04:00:38 +0000344/// Top-level MachineScheduler pass driver.
345///
346/// Visit blocks in function order. Divide each block into scheduling regions
Andrew Trick8823dec2012-03-14 04:00:41 +0000347/// and visit them bottom-up. Visiting regions bottom-up is not required, but is
348/// consistent with the DAG builder, which traverses the interior of the
349/// scheduling regions bottom-up.
Andrew Trick72515be2012-03-14 04:00:38 +0000350///
351/// This design avoids exposing scheduling boundaries to the DAG builder,
Andrew Trick8823dec2012-03-14 04:00:41 +0000352/// simplifying the DAG builder's support for "special" target instructions.
353/// At the same time the design allows target schedulers to operate across
Hiroshi Inouec73b6d62018-06-20 05:29:26 +0000354/// scheduling boundaries, for example to bundle the boundary instructions
Andrew Trick72515be2012-03-14 04:00:38 +0000355/// without reordering them. This creates complexity, because the target
356/// scheduler must update the RegionBegin and RegionEnd positions cached by
357/// ScheduleDAGInstrs whenever adding or removing instructions. A much simpler
358/// design would be to split blocks at scheduling boundaries, but LLVM has a
359/// general bias against block splitting purely for implementation simplicity.
Andrew Tricke1c034f2012-01-17 06:55:03 +0000360bool MachineScheduler::runOnMachineFunction(MachineFunction &mf) {
Matthias Braunf1caa282017-12-15 22:22:58 +0000361 if (skipFunction(mf.getFunction()))
Chad Rosier6338d7c2016-01-20 22:38:25 +0000362 return false;
363
Eric Christopher5f141b02015-03-11 22:56:10 +0000364 if (EnableMachineSched.getNumOccurrences()) {
365 if (!EnableMachineSched)
366 return false;
367 } else if (!mf.getSubtarget().enableMachineScheduler())
368 return false;
369
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000370 LLVM_DEBUG(dbgs() << "Before MISched:\n"; mf.print(dbgs()));
Andrew Trickc5d70082012-05-10 21:06:21 +0000371
Andrew Tricke77e84e2012-01-13 06:30:30 +0000372 // Initialize the context of the pass.
373 MF = &mf;
374 MLI = &getAnalysis<MachineLoopInfo>();
375 MDT = &getAnalysis<MachineDominatorTree>();
Andrew Trick45300682012-03-09 00:52:20 +0000376 PassConfig = &getAnalysis<TargetPassConfig>();
Chandler Carruth7b560d42015-09-09 17:55:00 +0000377 AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
Andrew Trick02a80da2012-03-08 01:41:12 +0000378
Lang Hamesad33d5a2012-01-27 22:36:19 +0000379 LIS = &getAnalysis<LiveIntervals>();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000380
Andrew Trick48f2a722013-03-08 05:40:34 +0000381 if (VerifyScheduling) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000382 LLVM_DEBUG(LIS->dump());
Andrew Trick48f2a722013-03-08 05:40:34 +0000383 MF->verify(this, "Before machine scheduling.");
384 }
Andrew Trick4d4b5462012-04-24 20:36:19 +0000385 RegClassInfo->runOnMachineFunction(*MF);
Andrew Trick88639922012-04-24 17:56:43 +0000386
Andrew Trick978674b2013-09-20 05:14:41 +0000387 // Instantiate the selected scheduler for this target, function, and
388 // optimization level.
Ahmed Charles56440fd2014-03-06 05:51:42 +0000389 std::unique_ptr<ScheduleDAGInstrs> Scheduler(createMachineScheduler());
Matthias Braun93563e72015-11-03 01:53:29 +0000390 scheduleRegions(*Scheduler, false);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000391
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000392 LLVM_DEBUG(LIS->dump());
Andrew Trickd7f890e2013-12-28 21:56:47 +0000393 if (VerifyScheduling)
394 MF->verify(this, "After machine scheduling.");
395 return true;
396}
397
Andrew Trick17080b92013-12-28 21:56:51 +0000398bool PostMachineScheduler::runOnMachineFunction(MachineFunction &mf) {
Matthias Braunf1caa282017-12-15 22:22:58 +0000399 if (skipFunction(mf.getFunction()))
Paul Robinson7c99ec52014-03-31 17:43:35 +0000400 return false;
401
Chad Rosier816a1ab2016-01-20 23:08:32 +0000402 if (EnablePostRAMachineSched.getNumOccurrences()) {
403 if (!EnablePostRAMachineSched)
404 return false;
405 } else if (!mf.getSubtarget().enablePostRAScheduler()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000406 LLVM_DEBUG(dbgs() << "Subtarget disables post-MI-sched.\n");
Andrew Trick8d2ee372014-06-04 07:06:27 +0000407 return false;
408 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000409 LLVM_DEBUG(dbgs() << "Before post-MI-sched:\n"; mf.print(dbgs()));
Andrew Trick17080b92013-12-28 21:56:51 +0000410
411 // Initialize the context of the pass.
412 MF = &mf;
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000413 MLI = &getAnalysis<MachineLoopInfo>();
Andrew Trick17080b92013-12-28 21:56:51 +0000414 PassConfig = &getAnalysis<TargetPassConfig>();
415
416 if (VerifyScheduling)
417 MF->verify(this, "Before post machine scheduling.");
418
419 // Instantiate the selected scheduler for this target, function, and
420 // optimization level.
Ahmed Charles56440fd2014-03-06 05:51:42 +0000421 std::unique_ptr<ScheduleDAGInstrs> Scheduler(createPostMachineScheduler());
Matthias Braun93563e72015-11-03 01:53:29 +0000422 scheduleRegions(*Scheduler, true);
Andrew Trick17080b92013-12-28 21:56:51 +0000423
424 if (VerifyScheduling)
425 MF->verify(this, "After post machine scheduling.");
426 return true;
427}
428
Andrew Trickd14d7c22013-12-28 21:56:57 +0000429/// Return true of the given instruction should not be included in a scheduling
430/// region.
431///
432/// MachineScheduler does not currently support scheduling across calls. To
433/// handle calls, the DAG builder needs to be modified to create register
434/// anti/output dependencies on the registers clobbered by the call's regmask
435/// operand. In PreRA scheduling, the stack pointer adjustment already prevents
436/// scheduling across calls. In PostRA scheduling, we need the isCall to enforce
437/// the boundary, but there would be no benefit to postRA scheduling across
438/// calls this late anyway.
439static bool isSchedBoundary(MachineBasicBlock::iterator MI,
440 MachineBasicBlock *MBB,
441 MachineFunction *MF,
Matthias Braun93563e72015-11-03 01:53:29 +0000442 const TargetInstrInfo *TII) {
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +0000443 return MI->isCall() || TII->isSchedulingBoundary(*MI, MBB, *MF);
Andrew Trickd14d7c22013-12-28 21:56:57 +0000444}
445
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000446/// A region of an MBB for scheduling.
Mikael Holmen4eb2a962017-09-13 14:07:47 +0000447namespace {
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000448struct SchedRegion {
449 /// RegionBegin is the first instruction in the scheduling region, and
450 /// RegionEnd is either MBB->end() or the scheduling boundary after the
451 /// last instruction in the scheduling region. These iterators cannot refer
452 /// to instructions outside of the identified scheduling region because
453 /// those may be reordered before scheduling this region.
454 MachineBasicBlock::iterator RegionBegin;
455 MachineBasicBlock::iterator RegionEnd;
456 unsigned NumRegionInstrs;
Eugene Zelenko32a40562017-09-11 23:00:48 +0000457
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000458 SchedRegion(MachineBasicBlock::iterator B, MachineBasicBlock::iterator E,
459 unsigned N) :
460 RegionBegin(B), RegionEnd(E), NumRegionInstrs(N) {}
461};
Mikael Holmen4eb2a962017-09-13 14:07:47 +0000462} // end anonymous namespace
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000463
Eugene Zelenko32a40562017-09-11 23:00:48 +0000464using MBBRegionsVector = SmallVector<SchedRegion, 16>;
465
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000466static void
467getSchedRegions(MachineBasicBlock *MBB,
468 MBBRegionsVector &Regions,
469 bool RegionsTopDown) {
470 MachineFunction *MF = MBB->getParent();
471 const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
472
473 MachineBasicBlock::iterator I = nullptr;
474 for(MachineBasicBlock::iterator RegionEnd = MBB->end();
475 RegionEnd != MBB->begin(); RegionEnd = I) {
476
477 // Avoid decrementing RegionEnd for blocks with no terminator.
478 if (RegionEnd != MBB->end() ||
479 isSchedBoundary(&*std::prev(RegionEnd), &*MBB, MF, TII)) {
480 --RegionEnd;
481 }
482
483 // The next region starts above the previous region. Look backward in the
484 // instruction stream until we find the nearest boundary.
485 unsigned NumRegionInstrs = 0;
486 I = RegionEnd;
487 for (;I != MBB->begin(); --I) {
488 MachineInstr &MI = *std::prev(I);
489 if (isSchedBoundary(&MI, &*MBB, MF, TII))
490 break;
Matt Arsenaultb27e49742019-03-25 17:15:44 +0000491 if (!MI.isDebugInstr()) {
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000492 // MBB::size() uses instr_iterator to count. Here we need a bundle to
493 // count as a single instruction.
494 ++NumRegionInstrs;
Matt Arsenaultb27e49742019-03-25 17:15:44 +0000495 }
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000496 }
497
Matt Arsenaultb27e49742019-03-25 17:15:44 +0000498 // It's possible we found a scheduling region that only has debug
499 // instructions. Don't bother scheduling these.
500 if (NumRegionInstrs != 0)
501 Regions.push_back(SchedRegion(I, RegionEnd, NumRegionInstrs));
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000502 }
503
504 if (RegionsTopDown)
505 std::reverse(Regions.begin(), Regions.end());
506}
507
Andrew Trickd7f890e2013-12-28 21:56:47 +0000508/// Main driver for both MachineScheduler and PostMachineScheduler.
Matthias Braun93563e72015-11-03 01:53:29 +0000509void MachineSchedulerBase::scheduleRegions(ScheduleDAGInstrs &Scheduler,
510 bool FixKillFlags) {
Andrew Tricke77e84e2012-01-13 06:30:30 +0000511 // Visit all machine basic blocks.
Andrew Trick88639922012-04-24 17:56:43 +0000512 //
513 // TODO: Visit blocks in global postorder or postorder within the bottom-up
514 // loop tree. Then we can optionally compute global RegPressure.
Andrew Tricke77e84e2012-01-13 06:30:30 +0000515 for (MachineFunction::iterator MBB = MF->begin(), MBBEnd = MF->end();
516 MBB != MBBEnd; ++MBB) {
517
Duncan P. N. Exon Smith5ec15682015-10-09 19:40:45 +0000518 Scheduler.startBlock(&*MBB);
Andrew Trickedfe2ec2012-03-09 08:02:51 +0000519
Andrew Trick33e05d72013-12-28 21:57:02 +0000520#ifndef NDEBUG
521 if (SchedOnlyFunc.getNumOccurrences() && SchedOnlyFunc != MF->getName())
522 continue;
523 if (SchedOnlyBlock.getNumOccurrences()
524 && (int)SchedOnlyBlock != MBB->getNumber())
525 continue;
526#endif
527
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000528 // Break the block into scheduling regions [I, RegionEnd). RegionEnd
529 // points to the scheduling boundary at the bottom of the region. The DAG
530 // does not include RegionEnd, but the region does (i.e. the next
531 // RegionEnd is above the previous RegionBegin). If the current block has
532 // no terminator then RegionEnd == MBB->end() for the bottom region.
533 //
534 // All the regions of MBB are first found and stored in MBBRegions, which
535 // will be processed (MBB) top-down if initialized with true.
Andrew Trickaf1bee72012-03-09 22:34:56 +0000536 //
537 // The Scheduler may insert instructions during either schedule() or
538 // exitRegion(), even for empty regions. So the local iterators 'I' and
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000539 // 'RegionEnd' are invalid across these calls. Instructions must not be
540 // added to other regions than the current one without updating MBBRegions.
Andrew Trick88639922012-04-24 17:56:43 +0000541
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000542 MBBRegionsVector MBBRegions;
543 getSchedRegions(&*MBB, MBBRegions, Scheduler.doMBBSchedRegionsTopDown());
544 for (MBBRegionsVector::iterator R = MBBRegions.begin();
545 R != MBBRegions.end(); ++R) {
546 MachineBasicBlock::iterator I = R->RegionBegin;
547 MachineBasicBlock::iterator RegionEnd = R->RegionEnd;
548 unsigned NumRegionInstrs = R->NumRegionInstrs;
Andrew Trickedfe2ec2012-03-09 08:02:51 +0000549
Andrew Trick60cf03e2012-03-07 05:21:52 +0000550 // Notify the scheduler of the region, even if we may skip scheduling
551 // it. Perhaps it still needs to be bundled.
Duncan P. N. Exon Smith5ec15682015-10-09 19:40:45 +0000552 Scheduler.enterRegion(&*MBB, I, RegionEnd, NumRegionInstrs);
Andrew Trick60cf03e2012-03-07 05:21:52 +0000553
554 // Skip empty scheduling regions (0 or 1 schedulable instructions).
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +0000555 if (I == RegionEnd || I == std::prev(RegionEnd)) {
Andrew Trick60cf03e2012-03-07 05:21:52 +0000556 // Close the current region. Bundle the terminator if needed.
Andrew Trickaf1bee72012-03-09 22:34:56 +0000557 // This invalidates 'RegionEnd' and 'I'.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000558 Scheduler.exitRegion();
Andrew Trick7ccdc5c2012-01-17 06:55:07 +0000559 continue;
Andrew Trick59ac4fb2012-01-14 02:17:18 +0000560 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000561 LLVM_DEBUG(dbgs() << "********** MI Scheduling **********\n");
562 LLVM_DEBUG(dbgs() << MF->getName() << ":" << printMBBReference(*MBB)
563 << " " << MBB->getName() << "\n From: " << *I
564 << " To: ";
565 if (RegionEnd != MBB->end()) dbgs() << *RegionEnd;
566 else dbgs() << "End";
567 dbgs() << " RegionInstrs: " << NumRegionInstrs << '\n');
Gerolf Hoflehnerb5220dc2014-08-07 21:49:44 +0000568 if (DumpCriticalPathLength) {
569 errs() << MF->getName();
Francis Visoiu Mistrih25528d62017-12-04 17:18:51 +0000570 errs() << ":%bb. " << MBB->getNumber();
Gerolf Hoflehnerb5220dc2014-08-07 21:49:44 +0000571 errs() << " " << MBB->getName() << " \n";
572 }
Andrew Trick7ccdc5c2012-01-17 06:55:07 +0000573
Andrew Trick1c0ec452012-03-09 03:46:42 +0000574 // Schedule a region: possibly reorder instructions.
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000575 // This invalidates the original region iterators.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000576 Scheduler.schedule();
Andrew Trick1c0ec452012-03-09 03:46:42 +0000577
578 // Close the current region.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000579 Scheduler.exitRegion();
Andrew Trick7e120f42012-01-14 02:17:09 +0000580 }
Andrew Trickd7f890e2013-12-28 21:56:47 +0000581 Scheduler.finishBlock();
Matthias Braun93563e72015-11-03 01:53:29 +0000582 // FIXME: Ideally, no further passes should rely on kill flags. However,
583 // thumb2 size reduction is currently an exception, so the PostMIScheduler
584 // needs to do this.
585 if (FixKillFlags)
Matthias Braun868bbd42017-05-27 02:50:50 +0000586 Scheduler.fixupKills(*MBB);
Andrew Tricke77e84e2012-01-13 06:30:30 +0000587 }
Andrew Trickd7f890e2013-12-28 21:56:47 +0000588 Scheduler.finalizeSchedule();
Andrew Tricke77e84e2012-01-13 06:30:30 +0000589}
590
Andrew Trickd7f890e2013-12-28 21:56:47 +0000591void MachineSchedulerBase::print(raw_ostream &O, const Module* m) const {
Andrew Tricke77e84e2012-01-13 06:30:30 +0000592 // unimplemented
593}
594
Aaron Ballman615eb472017-10-15 14:32:27 +0000595#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Sam Clegg705f7982017-06-21 22:19:17 +0000596LLVM_DUMP_METHOD void ReadyQueue::dump() const {
James Y Knighte72b0db2015-09-18 18:52:20 +0000597 dbgs() << "Queue " << Name << ": ";
Javed Absare3a0cc22017-06-21 09:10:10 +0000598 for (const SUnit *SU : Queue)
599 dbgs() << SU->NodeNum << " ";
Andrew Trick7a8e1002012-09-11 00:39:15 +0000600 dbgs() << "\n";
601}
Matthias Braun8c209aa2017-01-28 02:02:38 +0000602#endif
Andrew Trick8823dec2012-03-14 04:00:41 +0000603
604//===----------------------------------------------------------------------===//
Andrew Trickd7f890e2013-12-28 21:56:47 +0000605// ScheduleDAGMI - Basic machine instruction scheduling. This is
606// independent of PreRA/PostRA scheduling and involves no extra book-keeping for
607// virtual registers.
608// ===----------------------------------------------------------------------===/
Andrew Trick8823dec2012-03-14 04:00:41 +0000609
David Blaikie422b93d2014-04-21 20:32:32 +0000610// Provide a vtable anchor.
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000611ScheduleDAGMI::~ScheduleDAGMI() = default;
Andrew Trick44f750a2013-01-25 04:01:04 +0000612
Andrew Trick02a80da2012-03-08 01:41:12 +0000613/// ReleaseSucc - Decrement the NumPredsLeft count of a successor. When
614/// NumPredsLeft reaches zero, release the successor node.
Andrew Trick61f1a272012-05-24 22:11:09 +0000615///
616/// FIXME: Adjust SuccSU height based on MinLatency.
Andrew Trick8823dec2012-03-14 04:00:41 +0000617void ScheduleDAGMI::releaseSucc(SUnit *SU, SDep *SuccEdge) {
Andrew Trick02a80da2012-03-08 01:41:12 +0000618 SUnit *SuccSU = SuccEdge->getSUnit();
619
Andrew Trickf1ff84c2012-11-12 19:28:57 +0000620 if (SuccEdge->isWeak()) {
621 --SuccSU->WeakPredsLeft;
Andrew Tricka7714a02012-11-12 19:40:10 +0000622 if (SuccEdge->isCluster())
623 NextClusterSucc = SuccSU;
Andrew Trickf1ff84c2012-11-12 19:28:57 +0000624 return;
625 }
Andrew Trick02a80da2012-03-08 01:41:12 +0000626#ifndef NDEBUG
627 if (SuccSU->NumPredsLeft == 0) {
628 dbgs() << "*** Scheduling failed! ***\n";
Matthias Braun726e12c2018-09-19 00:23:35 +0000629 dumpNode(*SuccSU);
Andrew Trick02a80da2012-03-08 01:41:12 +0000630 dbgs() << " has been released too many times!\n";
Craig Topperc0196b12014-04-14 00:51:57 +0000631 llvm_unreachable(nullptr);
Andrew Trick02a80da2012-03-08 01:41:12 +0000632 }
633#endif
Andrew Trick7f1ebbe2014-06-07 01:48:43 +0000634 // SU->TopReadyCycle was set to CurrCycle when it was scheduled. However,
635 // CurrCycle may have advanced since then.
636 if (SuccSU->TopReadyCycle < SU->TopReadyCycle + SuccEdge->getLatency())
637 SuccSU->TopReadyCycle = SU->TopReadyCycle + SuccEdge->getLatency();
638
Andrew Trick02a80da2012-03-08 01:41:12 +0000639 --SuccSU->NumPredsLeft;
640 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU)
Andrew Trick8823dec2012-03-14 04:00:41 +0000641 SchedImpl->releaseTopNode(SuccSU);
Andrew Trick02a80da2012-03-08 01:41:12 +0000642}
643
644/// releaseSuccessors - Call releaseSucc on each of SU's successors.
Andrew Trick8823dec2012-03-14 04:00:41 +0000645void ScheduleDAGMI::releaseSuccessors(SUnit *SU) {
Javed Absare3a0cc22017-06-21 09:10:10 +0000646 for (SDep &Succ : SU->Succs)
647 releaseSucc(SU, &Succ);
Andrew Trick02a80da2012-03-08 01:41:12 +0000648}
649
Andrew Trick8823dec2012-03-14 04:00:41 +0000650/// ReleasePred - Decrement the NumSuccsLeft count of a predecessor. When
651/// NumSuccsLeft reaches zero, release the predecessor node.
Andrew Trick61f1a272012-05-24 22:11:09 +0000652///
653/// FIXME: Adjust PredSU height based on MinLatency.
Andrew Trick8823dec2012-03-14 04:00:41 +0000654void ScheduleDAGMI::releasePred(SUnit *SU, SDep *PredEdge) {
655 SUnit *PredSU = PredEdge->getSUnit();
656
Andrew Trickf1ff84c2012-11-12 19:28:57 +0000657 if (PredEdge->isWeak()) {
658 --PredSU->WeakSuccsLeft;
Andrew Tricka7714a02012-11-12 19:40:10 +0000659 if (PredEdge->isCluster())
660 NextClusterPred = PredSU;
Andrew Trickf1ff84c2012-11-12 19:28:57 +0000661 return;
662 }
Andrew Trick8823dec2012-03-14 04:00:41 +0000663#ifndef NDEBUG
664 if (PredSU->NumSuccsLeft == 0) {
665 dbgs() << "*** Scheduling failed! ***\n";
Matthias Braun726e12c2018-09-19 00:23:35 +0000666 dumpNode(*PredSU);
Andrew Trick8823dec2012-03-14 04:00:41 +0000667 dbgs() << " has been released too many times!\n";
Craig Topperc0196b12014-04-14 00:51:57 +0000668 llvm_unreachable(nullptr);
Andrew Trick8823dec2012-03-14 04:00:41 +0000669 }
670#endif
Andrew Trick7f1ebbe2014-06-07 01:48:43 +0000671 // SU->BotReadyCycle was set to CurrCycle when it was scheduled. However,
672 // CurrCycle may have advanced since then.
673 if (PredSU->BotReadyCycle < SU->BotReadyCycle + PredEdge->getLatency())
674 PredSU->BotReadyCycle = SU->BotReadyCycle + PredEdge->getLatency();
675
Andrew Trick8823dec2012-03-14 04:00:41 +0000676 --PredSU->NumSuccsLeft;
677 if (PredSU->NumSuccsLeft == 0 && PredSU != &EntrySU)
678 SchedImpl->releaseBottomNode(PredSU);
679}
680
681/// releasePredecessors - Call releasePred on each of SU's predecessors.
682void ScheduleDAGMI::releasePredecessors(SUnit *SU) {
Javed Absare3a0cc22017-06-21 09:10:10 +0000683 for (SDep &Pred : SU->Preds)
684 releasePred(SU, &Pred);
Andrew Trick8823dec2012-03-14 04:00:41 +0000685}
686
Jonas Paulsson57a705d2017-08-17 08:33:44 +0000687void ScheduleDAGMI::startBlock(MachineBasicBlock *bb) {
688 ScheduleDAGInstrs::startBlock(bb);
689 SchedImpl->enterMBB(bb);
690}
691
692void ScheduleDAGMI::finishBlock() {
693 SchedImpl->leaveMBB();
694 ScheduleDAGInstrs::finishBlock();
695}
696
Andrew Trickd7f890e2013-12-28 21:56:47 +0000697/// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
698/// crossing a scheduling boundary. [begin, end) includes all instructions in
699/// the region, including the boundary itself and single-instruction regions
700/// that don't get scheduled.
701void ScheduleDAGMI::enterRegion(MachineBasicBlock *bb,
702 MachineBasicBlock::iterator begin,
703 MachineBasicBlock::iterator end,
704 unsigned regioninstrs)
705{
706 ScheduleDAGInstrs::enterRegion(bb, begin, end, regioninstrs);
707
708 SchedImpl->initPolicy(begin, end, regioninstrs);
709}
710
Andrew Tricke833e1c2013-04-13 06:07:40 +0000711/// This is normally called from the main scheduler loop but may also be invoked
712/// by the scheduling strategy to perform additional code motion.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000713void ScheduleDAGMI::moveInstruction(
714 MachineInstr *MI, MachineBasicBlock::iterator InsertPos) {
Andrew Trick463b2f12012-05-17 18:35:03 +0000715 // Advance RegionBegin if the first instruction moves down.
Andrew Trick54f7def2012-03-21 04:12:10 +0000716 if (&*RegionBegin == MI)
Andrew Trick463b2f12012-05-17 18:35:03 +0000717 ++RegionBegin;
718
719 // Update the instruction stream.
Andrew Trick8823dec2012-03-14 04:00:41 +0000720 BB->splice(InsertPos, BB, MI);
Andrew Trick463b2f12012-05-17 18:35:03 +0000721
722 // Update LiveIntervals
Andrew Trickd7f890e2013-12-28 21:56:47 +0000723 if (LIS)
Duncan P. N. Exon Smithbe8f8c42016-02-27 20:14:29 +0000724 LIS->handleMove(*MI, /*UpdateFlags=*/true);
Andrew Trick463b2f12012-05-17 18:35:03 +0000725
726 // Recede RegionBegin if an instruction moves above the first.
Andrew Trick8823dec2012-03-14 04:00:41 +0000727 if (RegionBegin == InsertPos)
728 RegionBegin = MI;
729}
730
Andrew Trickde670c02012-03-21 04:12:07 +0000731bool ScheduleDAGMI::checkSchedLimit() {
732#ifndef NDEBUG
733 if (NumInstrsScheduled == MISchedCutoff && MISchedCutoff != ~0U) {
734 CurrentTop = CurrentBottom;
735 return false;
736 }
737 ++NumInstrsScheduled;
738#endif
739 return true;
740}
741
Andrew Trickd7f890e2013-12-28 21:56:47 +0000742/// Per-region scheduling driver, called back from
743/// MachineScheduler::runOnMachineFunction. This is a simplified driver that
744/// does not consider liveness or register pressure. It is useful for PostRA
745/// scheduling and potentially other custom schedulers.
746void ScheduleDAGMI::schedule() {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000747 LLVM_DEBUG(dbgs() << "ScheduleDAGMI::schedule starting\n");
748 LLVM_DEBUG(SchedImpl->dumpPolicy());
James Y Knighte72b0db2015-09-18 18:52:20 +0000749
Andrew Trickd7f890e2013-12-28 21:56:47 +0000750 // Build the DAG.
751 buildSchedGraph(AA);
752
Andrew Trickd7f890e2013-12-28 21:56:47 +0000753 postprocessDAG();
754
755 SmallVector<SUnit*, 8> TopRoots, BotRoots;
756 findRootsAndBiasEdges(TopRoots, BotRoots);
757
Matthias Braun726e12c2018-09-19 00:23:35 +0000758 LLVM_DEBUG(dump());
Matthias Braun3136e422018-09-19 20:50:49 +0000759 if (PrintDAGs) dump();
Andrew Trickd7f890e2013-12-28 21:56:47 +0000760 if (ViewMISchedDAGs) viewGraph();
761
Jonas Paulssonbc32f7d2018-03-05 16:31:49 +0000762 // Initialize the strategy before modifying the DAG.
763 // This may initialize a DFSResult to be used for queue priority.
764 SchedImpl->initialize(this);
765
Andrew Trickd7f890e2013-12-28 21:56:47 +0000766 // Initialize ready queues now that the DAG and priority data are finalized.
767 initQueues(TopRoots, BotRoots);
768
769 bool IsTopNode = false;
James Y Knighte72b0db2015-09-18 18:52:20 +0000770 while (true) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000771 LLVM_DEBUG(dbgs() << "** ScheduleDAGMI::schedule picking next node\n");
James Y Knighte72b0db2015-09-18 18:52:20 +0000772 SUnit *SU = SchedImpl->pickNode(IsTopNode);
773 if (!SU) break;
774
Andrew Trickd7f890e2013-12-28 21:56:47 +0000775 assert(!SU->isScheduled && "Node already scheduled");
776 if (!checkSchedLimit())
777 break;
778
779 MachineInstr *MI = SU->getInstr();
780 if (IsTopNode) {
781 assert(SU->isTopReady() && "node still has unscheduled dependencies");
782 if (&*CurrentTop == MI)
783 CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
784 else
785 moveInstruction(MI, CurrentTop);
Matthias Braunb550b762016-04-21 01:54:13 +0000786 } else {
Andrew Trickd7f890e2013-12-28 21:56:47 +0000787 assert(SU->isBottomReady() && "node still has unscheduled dependencies");
788 MachineBasicBlock::iterator priorII =
789 priorNonDebug(CurrentBottom, CurrentTop);
790 if (&*priorII == MI)
791 CurrentBottom = priorII;
792 else {
793 if (&*CurrentTop == MI)
794 CurrentTop = nextIfDebug(++CurrentTop, priorII);
795 moveInstruction(MI, CurrentBottom);
796 CurrentBottom = MI;
797 }
798 }
Andrew Trick7f1ebbe2014-06-07 01:48:43 +0000799 // Notify the scheduling strategy before updating the DAG.
Andrew Trick491e34a2014-06-12 22:36:28 +0000800 // This sets the scheduled node's ReadyCycle to CurrCycle. When updateQueues
Andrew Trick7f1ebbe2014-06-07 01:48:43 +0000801 // runs, it can then use the accurate ReadyCycle time to determine whether
802 // newly released nodes can move to the readyQ.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000803 SchedImpl->schedNode(SU, IsTopNode);
Andrew Trick7f1ebbe2014-06-07 01:48:43 +0000804
805 updateQueues(SU, IsTopNode);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000806 }
807 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
808
809 placeDebugValues();
810
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000811 LLVM_DEBUG({
Francis Visoiu Mistrih25528d62017-12-04 17:18:51 +0000812 dbgs() << "*** Final schedule for "
813 << printMBBReference(*begin()->getParent()) << " ***\n";
814 dumpSchedule();
815 dbgs() << '\n';
816 });
Andrew Trickd7f890e2013-12-28 21:56:47 +0000817}
818
819/// Apply each ScheduleDAGMutation step in order.
820void ScheduleDAGMI::postprocessDAG() {
Javed Absare3a0cc22017-06-21 09:10:10 +0000821 for (auto &m : Mutations)
822 m->apply(this);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000823}
824
825void ScheduleDAGMI::
826findRootsAndBiasEdges(SmallVectorImpl<SUnit*> &TopRoots,
827 SmallVectorImpl<SUnit*> &BotRoots) {
Javed Absare3a0cc22017-06-21 09:10:10 +0000828 for (SUnit &SU : SUnits) {
829 assert(!SU.isBoundaryNode() && "Boundary node should not be in SUnits");
Andrew Trickd7f890e2013-12-28 21:56:47 +0000830
831 // Order predecessors so DFSResult follows the critical path.
Javed Absare3a0cc22017-06-21 09:10:10 +0000832 SU.biasCriticalPath();
Andrew Trickd7f890e2013-12-28 21:56:47 +0000833
834 // A SUnit is ready to top schedule if it has no predecessors.
Javed Absare3a0cc22017-06-21 09:10:10 +0000835 if (!SU.NumPredsLeft)
836 TopRoots.push_back(&SU);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000837 // A SUnit is ready to bottom schedule if it has no successors.
Javed Absare3a0cc22017-06-21 09:10:10 +0000838 if (!SU.NumSuccsLeft)
839 BotRoots.push_back(&SU);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000840 }
841 ExitSU.biasCriticalPath();
842}
843
844/// Identify DAG roots and setup scheduler queues.
845void ScheduleDAGMI::initQueues(ArrayRef<SUnit*> TopRoots,
846 ArrayRef<SUnit*> BotRoots) {
Craig Topperc0196b12014-04-14 00:51:57 +0000847 NextClusterSucc = nullptr;
848 NextClusterPred = nullptr;
Andrew Trickd7f890e2013-12-28 21:56:47 +0000849
850 // Release all DAG roots for scheduling, not including EntrySU/ExitSU.
851 //
852 // Nodes with unreleased weak edges can still be roots.
853 // Release top roots in forward order.
Javed Absare3a0cc22017-06-21 09:10:10 +0000854 for (SUnit *SU : TopRoots)
855 SchedImpl->releaseTopNode(SU);
856
Andrew Trickd7f890e2013-12-28 21:56:47 +0000857 // Release bottom roots in reverse order so the higher priority nodes appear
858 // first. This is more natural and slightly more efficient.
859 for (SmallVectorImpl<SUnit*>::const_reverse_iterator
860 I = BotRoots.rbegin(), E = BotRoots.rend(); I != E; ++I) {
861 SchedImpl->releaseBottomNode(*I);
862 }
863
864 releaseSuccessors(&EntrySU);
865 releasePredecessors(&ExitSU);
866
867 SchedImpl->registerRoots();
868
869 // Advance past initial DebugValues.
870 CurrentTop = nextIfDebug(RegionBegin, RegionEnd);
871 CurrentBottom = RegionEnd;
872}
873
874/// Update scheduler queues after scheduling an instruction.
875void ScheduleDAGMI::updateQueues(SUnit *SU, bool IsTopNode) {
876 // Release dependent instructions for scheduling.
877 if (IsTopNode)
878 releaseSuccessors(SU);
879 else
880 releasePredecessors(SU);
881
882 SU->isScheduled = true;
883}
884
885/// Reinsert any remaining debug_values, just like the PostRA scheduler.
886void ScheduleDAGMI::placeDebugValues() {
887 // If first instruction was a DBG_VALUE then put it back.
888 if (FirstDbgValue) {
889 BB->splice(RegionBegin, BB, FirstDbgValue);
890 RegionBegin = FirstDbgValue;
891 }
892
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +0000893 for (std::vector<std::pair<MachineInstr *, MachineInstr *>>::iterator
Andrew Trickd7f890e2013-12-28 21:56:47 +0000894 DI = DbgValues.end(), DE = DbgValues.begin(); DI != DE; --DI) {
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +0000895 std::pair<MachineInstr *, MachineInstr *> P = *std::prev(DI);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000896 MachineInstr *DbgValue = P.first;
897 MachineBasicBlock::iterator OrigPrevMI = P.second;
898 if (&*RegionBegin == DbgValue)
899 ++RegionBegin;
900 BB->splice(++OrigPrevMI, BB, DbgValue);
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +0000901 if (OrigPrevMI == std::prev(RegionEnd))
Andrew Trickd7f890e2013-12-28 21:56:47 +0000902 RegionEnd = DbgValue;
903 }
904 DbgValues.clear();
Craig Topperc0196b12014-04-14 00:51:57 +0000905 FirstDbgValue = nullptr;
Andrew Trickd7f890e2013-12-28 21:56:47 +0000906}
907
Aaron Ballman615eb472017-10-15 14:32:27 +0000908#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Matthias Braun8c209aa2017-01-28 02:02:38 +0000909LLVM_DUMP_METHOD void ScheduleDAGMI::dumpSchedule() const {
Andrew Trickd7f890e2013-12-28 21:56:47 +0000910 for (MachineBasicBlock::iterator MI = begin(), ME = end(); MI != ME; ++MI) {
911 if (SUnit *SU = getSUnit(&(*MI)))
Matthias Braun726e12c2018-09-19 00:23:35 +0000912 dumpNode(*SU);
Andrew Trickd7f890e2013-12-28 21:56:47 +0000913 else
914 dbgs() << "Missing SUnit\n";
915 }
916}
917#endif
918
919//===----------------------------------------------------------------------===//
920// ScheduleDAGMILive - Base class for MachineInstr scheduling with LiveIntervals
921// preservation.
922//===----------------------------------------------------------------------===//
923
924ScheduleDAGMILive::~ScheduleDAGMILive() {
925 delete DFSResult;
926}
927
Matthias Braun40639882016-11-11 22:37:31 +0000928void ScheduleDAGMILive::collectVRegUses(SUnit &SU) {
929 const MachineInstr &MI = *SU.getInstr();
930 for (const MachineOperand &MO : MI.operands()) {
931 if (!MO.isReg())
932 continue;
933 if (!MO.readsReg())
934 continue;
935 if (TrackLaneMasks && !MO.isUse())
936 continue;
937
Daniel Sanders0c476112019-08-15 19:22:08 +0000938 Register Reg = MO.getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +0000939 if (!Register::isVirtualRegister(Reg))
Matthias Braun40639882016-11-11 22:37:31 +0000940 continue;
941
942 // Ignore re-defs.
943 if (TrackLaneMasks) {
944 bool FoundDef = false;
945 for (const MachineOperand &MO2 : MI.operands()) {
946 if (MO2.isReg() && MO2.isDef() && MO2.getReg() == Reg && !MO2.isDead()) {
947 FoundDef = true;
948 break;
949 }
950 }
951 if (FoundDef)
952 continue;
953 }
954
955 // Record this local VReg use.
956 VReg2SUnitMultiMap::iterator UI = VRegUses.find(Reg);
957 for (; UI != VRegUses.end(); ++UI) {
958 if (UI->SU == &SU)
959 break;
960 }
961 if (UI == VRegUses.end())
Krzysztof Parzyszek91b5cf82016-12-15 14:36:06 +0000962 VRegUses.insert(VReg2SUnit(Reg, LaneBitmask::getNone(), &SU));
Matthias Braun40639882016-11-11 22:37:31 +0000963 }
964}
965
Andrew Trick88639922012-04-24 17:56:43 +0000966/// enterRegion - Called back from MachineScheduler::runOnMachineFunction after
967/// crossing a scheduling boundary. [begin, end) includes all instructions in
968/// the region, including the boundary itself and single-instruction regions
969/// that don't get scheduled.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000970void ScheduleDAGMILive::enterRegion(MachineBasicBlock *bb,
Andrew Trick88639922012-04-24 17:56:43 +0000971 MachineBasicBlock::iterator begin,
972 MachineBasicBlock::iterator end,
Andrew Tricka53e1012013-08-23 17:48:33 +0000973 unsigned regioninstrs)
Andrew Trick88639922012-04-24 17:56:43 +0000974{
Andrew Trickd7f890e2013-12-28 21:56:47 +0000975 // ScheduleDAGMI initializes SchedImpl's per-region policy.
976 ScheduleDAGMI::enterRegion(bb, begin, end, regioninstrs);
Andrew Trick4add42f2012-05-10 21:06:10 +0000977
978 // For convenience remember the end of the liveness region.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +0000979 LiveRegionEnd = (RegionEnd == bb->end()) ? RegionEnd : std::next(RegionEnd);
Andrew Trick75e411c2013-09-06 17:32:34 +0000980
Andrew Trickb248b4a2013-09-06 17:32:47 +0000981 SUPressureDiffs.clear();
982
Andrew Trick75e411c2013-09-06 17:32:34 +0000983 ShouldTrackPressure = SchedImpl->shouldTrackPressure();
Matthias Braund4f64092016-01-20 00:23:32 +0000984 ShouldTrackLaneMasks = SchedImpl->shouldTrackLaneMasks();
985
Matthias Braunf9acaca2016-05-31 22:38:06 +0000986 assert((!ShouldTrackLaneMasks || ShouldTrackPressure) &&
987 "ShouldTrackLaneMasks requires ShouldTrackPressure");
Andrew Trick4add42f2012-05-10 21:06:10 +0000988}
989
Mingjie Xing4b191772019-09-14 03:27:38 +0000990// Setup the register pressure trackers for the top scheduled and bottom
Andrew Trick4add42f2012-05-10 21:06:10 +0000991// scheduled regions.
Andrew Trickd7f890e2013-12-28 21:56:47 +0000992void ScheduleDAGMILive::initRegPressure() {
Matthias Braun40639882016-11-11 22:37:31 +0000993 VRegUses.clear();
994 VRegUses.setUniverse(MRI.getNumVirtRegs());
995 for (SUnit &SU : SUnits)
996 collectVRegUses(SU);
997
Matthias Braund4f64092016-01-20 00:23:32 +0000998 TopRPTracker.init(&MF, RegClassInfo, LIS, BB, RegionBegin,
999 ShouldTrackLaneMasks, false);
1000 BotRPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
1001 ShouldTrackLaneMasks, false);
Andrew Trick4add42f2012-05-10 21:06:10 +00001002
1003 // Close the RPTracker to finalize live ins.
1004 RPTracker.closeRegion();
1005
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001006 LLVM_DEBUG(RPTracker.dump());
Andrew Trick79d3eec2012-05-24 22:11:14 +00001007
Andrew Trick4add42f2012-05-10 21:06:10 +00001008 // Initialize the live ins and live outs.
Matthias Braun3e86de12015-09-17 21:12:24 +00001009 TopRPTracker.addLiveRegs(RPTracker.getPressure().LiveInRegs);
1010 BotRPTracker.addLiveRegs(RPTracker.getPressure().LiveOutRegs);
Andrew Trick4add42f2012-05-10 21:06:10 +00001011
1012 // Close one end of the tracker so we can call
1013 // getMaxUpward/DownwardPressureDelta before advancing across any
1014 // instructions. This converts currently live regs into live ins/outs.
1015 TopRPTracker.closeTop();
1016 BotRPTracker.closeBottom();
1017
Andrew Trick9c17eab2013-07-30 19:59:12 +00001018 BotRPTracker.initLiveThru(RPTracker);
1019 if (!BotRPTracker.getLiveThru().empty()) {
1020 TopRPTracker.initLiveThru(BotRPTracker.getLiveThru());
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001021 LLVM_DEBUG(dbgs() << "Live Thru: ";
1022 dumpRegSetPressure(BotRPTracker.getLiveThru(), TRI));
Andrew Trick9c17eab2013-07-30 19:59:12 +00001023 };
1024
Andrew Trick2bc74c22013-08-30 04:36:57 +00001025 // For each live out vreg reduce the pressure change associated with other
1026 // uses of the same vreg below the live-out reaching def.
Matthias Braun3e86de12015-09-17 21:12:24 +00001027 updatePressureDiffs(RPTracker.getPressure().LiveOutRegs);
Andrew Trick2bc74c22013-08-30 04:36:57 +00001028
Andrew Trick4add42f2012-05-10 21:06:10 +00001029 // Account for liveness generated by the region boundary.
Andrew Trick2bc74c22013-08-30 04:36:57 +00001030 if (LiveRegionEnd != RegionEnd) {
Matthias Braun5d458612016-01-20 00:23:26 +00001031 SmallVector<RegisterMaskPair, 8> LiveUses;
Andrew Trick2bc74c22013-08-30 04:36:57 +00001032 BotRPTracker.recede(&LiveUses);
1033 updatePressureDiffs(LiveUses);
1034 }
Andrew Trick4add42f2012-05-10 21:06:10 +00001035
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001036 LLVM_DEBUG(dbgs() << "Top Pressure:\n";
1037 dumpRegSetPressure(TopRPTracker.getRegSetPressureAtPos(), TRI);
1038 dbgs() << "Bottom Pressure:\n";
1039 dumpRegSetPressure(BotRPTracker.getRegSetPressureAtPos(), TRI););
Matthias Braune6edd482015-11-13 22:30:31 +00001040
Yaxun Liuc41e2f62017-12-15 03:56:57 +00001041 assert((BotRPTracker.getPos() == RegionEnd ||
Shiva Chen801bf7e2018-05-09 02:42:00 +00001042 (RegionEnd->isDebugInstr() &&
Yaxun Liuc41e2f62017-12-15 03:56:57 +00001043 BotRPTracker.getPos() == priorNonDebug(RegionEnd, RegionBegin))) &&
1044 "Can't find the region bottom");
Andrew Trick22025772012-05-17 18:35:10 +00001045
1046 // Cache the list of excess pressure sets in this region. This will also track
1047 // the max pressure in the scheduled code for these sets.
1048 RegionCriticalPSets.clear();
Jakub Staszakc641ada2013-01-25 21:44:27 +00001049 const std::vector<unsigned> &RegionPressure =
1050 RPTracker.getPressure().MaxSetPressure;
Andrew Trick22025772012-05-17 18:35:10 +00001051 for (unsigned i = 0, e = RegionPressure.size(); i < e; ++i) {
Andrew Trick736dd9a2013-06-21 18:32:58 +00001052 unsigned Limit = RegClassInfo->getRegPressureSetLimit(i);
Andrew Trickb55db582013-06-21 18:33:01 +00001053 if (RegionPressure[i] > Limit) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001054 LLVM_DEBUG(dbgs() << TRI->getRegPressureSetName(i) << " Limit " << Limit
1055 << " Actual " << RegionPressure[i] << "\n");
Andrew Trick1a831342013-08-30 03:49:48 +00001056 RegionCriticalPSets.push_back(PressureChange(i));
Andrew Trickb55db582013-06-21 18:33:01 +00001057 }
Andrew Trick22025772012-05-17 18:35:10 +00001058 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001059 LLVM_DEBUG(dbgs() << "Excess PSets: ";
1060 for (const PressureChange &RCPS
1061 : RegionCriticalPSets) dbgs()
1062 << TRI->getRegPressureSetName(RCPS.getPSet()) << " ";
1063 dbgs() << "\n");
Andrew Trick22025772012-05-17 18:35:10 +00001064}
1065
Andrew Trickd7f890e2013-12-28 21:56:47 +00001066void ScheduleDAGMILive::
Andrew Trickb248b4a2013-09-06 17:32:47 +00001067updateScheduledPressure(const SUnit *SU,
1068 const std::vector<unsigned> &NewMaxPressure) {
1069 const PressureDiff &PDiff = getPressureDiff(SU);
1070 unsigned CritIdx = 0, CritEnd = RegionCriticalPSets.size();
Javed Absare3a0cc22017-06-21 09:10:10 +00001071 for (const PressureChange &PC : PDiff) {
1072 if (!PC.isValid())
Andrew Trickb248b4a2013-09-06 17:32:47 +00001073 break;
Javed Absare3a0cc22017-06-21 09:10:10 +00001074 unsigned ID = PC.getPSet();
Andrew Trickb248b4a2013-09-06 17:32:47 +00001075 while (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() < ID)
1076 ++CritIdx;
1077 if (CritIdx != CritEnd && RegionCriticalPSets[CritIdx].getPSet() == ID) {
1078 if ((int)NewMaxPressure[ID] > RegionCriticalPSets[CritIdx].getUnitInc()
Simon Pilgrim858d8e62017-02-23 12:00:34 +00001079 && NewMaxPressure[ID] <= (unsigned)std::numeric_limits<int16_t>::max())
Andrew Trickb248b4a2013-09-06 17:32:47 +00001080 RegionCriticalPSets[CritIdx].setUnitInc(NewMaxPressure[ID]);
1081 }
1082 unsigned Limit = RegClassInfo->getRegPressureSetLimit(ID);
1083 if (NewMaxPressure[ID] >= Limit - 2) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001084 LLVM_DEBUG(dbgs() << " " << TRI->getRegPressureSetName(ID) << ": "
1085 << NewMaxPressure[ID]
1086 << ((NewMaxPressure[ID] > Limit) ? " > " : " <= ")
1087 << Limit << "(+ " << BotRPTracker.getLiveThru()[ID]
1088 << " livethru)\n");
Andrew Trickb248b4a2013-09-06 17:32:47 +00001089 }
Andrew Trick22025772012-05-17 18:35:10 +00001090 }
Andrew Trick88639922012-04-24 17:56:43 +00001091}
1092
Andrew Trick2bc74c22013-08-30 04:36:57 +00001093/// Update the PressureDiff array for liveness after scheduling this
1094/// instruction.
Matthias Braun5d458612016-01-20 00:23:26 +00001095void ScheduleDAGMILive::updatePressureDiffs(
1096 ArrayRef<RegisterMaskPair> LiveUses) {
1097 for (const RegisterMaskPair &P : LiveUses) {
Matthias Braun5d458612016-01-20 00:23:26 +00001098 unsigned Reg = P.RegUnit;
Matthias Braund4f64092016-01-20 00:23:32 +00001099 /// FIXME: Currently assuming single-use physregs.
Daniel Sanders2bea69b2019-08-01 23:27:28 +00001100 if (!Register::isVirtualRegister(Reg))
Andrew Trick2bc74c22013-08-30 04:36:57 +00001101 continue;
Andrew Trickffdbefb2013-09-06 17:32:39 +00001102
Matthias Braund4f64092016-01-20 00:23:32 +00001103 if (ShouldTrackLaneMasks) {
1104 // If the register has just become live then other uses won't change
1105 // this fact anymore => decrement pressure.
1106 // If the register has just become dead then other uses make it come
1107 // back to life => increment pressure.
Krzysztof Parzyszekea9f8ce2016-12-16 19:11:56 +00001108 bool Decrement = P.LaneMask.any();
Matthias Braund4f64092016-01-20 00:23:32 +00001109
1110 for (const VReg2SUnit &V2SU
1111 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1112 SUnit &SU = *V2SU.SU;
1113 if (SU.isScheduled || &SU == &ExitSU)
1114 continue;
1115
1116 PressureDiff &PDiff = getPressureDiff(&SU);
Stanislav Mekhanoshin42259cf2017-02-24 21:56:16 +00001117 PDiff.addPressureChange(Reg, Decrement, &MRI);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001118 LLVM_DEBUG(dbgs() << " UpdateRegP: SU(" << SU.NodeNum << ") "
1119 << printReg(Reg, TRI) << ':'
1120 << PrintLaneMask(P.LaneMask) << ' ' << *SU.getInstr();
1121 dbgs() << " to "; PDiff.dump(*TRI););
Matthias Braund4f64092016-01-20 00:23:32 +00001122 }
1123 } else {
Krzysztof Parzyszekea9f8ce2016-12-16 19:11:56 +00001124 assert(P.LaneMask.any());
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001125 LLVM_DEBUG(dbgs() << " LiveReg: " << printVRegOrUnit(Reg, TRI) << "\n");
Matthias Braund4f64092016-01-20 00:23:32 +00001126 // This may be called before CurrentBottom has been initialized. However,
1127 // BotRPTracker must have a valid position. We want the value live into the
1128 // instruction or live out of the block, so ask for the previous
1129 // instruction's live-out.
1130 const LiveInterval &LI = LIS->getInterval(Reg);
1131 VNInfo *VNI;
1132 MachineBasicBlock::const_iterator I =
1133 nextIfDebug(BotRPTracker.getPos(), BB->end());
1134 if (I == BB->end())
1135 VNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
1136 else {
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001137 LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*I));
Matthias Braund4f64092016-01-20 00:23:32 +00001138 VNI = LRQ.valueIn();
1139 }
1140 // RegisterPressureTracker guarantees that readsReg is true for LiveUses.
1141 assert(VNI && "No live value at use.");
1142 for (const VReg2SUnit &V2SU
1143 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1144 SUnit *SU = V2SU.SU;
1145 // If this use comes before the reaching def, it cannot be a last use,
1146 // so decrease its pressure change.
1147 if (!SU->isScheduled && SU != &ExitSU) {
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001148 LiveQueryResult LRQ =
1149 LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
Matthias Braund4f64092016-01-20 00:23:32 +00001150 if (LRQ.valueIn() == VNI) {
1151 PressureDiff &PDiff = getPressureDiff(SU);
Stanislav Mekhanoshin42259cf2017-02-24 21:56:16 +00001152 PDiff.addPressureChange(Reg, true, &MRI);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001153 LLVM_DEBUG(dbgs() << " UpdateRegP: SU(" << SU->NodeNum << ") "
1154 << *SU->getInstr();
1155 dbgs() << " to "; PDiff.dump(*TRI););
Matthias Braund4f64092016-01-20 00:23:32 +00001156 }
Matthias Braun9198c672015-11-06 20:59:02 +00001157 }
Andrew Trick2bc74c22013-08-30 04:36:57 +00001158 }
1159 }
1160 }
1161}
1162
Matthias Braun726e12c2018-09-19 00:23:35 +00001163void ScheduleDAGMILive::dump() const {
1164#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1165 if (EntrySU.getInstr() != nullptr)
1166 dumpNodeAll(EntrySU);
1167 for (const SUnit &SU : SUnits) {
1168 dumpNodeAll(SU);
1169 if (ShouldTrackPressure) {
1170 dbgs() << " Pressure Diff : ";
1171 getPressureDiff(&SU).dump(*TRI);
1172 }
1173 dbgs() << " Single Issue : ";
1174 if (SchedModel.mustBeginGroup(SU.getInstr()) &&
1175 SchedModel.mustEndGroup(SU.getInstr()))
1176 dbgs() << "true;";
1177 else
1178 dbgs() << "false;";
1179 dbgs() << '\n';
1180 }
1181 if (ExitSU.getInstr() != nullptr)
1182 dumpNodeAll(ExitSU);
1183#endif
1184}
1185
Andrew Trick8823dec2012-03-14 04:00:41 +00001186/// schedule - Called back from MachineScheduler::runOnMachineFunction
Andrew Trick88639922012-04-24 17:56:43 +00001187/// after setting up the current scheduling region. [RegionBegin, RegionEnd)
1188/// only includes instructions that have DAG nodes, not scheduling boundaries.
Andrew Trick7a8e1002012-09-11 00:39:15 +00001189///
1190/// This is a skeletal driver, with all the functionality pushed into helpers,
Nick Lewycky06b0ea22015-08-18 22:41:58 +00001191/// so that it can be easily extended by experimental schedulers. Generally,
Andrew Trick7a8e1002012-09-11 00:39:15 +00001192/// implementing MachineSchedStrategy should be sufficient to implement a new
1193/// scheduling algorithm. However, if a scheduler further subclasses
Andrew Trickd7f890e2013-12-28 21:56:47 +00001194/// ScheduleDAGMILive then it will want to override this virtual method in order
1195/// to update any specialized state.
1196void ScheduleDAGMILive::schedule() {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001197 LLVM_DEBUG(dbgs() << "ScheduleDAGMILive::schedule starting\n");
1198 LLVM_DEBUG(SchedImpl->dumpPolicy());
Andrew Trick7a8e1002012-09-11 00:39:15 +00001199 buildDAGWithRegPressure();
1200
Andrew Tricka2733e92012-09-14 17:22:42 +00001201 postprocessDAG();
1202
Andrew Tricke2c3f5c2013-01-25 06:33:57 +00001203 SmallVector<SUnit*, 8> TopRoots, BotRoots;
1204 findRootsAndBiasEdges(TopRoots, BotRoots);
1205
1206 // Initialize the strategy before modifying the DAG.
1207 // This may initialize a DFSResult to be used for queue priority.
1208 SchedImpl->initialize(this);
1209
Matthias Braun726e12c2018-09-19 00:23:35 +00001210 LLVM_DEBUG(dump());
Matthias Braun3136e422018-09-19 20:50:49 +00001211 if (PrintDAGs) dump();
Andrew Tricke2c3f5c2013-01-25 06:33:57 +00001212 if (ViewMISchedDAGs) viewGraph();
Andrew Trick7a8e1002012-09-11 00:39:15 +00001213
Andrew Tricke2c3f5c2013-01-25 06:33:57 +00001214 // Initialize ready queues now that the DAG and priority data are finalized.
1215 initQueues(TopRoots, BotRoots);
Andrew Trick7a8e1002012-09-11 00:39:15 +00001216
1217 bool IsTopNode = false;
James Y Knighte72b0db2015-09-18 18:52:20 +00001218 while (true) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001219 LLVM_DEBUG(dbgs() << "** ScheduleDAGMILive::schedule picking next node\n");
James Y Knighte72b0db2015-09-18 18:52:20 +00001220 SUnit *SU = SchedImpl->pickNode(IsTopNode);
1221 if (!SU) break;
1222
Andrew Trick984d98b2012-10-08 18:53:53 +00001223 assert(!SU->isScheduled && "Node already scheduled");
Andrew Trick7a8e1002012-09-11 00:39:15 +00001224 if (!checkSchedLimit())
1225 break;
1226
1227 scheduleMI(SU, IsTopNode);
1228
Andrew Trickd7f890e2013-12-28 21:56:47 +00001229 if (DFSResult) {
1230 unsigned SubtreeID = DFSResult->getSubtreeID(SU);
1231 if (!ScheduledTrees.test(SubtreeID)) {
1232 ScheduledTrees.set(SubtreeID);
1233 DFSResult->scheduleTree(SubtreeID);
1234 SchedImpl->scheduleTree(SubtreeID);
1235 }
1236 }
1237
1238 // Notify the scheduling strategy after updating the DAG.
1239 SchedImpl->schedNode(SU, IsTopNode);
Andrew Trick43adfb32015-03-27 06:10:13 +00001240
1241 updateQueues(SU, IsTopNode);
Andrew Trick7a8e1002012-09-11 00:39:15 +00001242 }
1243 assert(CurrentTop == CurrentBottom && "Nonempty unscheduled zone.");
1244
1245 placeDebugValues();
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001246
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001247 LLVM_DEBUG({
Francis Visoiu Mistrih25528d62017-12-04 17:18:51 +00001248 dbgs() << "*** Final schedule for "
1249 << printMBBReference(*begin()->getParent()) << " ***\n";
1250 dumpSchedule();
1251 dbgs() << '\n';
1252 });
Andrew Trick7a8e1002012-09-11 00:39:15 +00001253}
1254
1255/// Build the DAG and setup three register pressure trackers.
Andrew Trickd7f890e2013-12-28 21:56:47 +00001256void ScheduleDAGMILive::buildDAGWithRegPressure() {
Andrew Trickb6e74712013-09-04 20:59:59 +00001257 if (!ShouldTrackPressure) {
1258 RPTracker.reset();
1259 RegionCriticalPSets.clear();
1260 buildSchedGraph(AA);
1261 return;
1262 }
1263
Andrew Trick4add42f2012-05-10 21:06:10 +00001264 // Initialize the register pressure tracker used by buildSchedGraph.
Andrew Trick9c17eab2013-07-30 19:59:12 +00001265 RPTracker.init(&MF, RegClassInfo, LIS, BB, LiveRegionEnd,
Matthias Braund4f64092016-01-20 00:23:32 +00001266 ShouldTrackLaneMasks, /*TrackUntiedDefs=*/true);
Andrew Trick88639922012-04-24 17:56:43 +00001267
Andrew Trick4add42f2012-05-10 21:06:10 +00001268 // Account for liveness generate by the region boundary.
1269 if (LiveRegionEnd != RegionEnd)
1270 RPTracker.recede();
1271
1272 // Build the DAG, and compute current register pressure.
Matthias Braund4f64092016-01-20 00:23:32 +00001273 buildSchedGraph(AA, &RPTracker, &SUPressureDiffs, LIS, ShouldTrackLaneMasks);
Andrew Trick02a80da2012-03-08 01:41:12 +00001274
Andrew Trick4add42f2012-05-10 21:06:10 +00001275 // Initialize top/bottom trackers after computing region pressure.
1276 initRegPressure();
Andrew Trick7a8e1002012-09-11 00:39:15 +00001277}
Andrew Trick4add42f2012-05-10 21:06:10 +00001278
Andrew Trickd7f890e2013-12-28 21:56:47 +00001279void ScheduleDAGMILive::computeDFSResult() {
Andrew Trick44f750a2013-01-25 04:01:04 +00001280 if (!DFSResult)
1281 DFSResult = new SchedDFSResult(/*BottomU*/true, MinSubtreeSize);
1282 DFSResult->clear();
Andrew Trick44f750a2013-01-25 04:01:04 +00001283 ScheduledTrees.clear();
Andrew Tricke2c3f5c2013-01-25 06:33:57 +00001284 DFSResult->resize(SUnits.size());
1285 DFSResult->compute(SUnits);
Andrew Trick44f750a2013-01-25 04:01:04 +00001286 ScheduledTrees.resize(DFSResult->getNumSubtrees());
1287}
1288
Andrew Trick483f4192013-08-29 18:04:49 +00001289/// Compute the max cyclic critical path through the DAG. The scheduling DAG
1290/// only provides the critical path for single block loops. To handle loops that
1291/// span blocks, we could use the vreg path latencies provided by
1292/// MachineTraceMetrics instead. However, MachineTraceMetrics is not currently
1293/// available for use in the scheduler.
1294///
1295/// The cyclic path estimation identifies a def-use pair that crosses the back
Andrew Trickef80f502013-08-30 02:02:12 +00001296/// edge and considers the depth and height of the nodes. For example, consider
Andrew Trick483f4192013-08-29 18:04:49 +00001297/// the following instruction sequence where each instruction has unit latency
1298/// and defines an epomymous virtual register:
1299///
1300/// a->b(a,c)->c(b)->d(c)->exit
1301///
1302/// The cyclic critical path is a two cycles: b->c->b
1303/// The acyclic critical path is four cycles: a->b->c->d->exit
1304/// LiveOutHeight = height(c) = len(c->d->exit) = 2
1305/// LiveOutDepth = depth(c) + 1 = len(a->b->c) + 1 = 3
1306/// LiveInHeight = height(b) + 1 = len(b->c->d->exit) + 1 = 4
1307/// LiveInDepth = depth(b) = len(a->b) = 1
1308///
1309/// LiveOutDepth - LiveInDepth = 3 - 1 = 2
1310/// LiveInHeight - LiveOutHeight = 4 - 2 = 2
1311/// CyclicCriticalPath = min(2, 2) = 2
Andrew Trickd7f890e2013-12-28 21:56:47 +00001312///
1313/// This could be relevant to PostRA scheduling, but is currently implemented
1314/// assuming LiveIntervals.
1315unsigned ScheduleDAGMILive::computeCyclicCriticalPath() {
Andrew Trick483f4192013-08-29 18:04:49 +00001316 // This only applies to single block loop.
1317 if (!BB->isSuccessor(BB))
1318 return 0;
1319
1320 unsigned MaxCyclicLatency = 0;
1321 // Visit each live out vreg def to find def/use pairs that cross iterations.
Matthias Braun5d458612016-01-20 00:23:26 +00001322 for (const RegisterMaskPair &P : RPTracker.getPressure().LiveOutRegs) {
1323 unsigned Reg = P.RegUnit;
Daniel Sanders2bea69b2019-08-01 23:27:28 +00001324 if (!Register::isVirtualRegister(Reg))
1325 continue;
Andrew Trick483f4192013-08-29 18:04:49 +00001326 const LiveInterval &LI = LIS->getInterval(Reg);
1327 const VNInfo *DefVNI = LI.getVNInfoBefore(LIS->getMBBEndIdx(BB));
1328 if (!DefVNI)
1329 continue;
1330
1331 MachineInstr *DefMI = LIS->getInstructionFromIndex(DefVNI->def);
1332 const SUnit *DefSU = getSUnit(DefMI);
1333 if (!DefSU)
1334 continue;
1335
1336 unsigned LiveOutHeight = DefSU->getHeight();
1337 unsigned LiveOutDepth = DefSU->getDepth() + DefSU->Latency;
1338 // Visit all local users of the vreg def.
Matthias Braunb0c437b2015-10-29 03:57:17 +00001339 for (const VReg2SUnit &V2SU
1340 : make_range(VRegUses.find(Reg), VRegUses.end())) {
1341 SUnit *SU = V2SU.SU;
1342 if (SU == &ExitSU)
Andrew Trick483f4192013-08-29 18:04:49 +00001343 continue;
1344
1345 // Only consider uses of the phi.
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001346 LiveQueryResult LRQ = LI.Query(LIS->getInstructionIndex(*SU->getInstr()));
Andrew Trick483f4192013-08-29 18:04:49 +00001347 if (!LRQ.valueIn()->isPHIDef())
1348 continue;
1349
1350 // Assume that a path spanning two iterations is a cycle, which could
1351 // overestimate in strange cases. This allows cyclic latency to be
1352 // estimated as the minimum slack of the vreg's depth or height.
1353 unsigned CyclicLatency = 0;
Matthias Braunb0c437b2015-10-29 03:57:17 +00001354 if (LiveOutDepth > SU->getDepth())
1355 CyclicLatency = LiveOutDepth - SU->getDepth();
Andrew Trick483f4192013-08-29 18:04:49 +00001356
Matthias Braunb0c437b2015-10-29 03:57:17 +00001357 unsigned LiveInHeight = SU->getHeight() + DefSU->Latency;
Andrew Trick483f4192013-08-29 18:04:49 +00001358 if (LiveInHeight > LiveOutHeight) {
1359 if (LiveInHeight - LiveOutHeight < CyclicLatency)
1360 CyclicLatency = LiveInHeight - LiveOutHeight;
Matthias Braunb550b762016-04-21 01:54:13 +00001361 } else
Andrew Trick483f4192013-08-29 18:04:49 +00001362 CyclicLatency = 0;
1363
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001364 LLVM_DEBUG(dbgs() << "Cyclic Path: SU(" << DefSU->NodeNum << ") -> SU("
1365 << SU->NodeNum << ") = " << CyclicLatency << "c\n");
Andrew Trick483f4192013-08-29 18:04:49 +00001366 if (CyclicLatency > MaxCyclicLatency)
1367 MaxCyclicLatency = CyclicLatency;
1368 }
1369 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001370 LLVM_DEBUG(dbgs() << "Cyclic Critical Path: " << MaxCyclicLatency << "c\n");
Andrew Trick483f4192013-08-29 18:04:49 +00001371 return MaxCyclicLatency;
1372}
1373
Krzysztof Parzyszek7ea9a522016-04-28 19:17:44 +00001374/// Release ExitSU predecessors and setup scheduler queues. Re-position
1375/// the Top RP tracker in case the region beginning has changed.
1376void ScheduleDAGMILive::initQueues(ArrayRef<SUnit*> TopRoots,
1377 ArrayRef<SUnit*> BotRoots) {
1378 ScheduleDAGMI::initQueues(TopRoots, BotRoots);
1379 if (ShouldTrackPressure) {
1380 assert(TopRPTracker.getPos() == RegionBegin && "bad initial Top tracker");
1381 TopRPTracker.setPos(CurrentTop);
1382 }
1383}
1384
Andrew Trick7a8e1002012-09-11 00:39:15 +00001385/// Move an instruction and update register pressure.
Andrew Trickd7f890e2013-12-28 21:56:47 +00001386void ScheduleDAGMILive::scheduleMI(SUnit *SU, bool IsTopNode) {
Andrew Trick7a8e1002012-09-11 00:39:15 +00001387 // Move the instruction to its new location in the instruction stream.
1388 MachineInstr *MI = SU->getInstr();
Andrew Trick02a80da2012-03-08 01:41:12 +00001389
Andrew Trick7a8e1002012-09-11 00:39:15 +00001390 if (IsTopNode) {
1391 assert(SU->isTopReady() && "node still has unscheduled dependencies");
1392 if (&*CurrentTop == MI)
1393 CurrentTop = nextIfDebug(++CurrentTop, CurrentBottom);
Andrew Trick8823dec2012-03-14 04:00:41 +00001394 else {
Andrew Trick7a8e1002012-09-11 00:39:15 +00001395 moveInstruction(MI, CurrentTop);
1396 TopRPTracker.setPos(MI);
Andrew Trick8823dec2012-03-14 04:00:41 +00001397 }
Andrew Trickc3ea0052012-04-24 18:04:37 +00001398
Andrew Trickb6e74712013-09-04 20:59:59 +00001399 if (ShouldTrackPressure) {
1400 // Update top scheduled pressure.
Matthias Braund4f64092016-01-20 00:23:32 +00001401 RegisterOperands RegOpers;
1402 RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
1403 if (ShouldTrackLaneMasks) {
1404 // Adjust liveness and add missing dead+read-undef flags.
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001405 SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
Matthias Braund4f64092016-01-20 00:23:32 +00001406 RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
1407 } else {
1408 // Adjust for missing dead-def flags.
1409 RegOpers.detectDeadDefs(*MI, *LIS);
1410 }
1411
1412 TopRPTracker.advance(RegOpers);
Andrew Trickb6e74712013-09-04 20:59:59 +00001413 assert(TopRPTracker.getPos() == CurrentTop && "out of sync");
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001414 LLVM_DEBUG(dbgs() << "Top Pressure:\n"; dumpRegSetPressure(
1415 TopRPTracker.getRegSetPressureAtPos(), TRI););
Matthias Braun9198c672015-11-06 20:59:02 +00001416
Andrew Trickb248b4a2013-09-06 17:32:47 +00001417 updateScheduledPressure(SU, TopRPTracker.getPressure().MaxSetPressure);
Andrew Trickb6e74712013-09-04 20:59:59 +00001418 }
Matthias Braunb550b762016-04-21 01:54:13 +00001419 } else {
Andrew Trick7a8e1002012-09-11 00:39:15 +00001420 assert(SU->isBottomReady() && "node still has unscheduled dependencies");
1421 MachineBasicBlock::iterator priorII =
1422 priorNonDebug(CurrentBottom, CurrentTop);
1423 if (&*priorII == MI)
1424 CurrentBottom = priorII;
1425 else {
1426 if (&*CurrentTop == MI) {
1427 CurrentTop = nextIfDebug(++CurrentTop, priorII);
1428 TopRPTracker.setPos(CurrentTop);
1429 }
1430 moveInstruction(MI, CurrentBottom);
1431 CurrentBottom = MI;
Yaxun Liu8b7454a2018-01-23 16:04:53 +00001432 BotRPTracker.setPos(CurrentBottom);
Andrew Trick7a8e1002012-09-11 00:39:15 +00001433 }
Andrew Trickb6e74712013-09-04 20:59:59 +00001434 if (ShouldTrackPressure) {
Matthias Braund4f64092016-01-20 00:23:32 +00001435 RegisterOperands RegOpers;
1436 RegOpers.collect(*MI, *TRI, MRI, ShouldTrackLaneMasks, false);
1437 if (ShouldTrackLaneMasks) {
1438 // Adjust liveness and add missing dead+read-undef flags.
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001439 SlotIndex SlotIdx = LIS->getInstructionIndex(*MI).getRegSlot();
Matthias Braund4f64092016-01-20 00:23:32 +00001440 RegOpers.adjustLaneLiveness(*LIS, MRI, SlotIdx, MI);
1441 } else {
1442 // Adjust for missing dead-def flags.
1443 RegOpers.detectDeadDefs(*MI, *LIS);
1444 }
1445
Yaxun Liuc41e2f62017-12-15 03:56:57 +00001446 if (BotRPTracker.getPos() != CurrentBottom)
1447 BotRPTracker.recedeSkipDebugValues();
Matthias Braun5d458612016-01-20 00:23:26 +00001448 SmallVector<RegisterMaskPair, 8> LiveUses;
Matthias Braund4f64092016-01-20 00:23:32 +00001449 BotRPTracker.recede(RegOpers, &LiveUses);
Andrew Trickb6e74712013-09-04 20:59:59 +00001450 assert(BotRPTracker.getPos() == CurrentBottom && "out of sync");
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001451 LLVM_DEBUG(dbgs() << "Bottom Pressure:\n"; dumpRegSetPressure(
1452 BotRPTracker.getRegSetPressureAtPos(), TRI););
Matthias Braun9198c672015-11-06 20:59:02 +00001453
Andrew Trickb248b4a2013-09-06 17:32:47 +00001454 updateScheduledPressure(SU, BotRPTracker.getPressure().MaxSetPressure);
Andrew Trickb6e74712013-09-04 20:59:59 +00001455 updatePressureDiffs(LiveUses);
Andrew Trickb6e74712013-09-04 20:59:59 +00001456 }
Andrew Trick7a8e1002012-09-11 00:39:15 +00001457 }
1458}
1459
Andrew Trick263280242012-11-12 19:52:20 +00001460//===----------------------------------------------------------------------===//
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001461// BaseMemOpClusterMutation - DAG post-processing to cluster loads or stores.
Andrew Trick263280242012-11-12 19:52:20 +00001462//===----------------------------------------------------------------------===//
1463
Andrew Tricka7714a02012-11-12 19:40:10 +00001464namespace {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001465
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001466/// Post-process the DAG to create cluster edges between neighboring
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001467/// loads or between neighboring stores.
1468class BaseMemOpClusterMutation : public ScheduleDAGMutation {
1469 struct MemOpInfo {
Andrew Tricka7714a02012-11-12 19:40:10 +00001470 SUnit *SU;
Bjorn Pettersson238c9d6302019-04-19 09:08:38 +00001471 const MachineOperand *BaseOp;
Chad Rosierc27a18f2016-03-09 16:00:35 +00001472 int64_t Offset;
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001473
Bjorn Pettersson238c9d6302019-04-19 09:08:38 +00001474 MemOpInfo(SUnit *su, const MachineOperand *Op, int64_t ofs)
Francis Visoiu Mistrihd7eebd62018-11-28 12:00:20 +00001475 : SU(su), BaseOp(Op), Offset(ofs) {}
Benjamin Kramerb0f74b22014-03-07 21:35:39 +00001476
Francis Visoiu Mistrihd7eebd62018-11-28 12:00:20 +00001477 bool operator<(const MemOpInfo &RHS) const {
Francis Visoiu Mistrih879087c2018-11-28 12:00:28 +00001478 if (BaseOp->getType() != RHS.BaseOp->getType())
1479 return BaseOp->getType() < RHS.BaseOp->getType();
1480
1481 if (BaseOp->isReg())
1482 return std::make_tuple(BaseOp->getReg(), Offset, SU->NodeNum) <
1483 std::make_tuple(RHS.BaseOp->getReg(), RHS.Offset,
1484 RHS.SU->NodeNum);
Francis Visoiu Mistrih0b8dd442018-11-29 20:03:19 +00001485 if (BaseOp->isFI()) {
1486 const MachineFunction &MF =
1487 *BaseOp->getParent()->getParent()->getParent();
1488 const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering();
1489 bool StackGrowsDown = TFI.getStackGrowthDirection() ==
1490 TargetFrameLowering::StackGrowsDown;
1491 // Can't use tuple comparison here since we might need to use a
1492 // different order when the stack grows down.
1493 if (BaseOp->getIndex() != RHS.BaseOp->getIndex())
1494 return StackGrowsDown ? BaseOp->getIndex() > RHS.BaseOp->getIndex()
1495 : BaseOp->getIndex() < RHS.BaseOp->getIndex();
1496
1497 if (Offset != RHS.Offset)
1498 return StackGrowsDown ? Offset > RHS.Offset : Offset < RHS.Offset;
1499
1500 return SU->NodeNum < RHS.SU->NodeNum;
1501 }
Francis Visoiu Mistrih879087c2018-11-28 12:00:28 +00001502
1503 llvm_unreachable("MemOpClusterMutation only supports register or frame "
1504 "index bases.");
Benjamin Kramerb0f74b22014-03-07 21:35:39 +00001505 }
Andrew Tricka7714a02012-11-12 19:40:10 +00001506 };
Andrew Tricka7714a02012-11-12 19:40:10 +00001507
1508 const TargetInstrInfo *TII;
1509 const TargetRegisterInfo *TRI;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001510 bool IsLoad;
1511
Andrew Tricka7714a02012-11-12 19:40:10 +00001512public:
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001513 BaseMemOpClusterMutation(const TargetInstrInfo *tii,
1514 const TargetRegisterInfo *tri, bool IsLoad)
1515 : TII(tii), TRI(tri), IsLoad(IsLoad) {}
Andrew Tricka7714a02012-11-12 19:40:10 +00001516
Krzysztof Parzyszek5c61d112016-03-05 15:45:23 +00001517 void apply(ScheduleDAGInstrs *DAGInstrs) override;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001518
Andrew Tricka7714a02012-11-12 19:40:10 +00001519protected:
Clement Courbetb70355f2019-03-29 08:33:05 +00001520 void clusterNeighboringMemOps(ArrayRef<SUnit *> MemOps, ScheduleDAGInstrs *DAG);
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001521};
1522
1523class StoreClusterMutation : public BaseMemOpClusterMutation {
1524public:
1525 StoreClusterMutation(const TargetInstrInfo *tii,
1526 const TargetRegisterInfo *tri)
1527 : BaseMemOpClusterMutation(tii, tri, false) {}
1528};
1529
1530class LoadClusterMutation : public BaseMemOpClusterMutation {
1531public:
1532 LoadClusterMutation(const TargetInstrInfo *tii, const TargetRegisterInfo *tri)
1533 : BaseMemOpClusterMutation(tii, tri, true) {}
Andrew Tricka7714a02012-11-12 19:40:10 +00001534};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001535
1536} // end anonymous namespace
Andrew Tricka7714a02012-11-12 19:40:10 +00001537
Tom Stellard68726a52016-08-19 19:59:18 +00001538namespace llvm {
1539
1540std::unique_ptr<ScheduleDAGMutation>
1541createLoadClusterDAGMutation(const TargetInstrInfo *TII,
1542 const TargetRegisterInfo *TRI) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00001543 return EnableMemOpCluster ? std::make_unique<LoadClusterMutation>(TII, TRI)
Matthias Braun115efcd2016-11-28 20:11:54 +00001544 : nullptr;
Tom Stellard68726a52016-08-19 19:59:18 +00001545}
1546
1547std::unique_ptr<ScheduleDAGMutation>
1548createStoreClusterDAGMutation(const TargetInstrInfo *TII,
1549 const TargetRegisterInfo *TRI) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00001550 return EnableMemOpCluster ? std::make_unique<StoreClusterMutation>(TII, TRI)
Matthias Braun115efcd2016-11-28 20:11:54 +00001551 : nullptr;
Tom Stellard68726a52016-08-19 19:59:18 +00001552}
1553
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001554} // end namespace llvm
Tom Stellard68726a52016-08-19 19:59:18 +00001555
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001556void BaseMemOpClusterMutation::clusterNeighboringMemOps(
Clement Courbetb70355f2019-03-29 08:33:05 +00001557 ArrayRef<SUnit *> MemOps, ScheduleDAGInstrs *DAG) {
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001558 SmallVector<MemOpInfo, 32> MemOpRecords;
Javed Absare3a0cc22017-06-21 09:10:10 +00001559 for (SUnit *SU : MemOps) {
Bjorn Pettersson238c9d6302019-04-19 09:08:38 +00001560 const MachineOperand *BaseOp;
Chad Rosierc27a18f2016-03-09 16:00:35 +00001561 int64_t Offset;
Francis Visoiu Mistrihd7eebd62018-11-28 12:00:20 +00001562 if (TII->getMemOperandWithOffset(*SU->getInstr(), BaseOp, Offset, TRI))
1563 MemOpRecords.push_back(MemOpInfo(SU, BaseOp, Offset));
Andrew Tricka7714a02012-11-12 19:40:10 +00001564 }
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001565 if (MemOpRecords.size() < 2)
Andrew Tricka7714a02012-11-12 19:40:10 +00001566 return;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001567
Fangrui Song0cac7262018-09-27 02:13:45 +00001568 llvm::sort(MemOpRecords);
Andrew Tricka7714a02012-11-12 19:40:10 +00001569 unsigned ClusterLength = 1;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001570 for (unsigned Idx = 0, End = MemOpRecords.size(); Idx < (End - 1); ++Idx) {
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001571 SUnit *SUa = MemOpRecords[Idx].SU;
1572 SUnit *SUb = MemOpRecords[Idx+1].SU;
Francis Visoiu Mistrihd7eebd62018-11-28 12:00:20 +00001573 if (TII->shouldClusterMemOps(*MemOpRecords[Idx].BaseOp,
1574 *MemOpRecords[Idx + 1].BaseOp,
Duncan P. N. Exon Smith9cfc75c2016-06-30 00:01:54 +00001575 ClusterLength) &&
1576 DAG->addEdge(SUb, SDep(SUa, SDep::Cluster))) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001577 LLVM_DEBUG(dbgs() << "Cluster ld/st SU(" << SUa->NodeNum << ") - SU("
1578 << SUb->NodeNum << ")\n");
Andrew Tricka7714a02012-11-12 19:40:10 +00001579 // Copy successor edges from SUa to SUb. Interleaving computation
1580 // dependent on SUa can prevent load combining due to register reuse.
1581 // Predecessor edges do not need to be copied from SUb to SUa since nearby
1582 // loads should have effectively the same inputs.
Javed Absare3a0cc22017-06-21 09:10:10 +00001583 for (const SDep &Succ : SUa->Succs) {
1584 if (Succ.getSUnit() == SUb)
Andrew Tricka7714a02012-11-12 19:40:10 +00001585 continue;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001586 LLVM_DEBUG(dbgs() << " Copy Succ SU(" << Succ.getSUnit()->NodeNum
1587 << ")\n");
Javed Absare3a0cc22017-06-21 09:10:10 +00001588 DAG->addEdge(Succ.getSUnit(), SDep(SUb, SDep::Artificial));
Andrew Tricka7714a02012-11-12 19:40:10 +00001589 }
1590 ++ClusterLength;
Matthias Braunb550b762016-04-21 01:54:13 +00001591 } else
Andrew Tricka7714a02012-11-12 19:40:10 +00001592 ClusterLength = 1;
1593 }
1594}
1595
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001596/// Callback from DAG postProcessing to create cluster edges for loads.
Clement Courbetb70355f2019-03-29 08:33:05 +00001597void BaseMemOpClusterMutation::apply(ScheduleDAGInstrs *DAG) {
Andrew Tricka7714a02012-11-12 19:40:10 +00001598 // Map DAG NodeNum to store chain ID.
1599 DenseMap<unsigned, unsigned> StoreChainIDs;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001600 // Map each store chain to a set of dependent MemOps.
Andrew Tricka7714a02012-11-12 19:40:10 +00001601 SmallVector<SmallVector<SUnit*,4>, 32> StoreChainDependents;
Javed Absare3a0cc22017-06-21 09:10:10 +00001602 for (SUnit &SU : DAG->SUnits) {
1603 if ((IsLoad && !SU.getInstr()->mayLoad()) ||
1604 (!IsLoad && !SU.getInstr()->mayStore()))
Andrew Tricka7714a02012-11-12 19:40:10 +00001605 continue;
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001606
Andrew Tricka7714a02012-11-12 19:40:10 +00001607 unsigned ChainPredID = DAG->SUnits.size();
Javed Absare3a0cc22017-06-21 09:10:10 +00001608 for (const SDep &Pred : SU.Preds) {
1609 if (Pred.isCtrl()) {
1610 ChainPredID = Pred.getSUnit()->NodeNum;
Andrew Tricka7714a02012-11-12 19:40:10 +00001611 break;
1612 }
1613 }
1614 // Check if this chain-like pred has been seen
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001615 // before. ChainPredID==MaxNodeID at the top of the schedule.
Andrew Tricka7714a02012-11-12 19:40:10 +00001616 unsigned NumChains = StoreChainDependents.size();
1617 std::pair<DenseMap<unsigned, unsigned>::iterator, bool> Result =
1618 StoreChainIDs.insert(std::make_pair(ChainPredID, NumChains));
1619 if (Result.second)
1620 StoreChainDependents.resize(NumChains + 1);
Javed Absare3a0cc22017-06-21 09:10:10 +00001621 StoreChainDependents[Result.first->second].push_back(&SU);
Andrew Tricka7714a02012-11-12 19:40:10 +00001622 }
Jun Bum Lim4c5bd582016-04-15 14:58:38 +00001623
Andrew Tricka7714a02012-11-12 19:40:10 +00001624 // Iterate over the store chains.
Javed Absare3a0cc22017-06-21 09:10:10 +00001625 for (auto &SCD : StoreChainDependents)
1626 clusterNeighboringMemOps(SCD, DAG);
Andrew Tricka7714a02012-11-12 19:40:10 +00001627}
1628
Andrew Trick02a80da2012-03-08 01:41:12 +00001629//===----------------------------------------------------------------------===//
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001630// CopyConstrain - DAG post-processing to encourage copy elimination.
1631//===----------------------------------------------------------------------===//
1632
1633namespace {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001634
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001635/// Post-process the DAG to create weak edges from all uses of a copy to
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001636/// the one use that defines the copy's source vreg, most likely an induction
1637/// variable increment.
1638class CopyConstrain : public ScheduleDAGMutation {
1639 // Transient state.
1640 SlotIndex RegionBeginIdx;
Eugene Zelenko32a40562017-09-11 23:00:48 +00001641
Andrew Trick2e875172013-04-24 23:19:56 +00001642 // RegionEndIdx is the slot index of the last non-debug instruction in the
1643 // scheduling region. So we may have RegionBeginIdx == RegionEndIdx.
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001644 SlotIndex RegionEndIdx;
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001645
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001646public:
1647 CopyConstrain(const TargetInstrInfo *, const TargetRegisterInfo *) {}
1648
Krzysztof Parzyszek5c61d112016-03-05 15:45:23 +00001649 void apply(ScheduleDAGInstrs *DAGInstrs) override;
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001650
1651protected:
Andrew Trickd7f890e2013-12-28 21:56:47 +00001652 void constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG);
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001653};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001654
1655} // end anonymous namespace
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001656
Tom Stellard68726a52016-08-19 19:59:18 +00001657namespace llvm {
1658
1659std::unique_ptr<ScheduleDAGMutation>
1660createCopyConstrainDAGMutation(const TargetInstrInfo *TII,
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001661 const TargetRegisterInfo *TRI) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00001662 return std::make_unique<CopyConstrain>(TII, TRI);
Tom Stellard68726a52016-08-19 19:59:18 +00001663}
1664
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001665} // end namespace llvm
Tom Stellard68726a52016-08-19 19:59:18 +00001666
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001667/// constrainLocalCopy handles two possibilities:
1668/// 1) Local src:
1669/// I0: = dst
1670/// I1: src = ...
1671/// I2: = dst
1672/// I3: dst = src (copy)
1673/// (create pred->succ edges I0->I1, I2->I1)
1674///
1675/// 2) Local copy:
1676/// I0: dst = src (copy)
1677/// I1: = dst
1678/// I2: src = ...
1679/// I3: = dst
1680/// (create pred->succ edges I1->I2, I3->I2)
1681///
1682/// Although the MachineScheduler is currently constrained to single blocks,
1683/// this algorithm should handle extended blocks. An EBB is a set of
1684/// contiguously numbered blocks such that the previous block in the EBB is
1685/// always the single predecessor.
Andrew Trickd7f890e2013-12-28 21:56:47 +00001686void CopyConstrain::constrainLocalCopy(SUnit *CopySU, ScheduleDAGMILive *DAG) {
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001687 LiveIntervals *LIS = DAG->getLIS();
1688 MachineInstr *Copy = CopySU->getInstr();
1689
1690 // Check for pure vreg copies.
Matthias Braun7511abd2016-04-04 21:23:46 +00001691 const MachineOperand &SrcOp = Copy->getOperand(1);
Daniel Sanders0c476112019-08-15 19:22:08 +00001692 Register SrcReg = SrcOp.getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +00001693 if (!Register::isVirtualRegister(SrcReg) || !SrcOp.readsReg())
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001694 return;
1695
Matthias Braun7511abd2016-04-04 21:23:46 +00001696 const MachineOperand &DstOp = Copy->getOperand(0);
Daniel Sanders0c476112019-08-15 19:22:08 +00001697 Register DstReg = DstOp.getReg();
Daniel Sanders2bea69b2019-08-01 23:27:28 +00001698 if (!Register::isVirtualRegister(DstReg) || DstOp.isDead())
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001699 return;
1700
1701 // Check if either the dest or source is local. If it's live across a back
1702 // edge, it's not local. Note that if both vregs are live across the back
1703 // edge, we cannot successfully contrain the copy without cyclic scheduling.
Michael Kuperstein54c61ed2015-01-19 07:30:47 +00001704 // If both the copy's source and dest are local live intervals, then we
1705 // should treat the dest as the global for the purpose of adding
1706 // constraints. This adds edges from source's other uses to the copy.
1707 unsigned LocalReg = SrcReg;
1708 unsigned GlobalReg = DstReg;
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001709 LiveInterval *LocalLI = &LIS->getInterval(LocalReg);
1710 if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx)) {
Michael Kuperstein54c61ed2015-01-19 07:30:47 +00001711 LocalReg = DstReg;
1712 GlobalReg = SrcReg;
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001713 LocalLI = &LIS->getInterval(LocalReg);
1714 if (!LocalLI->isLocal(RegionBeginIdx, RegionEndIdx))
1715 return;
1716 }
1717 LiveInterval *GlobalLI = &LIS->getInterval(GlobalReg);
1718
1719 // Find the global segment after the start of the local LI.
1720 LiveInterval::iterator GlobalSegment = GlobalLI->find(LocalLI->beginIndex());
1721 // If GlobalLI does not overlap LocalLI->start, then a copy directly feeds a
1722 // local live range. We could create edges from other global uses to the local
1723 // start, but the coalescer should have already eliminated these cases, so
1724 // don't bother dealing with it.
1725 if (GlobalSegment == GlobalLI->end())
1726 return;
1727
1728 // If GlobalSegment is killed at the LocalLI->start, the call to find()
1729 // returned the next global segment. But if GlobalSegment overlaps with
Hiroshi Inouec73b6d62018-06-20 05:29:26 +00001730 // LocalLI->start, then advance to the next segment. If a hole in GlobalLI
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001731 // exists in LocalLI's vicinity, GlobalSegment will be the end of the hole.
1732 if (GlobalSegment->contains(LocalLI->beginIndex()))
1733 ++GlobalSegment;
1734
1735 if (GlobalSegment == GlobalLI->end())
1736 return;
1737
1738 // Check if GlobalLI contains a hole in the vicinity of LocalLI.
1739 if (GlobalSegment != GlobalLI->begin()) {
1740 // Two address defs have no hole.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001741 if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->end,
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001742 GlobalSegment->start)) {
1743 return;
1744 }
Andrew Trickd9761772013-07-30 19:59:08 +00001745 // If the prior global segment may be defined by the same two-address
1746 // instruction that also defines LocalLI, then can't make a hole here.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001747 if (SlotIndex::isSameInstr(std::prev(GlobalSegment)->start,
Andrew Trickd9761772013-07-30 19:59:08 +00001748 LocalLI->beginIndex())) {
1749 return;
1750 }
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001751 // If GlobalLI has a prior segment, it must be live into the EBB. Otherwise
1752 // it would be a disconnected component in the live range.
Benjamin Kramerb6d0bd42014-03-02 12:27:27 +00001753 assert(std::prev(GlobalSegment)->start < LocalLI->beginIndex() &&
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001754 "Disconnected LRG within the scheduling region.");
1755 }
1756 MachineInstr *GlobalDef = LIS->getInstructionFromIndex(GlobalSegment->start);
1757 if (!GlobalDef)
1758 return;
1759
1760 SUnit *GlobalSU = DAG->getSUnit(GlobalDef);
1761 if (!GlobalSU)
1762 return;
1763
1764 // GlobalDef is the bottom of the GlobalLI hole. Open the hole by
1765 // constraining the uses of the last local def to precede GlobalDef.
1766 SmallVector<SUnit*,8> LocalUses;
1767 const VNInfo *LastLocalVN = LocalLI->getVNInfoBefore(LocalLI->endIndex());
1768 MachineInstr *LastLocalDef = LIS->getInstructionFromIndex(LastLocalVN->def);
1769 SUnit *LastLocalSU = DAG->getSUnit(LastLocalDef);
Javed Absare3a0cc22017-06-21 09:10:10 +00001770 for (const SDep &Succ : LastLocalSU->Succs) {
1771 if (Succ.getKind() != SDep::Data || Succ.getReg() != LocalReg)
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001772 continue;
Javed Absare3a0cc22017-06-21 09:10:10 +00001773 if (Succ.getSUnit() == GlobalSU)
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001774 continue;
Javed Absare3a0cc22017-06-21 09:10:10 +00001775 if (!DAG->canAddEdge(GlobalSU, Succ.getSUnit()))
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001776 return;
Javed Absare3a0cc22017-06-21 09:10:10 +00001777 LocalUses.push_back(Succ.getSUnit());
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001778 }
1779 // Open the top of the GlobalLI hole by constraining any earlier global uses
1780 // to precede the start of LocalLI.
1781 SmallVector<SUnit*,8> GlobalUses;
1782 MachineInstr *FirstLocalDef =
1783 LIS->getInstructionFromIndex(LocalLI->beginIndex());
1784 SUnit *FirstLocalSU = DAG->getSUnit(FirstLocalDef);
Javed Absare3a0cc22017-06-21 09:10:10 +00001785 for (const SDep &Pred : GlobalSU->Preds) {
1786 if (Pred.getKind() != SDep::Anti || Pred.getReg() != GlobalReg)
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001787 continue;
Javed Absare3a0cc22017-06-21 09:10:10 +00001788 if (Pred.getSUnit() == FirstLocalSU)
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001789 continue;
Javed Absare3a0cc22017-06-21 09:10:10 +00001790 if (!DAG->canAddEdge(FirstLocalSU, Pred.getSUnit()))
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001791 return;
Javed Absare3a0cc22017-06-21 09:10:10 +00001792 GlobalUses.push_back(Pred.getSUnit());
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001793 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001794 LLVM_DEBUG(dbgs() << "Constraining copy SU(" << CopySU->NodeNum << ")\n");
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001795 // Add the weak edges.
1796 for (SmallVectorImpl<SUnit*>::const_iterator
1797 I = LocalUses.begin(), E = LocalUses.end(); I != E; ++I) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001798 LLVM_DEBUG(dbgs() << " Local use SU(" << (*I)->NodeNum << ") -> SU("
1799 << GlobalSU->NodeNum << ")\n");
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001800 DAG->addEdge(GlobalSU, SDep(*I, SDep::Weak));
1801 }
1802 for (SmallVectorImpl<SUnit*>::const_iterator
1803 I = GlobalUses.begin(), E = GlobalUses.end(); I != E; ++I) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00001804 LLVM_DEBUG(dbgs() << " Global use SU(" << (*I)->NodeNum << ") -> SU("
1805 << FirstLocalSU->NodeNum << ")\n");
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001806 DAG->addEdge(FirstLocalSU, SDep(*I, SDep::Weak));
1807 }
1808}
1809
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00001810/// Callback from DAG postProcessing to create weak edges to encourage
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001811/// copy elimination.
Krzysztof Parzyszek5c61d112016-03-05 15:45:23 +00001812void CopyConstrain::apply(ScheduleDAGInstrs *DAGInstrs) {
1813 ScheduleDAGMI *DAG = static_cast<ScheduleDAGMI*>(DAGInstrs);
Andrew Trickd7f890e2013-12-28 21:56:47 +00001814 assert(DAG->hasVRegLiveness() && "Expect VRegs with LiveIntervals");
1815
Andrew Trick2e875172013-04-24 23:19:56 +00001816 MachineBasicBlock::iterator FirstPos = nextIfDebug(DAG->begin(), DAG->end());
1817 if (FirstPos == DAG->end())
1818 return;
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001819 RegionBeginIdx = DAG->getLIS()->getInstructionIndex(*FirstPos);
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001820 RegionEndIdx = DAG->getLIS()->getInstructionIndex(
Duncan P. N. Exon Smith3ac9cc62016-02-27 06:40:41 +00001821 *priorNonDebug(DAG->end(), DAG->begin()));
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001822
Javed Absare3a0cc22017-06-21 09:10:10 +00001823 for (SUnit &SU : DAG->SUnits) {
1824 if (!SU.getInstr()->isCopy())
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001825 continue;
1826
Javed Absare3a0cc22017-06-21 09:10:10 +00001827 constrainLocalCopy(&SU, static_cast<ScheduleDAGMILive*>(DAG));
Andrew Trick85a1d4c2013-04-24 15:54:43 +00001828 }
1829}
1830
1831//===----------------------------------------------------------------------===//
Andrew Trickfc127d12013-12-07 05:59:44 +00001832// MachineSchedStrategy helpers used by GenericScheduler, GenericPostScheduler
1833// and possibly other custom schedulers.
Andrew Trickd14d7c22013-12-28 21:56:57 +00001834//===----------------------------------------------------------------------===//
Andrew Tricke1c034f2012-01-17 06:55:03 +00001835
Andrew Trick5a22df42013-12-05 17:56:02 +00001836static const unsigned InvalidCycle = ~0U;
1837
Andrew Trickfc127d12013-12-07 05:59:44 +00001838SchedBoundary::~SchedBoundary() { delete HazardRec; }
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001839
Jonas Paulsson238c14b2017-10-25 08:23:33 +00001840/// Given a Count of resource usage and a Latency value, return true if a
1841/// SchedBoundary becomes resource limited.
Jinsong Ji7aafdef2019-06-07 14:54:47 +00001842/// If we are checking after scheduling a node, we should return true when
1843/// we just reach the resource limit.
Jonas Paulsson238c14b2017-10-25 08:23:33 +00001844static bool checkResourceLimit(unsigned LFactor, unsigned Count,
Jinsong Ji7aafdef2019-06-07 14:54:47 +00001845 unsigned Latency, bool AfterSchedNode) {
1846 int ResCntFactor = (int)(Count - (Latency * LFactor));
1847 if (AfterSchedNode)
1848 return ResCntFactor >= (int)LFactor;
1849 else
1850 return ResCntFactor > (int)LFactor;
Jonas Paulsson238c14b2017-10-25 08:23:33 +00001851}
1852
Andrew Trickfc127d12013-12-07 05:59:44 +00001853void SchedBoundary::reset() {
1854 // A new HazardRec is created for each DAG and owned by SchedBoundary.
1855 // Destroying and reconstructing it is very expensive though. So keep
1856 // invalid, placeholder HazardRecs.
1857 if (HazardRec && HazardRec->isEnabled()) {
1858 delete HazardRec;
Craig Topperc0196b12014-04-14 00:51:57 +00001859 HazardRec = nullptr;
Andrew Trickfc127d12013-12-07 05:59:44 +00001860 }
1861 Available.clear();
1862 Pending.clear();
1863 CheckPending = false;
Andrew Trickfc127d12013-12-07 05:59:44 +00001864 CurrCycle = 0;
1865 CurrMOps = 0;
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00001866 MinReadyCycle = std::numeric_limits<unsigned>::max();
Andrew Trickfc127d12013-12-07 05:59:44 +00001867 ExpectedLatency = 0;
1868 DependentLatency = 0;
1869 RetiredMOps = 0;
1870 MaxExecutedResCount = 0;
1871 ZoneCritResIdx = 0;
1872 IsResourceLimited = false;
1873 ReservedCycles.clear();
Momchil Velikovc396f092019-05-10 16:54:32 +00001874 ReservedCyclesIndex.clear();
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001875#ifndef NDEBUG
Andrew Trickd14d7c22013-12-28 21:56:57 +00001876 // Track the maximum number of stall cycles that could arise either from the
1877 // latency of a DAG edge or the number of cycles that a processor resource is
1878 // reserved (SchedBoundary::ReservedCycles).
Andrew Trick7f1ebbe2014-06-07 01:48:43 +00001879 MaxObservedStall = 0;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001880#endif
Andrew Trickfc127d12013-12-07 05:59:44 +00001881 // Reserve a zero-count for invalid CritResIdx.
1882 ExecutedResCounts.resize(1);
1883 assert(!ExecutedResCounts[0] && "nonzero count for bad resource");
1884}
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001885
Andrew Trickfc127d12013-12-07 05:59:44 +00001886void SchedRemainder::
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001887init(ScheduleDAGMI *DAG, const TargetSchedModel *SchedModel) {
1888 reset();
1889 if (!SchedModel->hasInstrSchedModel())
1890 return;
1891 RemainingCounts.resize(SchedModel->getNumProcResourceKinds());
Javed Absare3a0cc22017-06-21 09:10:10 +00001892 for (SUnit &SU : DAG->SUnits) {
1893 const MCSchedClassDesc *SC = DAG->getSchedClass(&SU);
1894 RemIssueCount += SchedModel->getNumMicroOps(SU.getInstr(), SC)
Andrew Trickf78e7fa2013-06-15 05:39:19 +00001895 * SchedModel->getMicroOpFactor();
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001896 for (TargetSchedModel::ProcResIter
1897 PI = SchedModel->getWriteProcResBegin(SC),
1898 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
1899 unsigned PIdx = PI->ProcResourceIdx;
1900 unsigned Factor = SchedModel->getResourceFactor(PIdx);
1901 RemainingCounts[PIdx] += (Factor * PI->Cycles);
1902 }
1903 }
1904}
1905
Andrew Trickfc127d12013-12-07 05:59:44 +00001906void SchedBoundary::
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001907init(ScheduleDAGMI *dag, const TargetSchedModel *smodel, SchedRemainder *rem) {
1908 reset();
1909 DAG = dag;
1910 SchedModel = smodel;
1911 Rem = rem;
Andrew Trick5a22df42013-12-05 17:56:02 +00001912 if (SchedModel->hasInstrSchedModel()) {
Momchil Velikovc396f092019-05-10 16:54:32 +00001913 unsigned ResourceCount = SchedModel->getNumProcResourceKinds();
1914 ReservedCyclesIndex.resize(ResourceCount);
1915 ExecutedResCounts.resize(ResourceCount);
1916 unsigned NumUnits = 0;
1917
1918 for (unsigned i = 0; i < ResourceCount; ++i) {
1919 ReservedCyclesIndex[i] = NumUnits;
1920 NumUnits += SchedModel->getProcResource(i)->NumUnits;
1921 }
1922
1923 ReservedCycles.resize(NumUnits, InvalidCycle);
Andrew Trick5a22df42013-12-05 17:56:02 +00001924 }
Andrew Trick3ca33ac2012-11-07 07:05:09 +00001925}
1926
Andrew Trick880e5732013-12-05 17:55:58 +00001927/// Compute the stall cycles based on this SUnit's ready time. Heuristics treat
1928/// these "soft stalls" differently than the hard stall cycles based on CPU
1929/// resources and computed by checkHazard(). A fully in-order model
1930/// (MicroOpBufferSize==0) will not make use of this since instructions are not
1931/// available for scheduling until they are ready. However, a weaker in-order
1932/// model may use this for heuristics. For example, if a processor has in-order
1933/// behavior when reading certain resources, this may come into play.
Andrew Trickfc127d12013-12-07 05:59:44 +00001934unsigned SchedBoundary::getLatencyStallCycles(SUnit *SU) {
Andrew Trick880e5732013-12-05 17:55:58 +00001935 if (!SU->isUnbuffered)
1936 return 0;
1937
1938 unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
1939 if (ReadyCycle > CurrCycle)
1940 return ReadyCycle - CurrCycle;
1941 return 0;
1942}
1943
Momchil Velikovc396f092019-05-10 16:54:32 +00001944/// Compute the next cycle at which the given processor resource unit
1945/// can be scheduled.
1946unsigned SchedBoundary::getNextResourceCycleByInstance(unsigned InstanceIdx,
1947 unsigned Cycles) {
1948 unsigned NextUnreserved = ReservedCycles[InstanceIdx];
Andrew Trick5a22df42013-12-05 17:56:02 +00001949 // If this resource has never been used, always return cycle zero.
1950 if (NextUnreserved == InvalidCycle)
1951 return 0;
1952 // For bottom-up scheduling add the cycles needed for the current operation.
1953 if (!isTop())
1954 NextUnreserved += Cycles;
1955 return NextUnreserved;
1956}
1957
Momchil Velikovc396f092019-05-10 16:54:32 +00001958/// Compute the next cycle at which the given processor resource can be
1959/// scheduled. Returns the next cycle and the index of the processor resource
1960/// instance in the reserved cycles vector.
1961std::pair<unsigned, unsigned>
1962SchedBoundary::getNextResourceCycle(unsigned PIdx, unsigned Cycles) {
1963 unsigned MinNextUnreserved = InvalidCycle;
1964 unsigned InstanceIdx = 0;
1965 unsigned StartIndex = ReservedCyclesIndex[PIdx];
1966 unsigned NumberOfInstances = SchedModel->getProcResource(PIdx)->NumUnits;
1967 assert(NumberOfInstances > 0 &&
1968 "Cannot have zero instances of a ProcResource");
1969
1970 for (unsigned I = StartIndex, End = StartIndex + NumberOfInstances; I < End;
1971 ++I) {
1972 unsigned NextUnreserved = getNextResourceCycleByInstance(I, Cycles);
1973 if (MinNextUnreserved > NextUnreserved) {
1974 InstanceIdx = I;
1975 MinNextUnreserved = NextUnreserved;
1976 }
1977 }
1978 return std::make_pair(MinNextUnreserved, InstanceIdx);
1979}
1980
Andrew Trick8c9e6722012-06-29 03:23:24 +00001981/// Does this SU have a hazard within the current instruction group.
1982///
1983/// The scheduler supports two modes of hazard recognition. The first is the
1984/// ScheduleHazardRecognizer API. It is a fully general hazard recognizer that
1985/// supports highly complicated in-order reservation tables
Hiroshi Inouec73b6d62018-06-20 05:29:26 +00001986/// (ScoreboardHazardRecognizer) and arbitrary target-specific logic.
Andrew Trick8c9e6722012-06-29 03:23:24 +00001987///
1988/// The second is a streamlined mechanism that checks for hazards based on
1989/// simple counters that the scheduler itself maintains. It explicitly checks
1990/// for instruction dispatch limitations, including the number of micro-ops that
1991/// can dispatch per cycle.
1992///
1993/// TODO: Also check whether the SU must start a new group.
Andrew Trickfc127d12013-12-07 05:59:44 +00001994bool SchedBoundary::checkHazard(SUnit *SU) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00001995 if (HazardRec->isEnabled()
1996 && HazardRec->getHazardType(SU) != ScheduleHazardRecognizer::NoHazard) {
1997 return true;
1998 }
Javed Absar3d594372017-03-27 20:46:37 +00001999
Andrew Trickdd79f0f2012-10-10 05:43:09 +00002000 unsigned uops = SchedModel->getNumMicroOps(SU->getInstr());
Andrew Tricke2ff5752013-06-15 04:49:49 +00002001 if ((CurrMOps > 0) && (CurrMOps + uops > SchedModel->getIssueWidth())) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002002 LLVM_DEBUG(dbgs() << " SU(" << SU->NodeNum << ") uops="
2003 << SchedModel->getNumMicroOps(SU->getInstr()) << '\n');
Andrew Trick8c9e6722012-06-29 03:23:24 +00002004 return true;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002005 }
Javed Absar3d594372017-03-27 20:46:37 +00002006
2007 if (CurrMOps > 0 &&
2008 ((isTop() && SchedModel->mustBeginGroup(SU->getInstr())) ||
2009 (!isTop() && SchedModel->mustEndGroup(SU->getInstr())))) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002010 LLVM_DEBUG(dbgs() << " hazard: SU(" << SU->NodeNum << ") must "
2011 << (isTop() ? "begin" : "end") << " group\n");
Javed Absar3d594372017-03-27 20:46:37 +00002012 return true;
2013 }
2014
Andrew Trick5a22df42013-12-05 17:56:02 +00002015 if (SchedModel->hasInstrSchedModel() && SU->hasReservedResource) {
2016 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
Javed Absare485b142017-10-03 09:35:04 +00002017 for (const MCWriteProcResEntry &PE :
2018 make_range(SchedModel->getWriteProcResBegin(SC),
2019 SchedModel->getWriteProcResEnd(SC))) {
2020 unsigned ResIdx = PE.ProcResourceIdx;
2021 unsigned Cycles = PE.Cycles;
Momchil Velikovc396f092019-05-10 16:54:32 +00002022 unsigned NRCycle, InstanceIdx;
2023 std::tie(NRCycle, InstanceIdx) = getNextResourceCycle(ResIdx, Cycles);
Andrew Trick56327222014-06-27 04:57:05 +00002024 if (NRCycle > CurrCycle) {
Andrew Trick040c0da2014-06-27 05:09:36 +00002025#ifndef NDEBUG
Javed Absare485b142017-10-03 09:35:04 +00002026 MaxObservedStall = std::max(Cycles, MaxObservedStall);
Andrew Trick040c0da2014-06-27 05:09:36 +00002027#endif
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002028 LLVM_DEBUG(dbgs() << " SU(" << SU->NodeNum << ") "
Momchil Velikovc396f092019-05-10 16:54:32 +00002029 << SchedModel->getResourceName(ResIdx)
2030 << '[' << InstanceIdx - ReservedCyclesIndex[ResIdx] << ']'
2031 << "=" << NRCycle << "c\n");
Andrew Trick5a22df42013-12-05 17:56:02 +00002032 return true;
Andrew Trick56327222014-06-27 04:57:05 +00002033 }
Andrew Trick5a22df42013-12-05 17:56:02 +00002034 }
2035 }
Andrew Trick8c9e6722012-06-29 03:23:24 +00002036 return false;
2037}
2038
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002039// Find the unscheduled node in ReadySUs with the highest latency.
Andrew Trickfc127d12013-12-07 05:59:44 +00002040unsigned SchedBoundary::
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002041findMaxLatency(ArrayRef<SUnit*> ReadySUs) {
Craig Topperc0196b12014-04-14 00:51:57 +00002042 SUnit *LateSU = nullptr;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002043 unsigned RemLatency = 0;
Javed Absare3a0cc22017-06-21 09:10:10 +00002044 for (SUnit *SU : ReadySUs) {
2045 unsigned L = getUnscheduledLatency(SU);
Andrew Trickf5b8ef22013-06-15 04:49:44 +00002046 if (L > RemLatency) {
Andrew Trickd6d5ad32012-12-18 20:52:56 +00002047 RemLatency = L;
Javed Absare3a0cc22017-06-21 09:10:10 +00002048 LateSU = SU;
Andrew Trickf5b8ef22013-06-15 04:49:44 +00002049 }
Andrew Trickd6d5ad32012-12-18 20:52:56 +00002050 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002051 if (LateSU) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002052 LLVM_DEBUG(dbgs() << Available.getName() << " RemLatency SU("
2053 << LateSU->NodeNum << ") " << RemLatency << "c\n");
Andrew Trickd6d5ad32012-12-18 20:52:56 +00002054 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002055 return RemLatency;
2056}
Andrew Trickf5b8ef22013-06-15 04:49:44 +00002057
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002058// Count resources in this zone and the remaining unscheduled
2059// instruction. Return the max count, scaled. Set OtherCritIdx to the critical
2060// resource index, or zero if the zone is issue limited.
Andrew Trickfc127d12013-12-07 05:59:44 +00002061unsigned SchedBoundary::
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002062getOtherResourceCount(unsigned &OtherCritIdx) {
Alexey Samsonov64c391d2013-07-19 08:55:18 +00002063 OtherCritIdx = 0;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002064 if (!SchedModel->hasInstrSchedModel())
2065 return 0;
2066
2067 unsigned OtherCritCount = Rem->RemIssueCount
2068 + (RetiredMOps * SchedModel->getMicroOpFactor());
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002069 LLVM_DEBUG(dbgs() << " " << Available.getName() << " + Remain MOps: "
2070 << OtherCritCount / SchedModel->getMicroOpFactor() << '\n');
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002071 for (unsigned PIdx = 1, PEnd = SchedModel->getNumProcResourceKinds();
2072 PIdx != PEnd; ++PIdx) {
2073 unsigned OtherCount = getResourceCount(PIdx) + Rem->RemainingCounts[PIdx];
2074 if (OtherCount > OtherCritCount) {
2075 OtherCritCount = OtherCount;
2076 OtherCritIdx = PIdx;
2077 }
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002078 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002079 if (OtherCritIdx) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002080 LLVM_DEBUG(
2081 dbgs() << " " << Available.getName() << " + Remain CritRes: "
2082 << OtherCritCount / SchedModel->getResourceFactor(OtherCritIdx)
2083 << " " << SchedModel->getResourceName(OtherCritIdx) << "\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002084 }
2085 return OtherCritCount;
2086}
2087
Andrew Trickfc127d12013-12-07 05:59:44 +00002088void SchedBoundary::releaseNode(SUnit *SU, unsigned ReadyCycle) {
Andrew Trick7f1ebbe2014-06-07 01:48:43 +00002089 assert(SU->getInstr() && "Scheduled SUnit must have instr");
2090
2091#ifndef NDEBUG
Andrew Trick491e34a2014-06-12 22:36:28 +00002092 // ReadyCycle was been bumped up to the CurrCycle when this node was
2093 // scheduled, but CurrCycle may have been eagerly advanced immediately after
2094 // scheduling, so may now be greater than ReadyCycle.
2095 if (ReadyCycle > CurrCycle)
2096 MaxObservedStall = std::max(ReadyCycle - CurrCycle, MaxObservedStall);
Andrew Trick7f1ebbe2014-06-07 01:48:43 +00002097#endif
2098
Andrew Trick61f1a272012-05-24 22:11:09 +00002099 if (ReadyCycle < MinReadyCycle)
2100 MinReadyCycle = ReadyCycle;
2101
2102 // Check for interlocks first. For the purpose of other heuristics, an
2103 // instruction that cannot issue appears as if it's not in the ReadyQueue.
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002104 bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
Matthias Braun6493bc22016-04-22 19:09:17 +00002105 if ((!IsBuffered && ReadyCycle > CurrCycle) || checkHazard(SU) ||
2106 Available.size() >= ReadyListLimit)
Andrew Trick61f1a272012-05-24 22:11:09 +00002107 Pending.push(SU);
2108 else
2109 Available.push(SU);
2110}
2111
2112/// Move the boundary of scheduled code by one cycle.
Andrew Trickfc127d12013-12-07 05:59:44 +00002113void SchedBoundary::bumpCycle(unsigned NextCycle) {
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002114 if (SchedModel->getMicroOpBufferSize() == 0) {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00002115 assert(MinReadyCycle < std::numeric_limits<unsigned>::max() &&
2116 "MinReadyCycle uninitialized");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002117 if (MinReadyCycle > NextCycle)
2118 NextCycle = MinReadyCycle;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002119 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002120 // Update the current micro-ops, which will issue in the next cycle.
2121 unsigned DecMOps = SchedModel->getIssueWidth() * (NextCycle - CurrCycle);
2122 CurrMOps = (CurrMOps <= DecMOps) ? 0 : CurrMOps - DecMOps;
2123
2124 // Decrement DependentLatency based on the next cycle.
Andrew Trickf5b8ef22013-06-15 04:49:44 +00002125 if ((NextCycle - CurrCycle) > DependentLatency)
2126 DependentLatency = 0;
2127 else
2128 DependentLatency -= (NextCycle - CurrCycle);
Andrew Trick61f1a272012-05-24 22:11:09 +00002129
2130 if (!HazardRec->isEnabled()) {
Andrew Trick45446062012-06-05 21:11:27 +00002131 // Bypass HazardRec virtual calls.
Andrew Trick61f1a272012-05-24 22:11:09 +00002132 CurrCycle = NextCycle;
Matthias Braunb550b762016-04-21 01:54:13 +00002133 } else {
Andrew Trick45446062012-06-05 21:11:27 +00002134 // Bypass getHazardType calls in case of long latency.
Andrew Trick61f1a272012-05-24 22:11:09 +00002135 for (; CurrCycle != NextCycle; ++CurrCycle) {
2136 if (isTop())
2137 HazardRec->AdvanceCycle();
2138 else
2139 HazardRec->RecedeCycle();
2140 }
2141 }
2142 CheckPending = true;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002143 IsResourceLimited =
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002144 checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
Jinsong Ji7aafdef2019-06-07 14:54:47 +00002145 getScheduledLatency(), true);
Andrew Trick61f1a272012-05-24 22:11:09 +00002146
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002147 LLVM_DEBUG(dbgs() << "Cycle: " << CurrCycle << ' ' << Available.getName()
2148 << '\n');
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002149}
2150
Andrew Trickfc127d12013-12-07 05:59:44 +00002151void SchedBoundary::incExecutedResources(unsigned PIdx, unsigned Count) {
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002152 ExecutedResCounts[PIdx] += Count;
2153 if (ExecutedResCounts[PIdx] > MaxExecutedResCount)
2154 MaxExecutedResCount = ExecutedResCounts[PIdx];
Andrew Trick61f1a272012-05-24 22:11:09 +00002155}
2156
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002157/// Add the given processor resource to this scheduled zone.
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002158///
2159/// \param Cycles indicates the number of consecutive (non-pipelined) cycles
2160/// during which this resource is consumed.
2161///
2162/// \return the next cycle at which the instruction may execute without
2163/// oversubscribing resources.
Andrew Trickfc127d12013-12-07 05:59:44 +00002164unsigned SchedBoundary::
Andrew Trick5a22df42013-12-05 17:56:02 +00002165countResource(unsigned PIdx, unsigned Cycles, unsigned NextCycle) {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002166 unsigned Factor = SchedModel->getResourceFactor(PIdx);
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002167 unsigned Count = Factor * Cycles;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002168 LLVM_DEBUG(dbgs() << " " << SchedModel->getResourceName(PIdx) << " +"
2169 << Cycles << "x" << Factor << "u\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002170
2171 // Update Executed resources counts.
2172 incExecutedResources(PIdx, Count);
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002173 assert(Rem->RemainingCounts[PIdx] >= Count && "resource double counted");
2174 Rem->RemainingCounts[PIdx] -= Count;
2175
Andrew Trickb13ef172013-07-19 00:20:07 +00002176 // Check if this resource exceeds the current critical resource. If so, it
2177 // becomes the critical resource.
2178 if (ZoneCritResIdx != PIdx && (getResourceCount(PIdx) > getCriticalCount())) {
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002179 ZoneCritResIdx = PIdx;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002180 LLVM_DEBUG(dbgs() << " *** Critical resource "
2181 << SchedModel->getResourceName(PIdx) << ": "
2182 << getResourceCount(PIdx) / SchedModel->getLatencyFactor()
2183 << "c\n");
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002184 }
Andrew Trick5a22df42013-12-05 17:56:02 +00002185 // For reserved resources, record the highest cycle using the resource.
Momchil Velikovc396f092019-05-10 16:54:32 +00002186 unsigned NextAvailable, InstanceIdx;
2187 std::tie(NextAvailable, InstanceIdx) = getNextResourceCycle(PIdx, Cycles);
Andrew Trick5a22df42013-12-05 17:56:02 +00002188 if (NextAvailable > CurrCycle) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002189 LLVM_DEBUG(dbgs() << " Resource conflict: "
Momchil Velikovc396f092019-05-10 16:54:32 +00002190 << SchedModel->getResourceName(PIdx)
2191 << '[' << InstanceIdx - ReservedCyclesIndex[PIdx] << ']'
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002192 << " reserved until @" << NextAvailable << "\n");
Andrew Trick5a22df42013-12-05 17:56:02 +00002193 }
2194 return NextAvailable;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002195}
2196
Andrew Trick45446062012-06-05 21:11:27 +00002197/// Move the boundary of scheduled code by one SUnit.
Andrew Trickfc127d12013-12-07 05:59:44 +00002198void SchedBoundary::bumpNode(SUnit *SU) {
Andrew Trick45446062012-06-05 21:11:27 +00002199 // Update the reservation table.
2200 if (HazardRec->isEnabled()) {
2201 if (!isTop() && SU->isCall) {
2202 // Calls are scheduled with their preceding instructions. For bottom-up
2203 // scheduling, clear the pipeline state before emitting.
2204 HazardRec->Reset();
2205 }
2206 HazardRec->EmitInstruction(SU);
James Molloy9ad4cb32019-04-19 09:00:55 +00002207 // Scheduling an instruction may have made pending instructions available.
2208 CheckPending = true;
Andrew Trick45446062012-06-05 21:11:27 +00002209 }
Andrew Trick5a22df42013-12-05 17:56:02 +00002210 // checkHazard should prevent scheduling multiple instructions per cycle that
2211 // exceed the issue width.
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002212 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
2213 unsigned IncMOps = SchedModel->getNumMicroOps(SU->getInstr());
Daniel Jasper0d92abd2013-12-06 08:58:22 +00002214 assert(
2215 (CurrMOps == 0 || (CurrMOps + IncMOps) <= SchedModel->getIssueWidth()) &&
Andrew Trickf7760a22013-12-06 17:19:20 +00002216 "Cannot schedule this instruction's MicroOps in the current cycle.");
Andrew Trick5a22df42013-12-05 17:56:02 +00002217
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002218 unsigned ReadyCycle = (isTop() ? SU->TopReadyCycle : SU->BotReadyCycle);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002219 LLVM_DEBUG(dbgs() << " Ready @" << ReadyCycle << "c\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002220
Andrew Trick5a22df42013-12-05 17:56:02 +00002221 unsigned NextCycle = CurrCycle;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002222 switch (SchedModel->getMicroOpBufferSize()) {
2223 case 0:
2224 assert(ReadyCycle <= CurrCycle && "Broken PendingQueue");
2225 break;
2226 case 1:
2227 if (ReadyCycle > NextCycle) {
2228 NextCycle = ReadyCycle;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002229 LLVM_DEBUG(dbgs() << " *** Stall until: " << ReadyCycle << "\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002230 }
2231 break;
2232 default:
2233 // We don't currently model the OOO reorder buffer, so consider all
Andrew Trick880e5732013-12-05 17:55:58 +00002234 // scheduled MOps to be "retired". We do loosely model in-order resource
2235 // latency. If this instruction uses an in-order resource, account for any
2236 // likely stall cycles.
2237 if (SU->isUnbuffered && ReadyCycle > NextCycle)
2238 NextCycle = ReadyCycle;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002239 break;
2240 }
2241 RetiredMOps += IncMOps;
2242
2243 // Update resource counts and critical resource.
2244 if (SchedModel->hasInstrSchedModel()) {
2245 unsigned DecRemIssue = IncMOps * SchedModel->getMicroOpFactor();
2246 assert(Rem->RemIssueCount >= DecRemIssue && "MOps double counted");
2247 Rem->RemIssueCount -= DecRemIssue;
2248 if (ZoneCritResIdx) {
2249 // Scale scheduled micro-ops for comparing with the critical resource.
2250 unsigned ScaledMOps =
2251 RetiredMOps * SchedModel->getMicroOpFactor();
2252
2253 // If scaled micro-ops are now more than the previous critical resource by
2254 // a full cycle, then micro-ops issue becomes critical.
2255 if ((int)(ScaledMOps - getResourceCount(ZoneCritResIdx))
2256 >= (int)SchedModel->getLatencyFactor()) {
2257 ZoneCritResIdx = 0;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002258 LLVM_DEBUG(dbgs() << " *** Critical resource NumMicroOps: "
2259 << ScaledMOps / SchedModel->getLatencyFactor()
2260 << "c\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002261 }
2262 }
2263 for (TargetSchedModel::ProcResIter
2264 PI = SchedModel->getWriteProcResBegin(SC),
2265 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2266 unsigned RCycle =
Andrew Trick5a22df42013-12-05 17:56:02 +00002267 countResource(PI->ProcResourceIdx, PI->Cycles, NextCycle);
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002268 if (RCycle > NextCycle)
2269 NextCycle = RCycle;
2270 }
Andrew Trick5a22df42013-12-05 17:56:02 +00002271 if (SU->hasReservedResource) {
2272 // For reserved resources, record the highest cycle using the resource.
2273 // For top-down scheduling, this is the cycle in which we schedule this
2274 // instruction plus the number of cycles the operations reserves the
2275 // resource. For bottom-up is it simply the instruction's cycle.
2276 for (TargetSchedModel::ProcResIter
2277 PI = SchedModel->getWriteProcResBegin(SC),
2278 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2279 unsigned PIdx = PI->ProcResourceIdx;
Andrew Trickd14d7c22013-12-28 21:56:57 +00002280 if (SchedModel->getProcResource(PIdx)->BufferSize == 0) {
Momchil Velikovc396f092019-05-10 16:54:32 +00002281 unsigned ReservedUntil, InstanceIdx;
2282 std::tie(ReservedUntil, InstanceIdx) = getNextResourceCycle(PIdx, 0);
Chad Rosieraba845e2014-07-02 16:46:08 +00002283 if (isTop()) {
Momchil Velikovc396f092019-05-10 16:54:32 +00002284 ReservedCycles[InstanceIdx] =
2285 std::max(ReservedUntil, NextCycle + PI->Cycles);
2286 } else
2287 ReservedCycles[InstanceIdx] = NextCycle;
Andrew Trickd14d7c22013-12-28 21:56:57 +00002288 }
Andrew Trick5a22df42013-12-05 17:56:02 +00002289 }
2290 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002291 }
2292 // Update ExpectedLatency and DependentLatency.
2293 unsigned &TopLatency = isTop() ? ExpectedLatency : DependentLatency;
2294 unsigned &BotLatency = isTop() ? DependentLatency : ExpectedLatency;
2295 if (SU->getDepth() > TopLatency) {
2296 TopLatency = SU->getDepth();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002297 LLVM_DEBUG(dbgs() << " " << Available.getName() << " TopLatency SU("
2298 << SU->NodeNum << ") " << TopLatency << "c\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002299 }
2300 if (SU->getHeight() > BotLatency) {
2301 BotLatency = SU->getHeight();
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002302 LLVM_DEBUG(dbgs() << " " << Available.getName() << " BotLatency SU("
2303 << SU->NodeNum << ") " << BotLatency << "c\n");
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002304 }
2305 // If we stall for any reason, bump the cycle.
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002306 if (NextCycle > CurrCycle)
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002307 bumpCycle(NextCycle);
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002308 else
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002309 // After updating ZoneCritResIdx and ExpectedLatency, check if we're
Alp Tokercb402912014-01-24 17:20:08 +00002310 // resource limited. If a stall occurred, bumpCycle does this.
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002311 IsResourceLimited =
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002312 checkResourceLimit(SchedModel->getLatencyFactor(), getCriticalCount(),
Jinsong Ji7aafdef2019-06-07 14:54:47 +00002313 getScheduledLatency(), true);
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002314
Andrew Trick5a22df42013-12-05 17:56:02 +00002315 // Update CurrMOps after calling bumpCycle to handle stalls, since bumpCycle
2316 // resets CurrMOps. Loop to handle instructions with more MOps than issue in
2317 // one cycle. Since we commonly reach the max MOps here, opportunistically
2318 // bump the cycle to avoid uselessly checking everything in the readyQ.
2319 CurrMOps += IncMOps;
Javed Absar3d594372017-03-27 20:46:37 +00002320
2321 // Bump the cycle count for issue group constraints.
2322 // This must be done after NextCycle has been adjust for all other stalls.
2323 // Calling bumpCycle(X) will reduce CurrMOps by one issue group and set
2324 // currCycle to X.
2325 if ((isTop() && SchedModel->mustEndGroup(SU->getInstr())) ||
2326 (!isTop() && SchedModel->mustBeginGroup(SU->getInstr()))) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002327 LLVM_DEBUG(dbgs() << " Bump cycle to " << (isTop() ? "end" : "begin")
2328 << " group\n");
Javed Absar3d594372017-03-27 20:46:37 +00002329 bumpCycle(++NextCycle);
2330 }
2331
Andrew Trick5a22df42013-12-05 17:56:02 +00002332 while (CurrMOps >= SchedModel->getIssueWidth()) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002333 LLVM_DEBUG(dbgs() << " *** Max MOps " << CurrMOps << " at cycle "
2334 << CurrCycle << '\n');
Andrew Trickd14d7c22013-12-28 21:56:57 +00002335 bumpCycle(++NextCycle);
Andrew Trick5a22df42013-12-05 17:56:02 +00002336 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002337 LLVM_DEBUG(dumpScheduledState());
Andrew Trick45446062012-06-05 21:11:27 +00002338}
2339
Andrew Trick61f1a272012-05-24 22:11:09 +00002340/// Release pending ready nodes in to the available queue. This makes them
2341/// visible to heuristics.
Andrew Trickfc127d12013-12-07 05:59:44 +00002342void SchedBoundary::releasePending() {
Andrew Trick61f1a272012-05-24 22:11:09 +00002343 // If the available queue is empty, it is safe to reset MinReadyCycle.
2344 if (Available.empty())
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00002345 MinReadyCycle = std::numeric_limits<unsigned>::max();
Andrew Trick61f1a272012-05-24 22:11:09 +00002346
2347 // Check to see if any of the pending instructions are ready to issue. If
2348 // so, add them to the available queue.
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002349 bool IsBuffered = SchedModel->getMicroOpBufferSize() != 0;
Andrew Trick61f1a272012-05-24 22:11:09 +00002350 for (unsigned i = 0, e = Pending.size(); i != e; ++i) {
2351 SUnit *SU = *(Pending.begin()+i);
Andrew Trick45446062012-06-05 21:11:27 +00002352 unsigned ReadyCycle = isTop() ? SU->TopReadyCycle : SU->BotReadyCycle;
Andrew Trick61f1a272012-05-24 22:11:09 +00002353
2354 if (ReadyCycle < MinReadyCycle)
2355 MinReadyCycle = ReadyCycle;
2356
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002357 if (!IsBuffered && ReadyCycle > CurrCycle)
Andrew Trick61f1a272012-05-24 22:11:09 +00002358 continue;
2359
Andrew Trick8c9e6722012-06-29 03:23:24 +00002360 if (checkHazard(SU))
Andrew Trick61f1a272012-05-24 22:11:09 +00002361 continue;
2362
Matthias Braun6493bc22016-04-22 19:09:17 +00002363 if (Available.size() >= ReadyListLimit)
2364 break;
2365
Andrew Trick61f1a272012-05-24 22:11:09 +00002366 Available.push(SU);
2367 Pending.remove(Pending.begin()+i);
2368 --i; --e;
2369 }
2370 CheckPending = false;
2371}
2372
2373/// Remove SU from the ready set for this boundary.
Andrew Trickfc127d12013-12-07 05:59:44 +00002374void SchedBoundary::removeReady(SUnit *SU) {
Andrew Trick61f1a272012-05-24 22:11:09 +00002375 if (Available.isInQueue(SU))
2376 Available.remove(Available.find(SU));
2377 else {
2378 assert(Pending.isInQueue(SU) && "bad ready count");
2379 Pending.remove(Pending.find(SU));
2380 }
2381}
2382
2383/// If this queue only has one ready candidate, return it. As a side effect,
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002384/// defer any nodes that now hit a hazard, and advance the cycle until at least
2385/// one node is ready. If multiple instructions are ready, return NULL.
Andrew Trickfc127d12013-12-07 05:59:44 +00002386SUnit *SchedBoundary::pickOnlyChoice() {
Andrew Trick61f1a272012-05-24 22:11:09 +00002387 if (CheckPending)
2388 releasePending();
2389
Andrew Tricke2ff5752013-06-15 04:49:49 +00002390 if (CurrMOps > 0) {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002391 // Defer any ready instrs that now have a hazard.
2392 for (ReadyQueue::iterator I = Available.begin(); I != Available.end();) {
2393 if (checkHazard(*I)) {
2394 Pending.push(*I);
2395 I = Available.remove(I);
2396 continue;
2397 }
2398 ++I;
2399 }
2400 }
Andrew Trick61f1a272012-05-24 22:11:09 +00002401 for (unsigned i = 0; Available.empty(); ++i) {
Chad Rosieraba845e2014-07-02 16:46:08 +00002402// FIXME: Re-enable assert once PR20057 is resolved.
2403// assert(i <= (HazardRec->getMaxLookAhead() + MaxObservedStall) &&
2404// "permanent hazard");
2405 (void)i;
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002406 bumpCycle(CurrCycle + 1);
Andrew Trick61f1a272012-05-24 22:11:09 +00002407 releasePending();
2408 }
Matthias Braund29d31e2016-06-23 21:27:38 +00002409
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002410 LLVM_DEBUG(Pending.dump());
2411 LLVM_DEBUG(Available.dump());
Matthias Braund29d31e2016-06-23 21:27:38 +00002412
Andrew Trick61f1a272012-05-24 22:11:09 +00002413 if (Available.size() == 1)
2414 return *Available.begin();
Craig Topperc0196b12014-04-14 00:51:57 +00002415 return nullptr;
Andrew Trick61f1a272012-05-24 22:11:09 +00002416}
2417
Aaron Ballman615eb472017-10-15 14:32:27 +00002418#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002419// This is useful information to dump after bumpNode.
2420// Note that the Queue contents are more useful before pickNodeFromQueue.
Sam Clegg705f7982017-06-21 22:19:17 +00002421LLVM_DUMP_METHOD void SchedBoundary::dumpScheduledState() const {
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002422 unsigned ResFactor;
2423 unsigned ResCount;
2424 if (ZoneCritResIdx) {
2425 ResFactor = SchedModel->getResourceFactor(ZoneCritResIdx);
2426 ResCount = getResourceCount(ZoneCritResIdx);
Matthias Braunb550b762016-04-21 01:54:13 +00002427 } else {
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002428 ResFactor = SchedModel->getMicroOpFactor();
Javed Absar1a77bcc2017-09-27 10:31:58 +00002429 ResCount = RetiredMOps * ResFactor;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002430 }
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002431 unsigned LFactor = SchedModel->getLatencyFactor();
2432 dbgs() << Available.getName() << " @" << CurrCycle << "c\n"
2433 << " Retired: " << RetiredMOps;
2434 dbgs() << "\n Executed: " << getExecutedCount() / LFactor << "c";
2435 dbgs() << "\n Critical: " << ResCount / LFactor << "c, "
Andrew Trickfc127d12013-12-07 05:59:44 +00002436 << ResCount / ResFactor << " "
2437 << SchedModel->getResourceName(ZoneCritResIdx)
Andrew Trickf78e7fa2013-06-15 05:39:19 +00002438 << "\n ExpectedLatency: " << ExpectedLatency << "c\n"
2439 << (IsResourceLimited ? " - Resource" : " - Latency")
2440 << " limited.\n";
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002441}
Andrew Trick8e8415f2013-06-15 05:46:47 +00002442#endif
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002443
Andrew Trickfc127d12013-12-07 05:59:44 +00002444//===----------------------------------------------------------------------===//
Andrew Trickd14d7c22013-12-28 21:56:57 +00002445// GenericScheduler - Generic implementation of MachineSchedStrategy.
Andrew Trickfc127d12013-12-07 05:59:44 +00002446//===----------------------------------------------------------------------===//
2447
Andrew Trickd14d7c22013-12-28 21:56:57 +00002448void GenericSchedulerBase::SchedCandidate::
2449initResourceDelta(const ScheduleDAGMI *DAG,
2450 const TargetSchedModel *SchedModel) {
2451 if (!Policy.ReduceResIdx && !Policy.DemandResIdx)
2452 return;
2453
2454 const MCSchedClassDesc *SC = DAG->getSchedClass(SU);
2455 for (TargetSchedModel::ProcResIter
2456 PI = SchedModel->getWriteProcResBegin(SC),
2457 PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
2458 if (PI->ProcResourceIdx == Policy.ReduceResIdx)
2459 ResDelta.CritResources += PI->Cycles;
2460 if (PI->ProcResourceIdx == Policy.DemandResIdx)
2461 ResDelta.DemandedResources += PI->Cycles;
2462 }
2463}
2464
Tom Stellardecd6aa52018-08-21 21:48:43 +00002465/// Compute remaining latency. We need this both to determine whether the
2466/// overall schedule has become latency-limited and whether the instructions
2467/// outside this zone are resource or latency limited.
2468///
2469/// The "dependent" latency is updated incrementally during scheduling as the
2470/// max height/depth of scheduled nodes minus the cycles since it was
2471/// scheduled:
2472/// DLat = max (N.depth - (CurrCycle - N.ReadyCycle) for N in Zone
2473///
2474/// The "independent" latency is the max ready queue depth:
2475/// ILat = max N.depth for N in Available|Pending
2476///
2477/// RemainingLatency is the greater of independent and dependent latency.
2478///
2479/// These computations are expensive, especially in DAGs with many edges, so
2480/// only do them if necessary.
2481static unsigned computeRemLatency(SchedBoundary &CurrZone) {
2482 unsigned RemLatency = CurrZone.getDependentLatency();
2483 RemLatency = std::max(RemLatency,
2484 CurrZone.findMaxLatency(CurrZone.Available.elements()));
2485 RemLatency = std::max(RemLatency,
2486 CurrZone.findMaxLatency(CurrZone.Pending.elements()));
2487 return RemLatency;
2488}
2489
2490/// Returns true if the current cycle plus remaning latency is greater than
Hiroshi Inouedad8c6a2019-01-09 05:11:10 +00002491/// the critical path in the scheduling region.
Tom Stellardecd6aa52018-08-21 21:48:43 +00002492bool GenericSchedulerBase::shouldReduceLatency(const CandPolicy &Policy,
2493 SchedBoundary &CurrZone,
2494 bool ComputeRemLatency,
2495 unsigned &RemLatency) const {
2496 // The current cycle is already greater than the critical path, so we are
Hiroshi Inouedad8c6a2019-01-09 05:11:10 +00002497 // already latency limited and don't need to compute the remaining latency.
Tom Stellardecd6aa52018-08-21 21:48:43 +00002498 if (CurrZone.getCurrCycle() > Rem.CriticalPath)
2499 return true;
2500
2501 // If we haven't scheduled anything yet, then we aren't latency limited.
2502 if (CurrZone.getCurrCycle() == 0)
2503 return false;
2504
2505 if (ComputeRemLatency)
2506 RemLatency = computeRemLatency(CurrZone);
2507
2508 return RemLatency + CurrZone.getCurrCycle() > Rem.CriticalPath;
2509}
2510
Andrew Trickd14d7c22013-12-28 21:56:57 +00002511/// Set the CandPolicy given a scheduling zone given the current resources and
2512/// latencies inside and outside the zone.
Matthias Braunb550b762016-04-21 01:54:13 +00002513void GenericSchedulerBase::setPolicy(CandPolicy &Policy, bool IsPostRA,
Andrew Trickd14d7c22013-12-28 21:56:57 +00002514 SchedBoundary &CurrZone,
2515 SchedBoundary *OtherZone) {
Eric Christopher572e03a2015-06-19 01:53:21 +00002516 // Apply preemptive heuristics based on the total latency and resources
Andrew Trickd14d7c22013-12-28 21:56:57 +00002517 // inside and outside this zone. Potential stalls should be considered before
2518 // following this policy.
2519
Andrew Trickd14d7c22013-12-28 21:56:57 +00002520 // Compute the critical resource outside the zone.
Andrew Trick7afe4812013-12-28 22:25:57 +00002521 unsigned OtherCritIdx = 0;
Andrew Trickd14d7c22013-12-28 21:56:57 +00002522 unsigned OtherCount =
2523 OtherZone ? OtherZone->getOtherResourceCount(OtherCritIdx) : 0;
2524
2525 bool OtherResLimited = false;
Tom Stellardecd6aa52018-08-21 21:48:43 +00002526 unsigned RemLatency = 0;
2527 bool RemLatencyComputed = false;
2528 if (SchedModel->hasInstrSchedModel() && OtherCount != 0) {
2529 RemLatency = computeRemLatency(CurrZone);
2530 RemLatencyComputed = true;
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002531 OtherResLimited = checkResourceLimit(SchedModel->getLatencyFactor(),
Jinsong Ji7aafdef2019-06-07 14:54:47 +00002532 OtherCount, RemLatency, false);
Tom Stellardecd6aa52018-08-21 21:48:43 +00002533 }
Jonas Paulsson238c14b2017-10-25 08:23:33 +00002534
Andrew Trickd14d7c22013-12-28 21:56:57 +00002535 // Schedule aggressively for latency in PostRA mode. We don't check for
2536 // acyclic latency during PostRA, and highly out-of-order processors will
2537 // skip PostRA scheduling.
Tom Stellardecd6aa52018-08-21 21:48:43 +00002538 if (!OtherResLimited &&
2539 (IsPostRA || shouldReduceLatency(Policy, CurrZone, !RemLatencyComputed,
2540 RemLatency))) {
2541 Policy.ReduceLatency |= true;
2542 LLVM_DEBUG(dbgs() << " " << CurrZone.Available.getName()
2543 << " RemainingLatency " << RemLatency << " + "
2544 << CurrZone.getCurrCycle() << "c > CritPath "
2545 << Rem.CriticalPath << "\n");
Andrew Trickd14d7c22013-12-28 21:56:57 +00002546 }
2547 // If the same resource is limiting inside and outside the zone, do nothing.
2548 if (CurrZone.getZoneCritResIdx() == OtherCritIdx)
2549 return;
2550
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002551 LLVM_DEBUG(if (CurrZone.isResourceLimited()) {
2552 dbgs() << " " << CurrZone.Available.getName() << " ResourceLimited: "
2553 << SchedModel->getResourceName(CurrZone.getZoneCritResIdx()) << "\n";
2554 } if (OtherResLimited) dbgs()
2555 << " RemainingLimit: "
2556 << SchedModel->getResourceName(OtherCritIdx) << "\n";
2557 if (!CurrZone.isResourceLimited() && !OtherResLimited) dbgs()
2558 << " Latency limited both directions.\n");
Andrew Trickd14d7c22013-12-28 21:56:57 +00002559
2560 if (CurrZone.isResourceLimited() && !Policy.ReduceResIdx)
2561 Policy.ReduceResIdx = CurrZone.getZoneCritResIdx();
2562
2563 if (OtherResLimited)
2564 Policy.DemandResIdx = OtherCritIdx;
2565}
2566
2567#ifndef NDEBUG
2568const char *GenericSchedulerBase::getReasonStr(
2569 GenericSchedulerBase::CandReason Reason) {
2570 switch (Reason) {
2571 case NoCand: return "NOCAND ";
Matthias Braun49cb6e92016-05-27 22:14:26 +00002572 case Only1: return "ONLY1 ";
Nirav Dave1241dcb2018-11-14 21:11:53 +00002573 case PhysReg: return "PHYS-REG ";
Andrew Trickd14d7c22013-12-28 21:56:57 +00002574 case RegExcess: return "REG-EXCESS";
2575 case RegCritical: return "REG-CRIT ";
2576 case Stall: return "STALL ";
2577 case Cluster: return "CLUSTER ";
2578 case Weak: return "WEAK ";
2579 case RegMax: return "REG-MAX ";
2580 case ResourceReduce: return "RES-REDUCE";
2581 case ResourceDemand: return "RES-DEMAND";
2582 case TopDepthReduce: return "TOP-DEPTH ";
2583 case TopPathReduce: return "TOP-PATH ";
2584 case BotHeightReduce:return "BOT-HEIGHT";
2585 case BotPathReduce: return "BOT-PATH ";
2586 case NextDefUse: return "DEF-USE ";
2587 case NodeOrder: return "ORDER ";
2588 };
2589 llvm_unreachable("Unknown reason!");
2590}
2591
2592void GenericSchedulerBase::traceCandidate(const SchedCandidate &Cand) {
2593 PressureChange P;
2594 unsigned ResIdx = 0;
2595 unsigned Latency = 0;
2596 switch (Cand.Reason) {
2597 default:
2598 break;
2599 case RegExcess:
2600 P = Cand.RPDelta.Excess;
2601 break;
2602 case RegCritical:
2603 P = Cand.RPDelta.CriticalMax;
2604 break;
2605 case RegMax:
2606 P = Cand.RPDelta.CurrentMax;
2607 break;
2608 case ResourceReduce:
2609 ResIdx = Cand.Policy.ReduceResIdx;
2610 break;
2611 case ResourceDemand:
2612 ResIdx = Cand.Policy.DemandResIdx;
2613 break;
2614 case TopDepthReduce:
2615 Latency = Cand.SU->getDepth();
2616 break;
2617 case TopPathReduce:
2618 Latency = Cand.SU->getHeight();
2619 break;
2620 case BotHeightReduce:
2621 Latency = Cand.SU->getHeight();
2622 break;
2623 case BotPathReduce:
2624 Latency = Cand.SU->getDepth();
2625 break;
2626 }
James Y Knighte72b0db2015-09-18 18:52:20 +00002627 dbgs() << " Cand SU(" << Cand.SU->NodeNum << ") " << getReasonStr(Cand.Reason);
Andrew Trickd14d7c22013-12-28 21:56:57 +00002628 if (P.isValid())
2629 dbgs() << " " << TRI->getRegPressureSetName(P.getPSet())
2630 << ":" << P.getUnitInc() << " ";
2631 else
2632 dbgs() << " ";
2633 if (ResIdx)
2634 dbgs() << " " << SchedModel->getProcResource(ResIdx)->Name << " ";
2635 else
2636 dbgs() << " ";
2637 if (Latency)
2638 dbgs() << " " << Latency << " cycles ";
2639 else
2640 dbgs() << " ";
2641 dbgs() << '\n';
2642}
2643#endif
2644
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002645namespace llvm {
Andrew Trickd14d7c22013-12-28 21:56:57 +00002646/// Return true if this heuristic determines order.
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002647bool tryLess(int TryVal, int CandVal,
2648 GenericSchedulerBase::SchedCandidate &TryCand,
2649 GenericSchedulerBase::SchedCandidate &Cand,
2650 GenericSchedulerBase::CandReason Reason) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00002651 if (TryVal < CandVal) {
2652 TryCand.Reason = Reason;
2653 return true;
2654 }
2655 if (TryVal > CandVal) {
2656 if (Cand.Reason > Reason)
2657 Cand.Reason = Reason;
2658 return true;
2659 }
Andrew Trickd14d7c22013-12-28 21:56:57 +00002660 return false;
2661}
2662
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002663bool tryGreater(int TryVal, int CandVal,
2664 GenericSchedulerBase::SchedCandidate &TryCand,
2665 GenericSchedulerBase::SchedCandidate &Cand,
2666 GenericSchedulerBase::CandReason Reason) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00002667 if (TryVal > CandVal) {
2668 TryCand.Reason = Reason;
2669 return true;
2670 }
2671 if (TryVal < CandVal) {
2672 if (Cand.Reason > Reason)
2673 Cand.Reason = Reason;
2674 return true;
2675 }
Andrew Trickd14d7c22013-12-28 21:56:57 +00002676 return false;
2677}
2678
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002679bool tryLatency(GenericSchedulerBase::SchedCandidate &TryCand,
2680 GenericSchedulerBase::SchedCandidate &Cand,
2681 SchedBoundary &Zone) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00002682 if (Zone.isTop()) {
2683 if (Cand.SU->getDepth() > Zone.getScheduledLatency()) {
2684 if (tryLess(TryCand.SU->getDepth(), Cand.SU->getDepth(),
2685 TryCand, Cand, GenericSchedulerBase::TopDepthReduce))
2686 return true;
2687 }
2688 if (tryGreater(TryCand.SU->getHeight(), Cand.SU->getHeight(),
2689 TryCand, Cand, GenericSchedulerBase::TopPathReduce))
2690 return true;
Matthias Braunb550b762016-04-21 01:54:13 +00002691 } else {
Andrew Trickd14d7c22013-12-28 21:56:57 +00002692 if (Cand.SU->getHeight() > Zone.getScheduledLatency()) {
2693 if (tryLess(TryCand.SU->getHeight(), Cand.SU->getHeight(),
2694 TryCand, Cand, GenericSchedulerBase::BotHeightReduce))
2695 return true;
2696 }
2697 if (tryGreater(TryCand.SU->getDepth(), Cand.SU->getDepth(),
2698 TryCand, Cand, GenericSchedulerBase::BotPathReduce))
2699 return true;
2700 }
2701 return false;
2702}
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002703} // end namespace llvm
Andrew Trickd14d7c22013-12-28 21:56:57 +00002704
Matthias Braun49cb6e92016-05-27 22:14:26 +00002705static void tracePick(GenericSchedulerBase::CandReason Reason, bool IsTop) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002706 LLVM_DEBUG(dbgs() << "Pick " << (IsTop ? "Top " : "Bot ")
2707 << GenericSchedulerBase::getReasonStr(Reason) << '\n');
Matthias Braun49cb6e92016-05-27 22:14:26 +00002708}
2709
Matthias Braun6ad3d052016-06-25 00:23:00 +00002710static void tracePick(const GenericSchedulerBase::SchedCandidate &Cand) {
2711 tracePick(Cand.Reason, Cand.AtTop);
Andrew Trickd14d7c22013-12-28 21:56:57 +00002712}
2713
Andrew Trickfc127d12013-12-07 05:59:44 +00002714void GenericScheduler::initialize(ScheduleDAGMI *dag) {
Andrew Trickd7f890e2013-12-28 21:56:47 +00002715 assert(dag->hasVRegLiveness() &&
2716 "(PreRA)GenericScheduler needs vreg liveness");
2717 DAG = static_cast<ScheduleDAGMILive*>(dag);
Andrew Trickfc127d12013-12-07 05:59:44 +00002718 SchedModel = DAG->getSchedModel();
2719 TRI = DAG->TRI;
2720
2721 Rem.init(DAG, SchedModel);
2722 Top.init(DAG, SchedModel, &Rem);
2723 Bot.init(DAG, SchedModel, &Rem);
2724
2725 // Initialize resource counts.
2726
2727 // Initialize the HazardRecognizers. If itineraries don't exist, are empty, or
2728 // are disabled, then these HazardRecs will be disabled.
2729 const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
Andrew Trickfc127d12013-12-07 05:59:44 +00002730 if (!Top.HazardRec) {
2731 Top.HazardRec =
Eric Christopher99556d72014-10-14 06:56:25 +00002732 DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
Eric Christopherd9134482014-08-04 21:25:23 +00002733 Itin, DAG);
Andrew Trickfc127d12013-12-07 05:59:44 +00002734 }
2735 if (!Bot.HazardRec) {
2736 Bot.HazardRec =
Eric Christopher99556d72014-10-14 06:56:25 +00002737 DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
Eric Christopherd9134482014-08-04 21:25:23 +00002738 Itin, DAG);
Andrew Trickfc127d12013-12-07 05:59:44 +00002739 }
Matthias Brauncc676c42016-06-25 02:03:36 +00002740 TopCand.SU = nullptr;
2741 BotCand.SU = nullptr;
Andrew Trickfc127d12013-12-07 05:59:44 +00002742}
2743
2744/// Initialize the per-region scheduling policy.
2745void GenericScheduler::initPolicy(MachineBasicBlock::iterator Begin,
2746 MachineBasicBlock::iterator End,
2747 unsigned NumRegionInstrs) {
Justin Bognerfdf9bf42017-10-10 23:50:49 +00002748 const MachineFunction &MF = *Begin->getMF();
Eric Christopher99556d72014-10-14 06:56:25 +00002749 const TargetLowering *TLI = MF.getSubtarget().getTargetLowering();
Andrew Trickfc127d12013-12-07 05:59:44 +00002750
2751 // Avoid setting up the register pressure tracker for small regions to save
2752 // compile time. As a rough heuristic, only track pressure when the number of
2753 // schedulable instructions exceeds half the integer register file.
Andrew Trick350ff2c2014-01-21 21:27:37 +00002754 RegionPolicy.ShouldTrackPressure = true;
Andrew Trick46753512014-01-22 03:38:55 +00002755 for (unsigned VT = MVT::i32; VT > (unsigned)MVT::i1; --VT) {
2756 MVT::SimpleValueType LegalIntVT = (MVT::SimpleValueType)VT;
2757 if (TLI->isTypeLegal(LegalIntVT)) {
Andrew Trick350ff2c2014-01-21 21:27:37 +00002758 unsigned NIntRegs = Context->RegClassInfo->getNumAllocatableRegs(
Andrew Trick46753512014-01-22 03:38:55 +00002759 TLI->getRegClassFor(LegalIntVT));
Andrew Trick350ff2c2014-01-21 21:27:37 +00002760 RegionPolicy.ShouldTrackPressure = NumRegionInstrs > (NIntRegs / 2);
2761 }
2762 }
Andrew Trickfc127d12013-12-07 05:59:44 +00002763
2764 // For generic targets, we default to bottom-up, because it's simpler and more
2765 // compile-time optimizations have been implemented in that direction.
2766 RegionPolicy.OnlyBottomUp = true;
2767
2768 // Allow the subtarget to override default policy.
Duncan P. N. Exon Smith63298722016-07-01 00:23:27 +00002769 MF.getSubtarget().overrideSchedPolicy(RegionPolicy, NumRegionInstrs);
Andrew Trickfc127d12013-12-07 05:59:44 +00002770
2771 // After subtarget overrides, apply command line options.
Matt Arsenault18659f82019-05-30 23:31:36 +00002772 if (!EnableRegPressure) {
Andrew Trickfc127d12013-12-07 05:59:44 +00002773 RegionPolicy.ShouldTrackPressure = false;
Matt Arsenault18659f82019-05-30 23:31:36 +00002774 RegionPolicy.ShouldTrackLaneMasks = false;
2775 }
Andrew Trickfc127d12013-12-07 05:59:44 +00002776
2777 // Check -misched-topdown/bottomup can force or unforce scheduling direction.
2778 // e.g. -misched-bottomup=false allows scheduling in both directions.
2779 assert((!ForceTopDown || !ForceBottomUp) &&
2780 "-misched-topdown incompatible with -misched-bottomup");
2781 if (ForceBottomUp.getNumOccurrences() > 0) {
2782 RegionPolicy.OnlyBottomUp = ForceBottomUp;
2783 if (RegionPolicy.OnlyBottomUp)
2784 RegionPolicy.OnlyTopDown = false;
2785 }
2786 if (ForceTopDown.getNumOccurrences() > 0) {
2787 RegionPolicy.OnlyTopDown = ForceTopDown;
2788 if (RegionPolicy.OnlyTopDown)
2789 RegionPolicy.OnlyBottomUp = false;
2790 }
2791}
2792
Sam Clegg705f7982017-06-21 22:19:17 +00002793void GenericScheduler::dumpPolicy() const {
Matthias Braun8c209aa2017-01-28 02:02:38 +00002794 // Cannot completely remove virtual function even in release mode.
Aaron Ballman615eb472017-10-15 14:32:27 +00002795#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
James Y Knighte72b0db2015-09-18 18:52:20 +00002796 dbgs() << "GenericScheduler RegionPolicy: "
2797 << " ShouldTrackPressure=" << RegionPolicy.ShouldTrackPressure
2798 << " OnlyTopDown=" << RegionPolicy.OnlyTopDown
2799 << " OnlyBottomUp=" << RegionPolicy.OnlyBottomUp
2800 << "\n";
Matthias Braun8c209aa2017-01-28 02:02:38 +00002801#endif
James Y Knighte72b0db2015-09-18 18:52:20 +00002802}
2803
Andrew Trickfc127d12013-12-07 05:59:44 +00002804/// Set IsAcyclicLatencyLimited if the acyclic path is longer than the cyclic
2805/// critical path by more cycles than it takes to drain the instruction buffer.
2806/// We estimate an upper bounds on in-flight instructions as:
2807///
2808/// CyclesPerIteration = max( CyclicPath, Loop-Resource-Height )
2809/// InFlightIterations = AcyclicPath / CyclesPerIteration
2810/// InFlightResources = InFlightIterations * LoopResources
2811///
2812/// TODO: Check execution resources in addition to IssueCount.
2813void GenericScheduler::checkAcyclicLatency() {
2814 if (Rem.CyclicCritPath == 0 || Rem.CyclicCritPath >= Rem.CriticalPath)
2815 return;
2816
2817 // Scaled number of cycles per loop iteration.
2818 unsigned IterCount =
2819 std::max(Rem.CyclicCritPath * SchedModel->getLatencyFactor(),
2820 Rem.RemIssueCount);
2821 // Scaled acyclic critical path.
2822 unsigned AcyclicCount = Rem.CriticalPath * SchedModel->getLatencyFactor();
2823 // InFlightCount = (AcyclicPath / IterCycles) * InstrPerLoop
2824 unsigned InFlightCount =
2825 (AcyclicCount * Rem.RemIssueCount + IterCount-1) / IterCount;
2826 unsigned BufferLimit =
2827 SchedModel->getMicroOpBufferSize() * SchedModel->getMicroOpFactor();
2828
2829 Rem.IsAcyclicLatencyLimited = InFlightCount > BufferLimit;
2830
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002831 LLVM_DEBUG(
2832 dbgs() << "IssueCycles="
2833 << Rem.RemIssueCount / SchedModel->getLatencyFactor() << "c "
2834 << "IterCycles=" << IterCount / SchedModel->getLatencyFactor()
2835 << "c NumIters=" << (AcyclicCount + IterCount - 1) / IterCount
2836 << " InFlight=" << InFlightCount / SchedModel->getMicroOpFactor()
2837 << "m BufferLim=" << SchedModel->getMicroOpBufferSize() << "m\n";
2838 if (Rem.IsAcyclicLatencyLimited) dbgs() << " ACYCLIC LATENCY LIMIT\n");
Andrew Trickfc127d12013-12-07 05:59:44 +00002839}
2840
2841void GenericScheduler::registerRoots() {
2842 Rem.CriticalPath = DAG->ExitSU.getDepth();
2843
2844 // Some roots may not feed into ExitSU. Check all of them in case.
Javed Absare3a0cc22017-06-21 09:10:10 +00002845 for (const SUnit *SU : Bot.Available) {
2846 if (SU->getDepth() > Rem.CriticalPath)
2847 Rem.CriticalPath = SU->getDepth();
Andrew Trickfc127d12013-12-07 05:59:44 +00002848 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002849 LLVM_DEBUG(dbgs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << '\n');
Gerolf Hoflehnerb5220dc2014-08-07 21:49:44 +00002850 if (DumpCriticalPathLength) {
2851 errs() << "Critical Path(GS-RR ): " << Rem.CriticalPath << " \n";
2852 }
Andrew Trickfc127d12013-12-07 05:59:44 +00002853
Matthias Braun99551052017-04-12 18:09:05 +00002854 if (EnableCyclicPath && SchedModel->getMicroOpBufferSize() > 0) {
Andrew Trickfc127d12013-12-07 05:59:44 +00002855 Rem.CyclicCritPath = DAG->computeCyclicCriticalPath();
2856 checkAcyclicLatency();
2857 }
2858}
2859
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002860namespace llvm {
2861bool tryPressure(const PressureChange &TryP,
2862 const PressureChange &CandP,
2863 GenericSchedulerBase::SchedCandidate &TryCand,
2864 GenericSchedulerBase::SchedCandidate &Cand,
2865 GenericSchedulerBase::CandReason Reason,
2866 const TargetRegisterInfo *TRI,
2867 const MachineFunction &MF) {
Andrew Trickb1a45b62013-08-30 04:27:29 +00002868 // If one candidate decreases and the other increases, go with it.
2869 // Invalid candidates have UnitInc==0.
Hal Finkel7a87f8a2014-10-10 17:06:20 +00002870 if (tryGreater(TryP.getUnitInc() < 0, CandP.getUnitInc() < 0, TryCand, Cand,
2871 Reason)) {
Andrew Trickb1a45b62013-08-30 04:27:29 +00002872 return true;
2873 }
Matthias Braun6ad3d052016-06-25 00:23:00 +00002874 // Do not compare the magnitude of pressure changes between top and bottom
2875 // boundary.
2876 if (Cand.AtTop != TryCand.AtTop)
2877 return false;
2878
2879 // If both candidates affect the same set in the same boundary, go with the
2880 // smallest increase.
2881 unsigned TryPSet = TryP.getPSetOrMax();
2882 unsigned CandPSet = CandP.getPSetOrMax();
2883 if (TryPSet == CandPSet) {
2884 return tryLess(TryP.getUnitInc(), CandP.getUnitInc(), TryCand, Cand,
2885 Reason);
2886 }
Tom Stellard5ce53062015-12-16 18:31:01 +00002887
2888 int TryRank = TryP.isValid() ? TRI->getRegPressureSetScore(MF, TryPSet) :
2889 std::numeric_limits<int>::max();
2890
2891 int CandRank = CandP.isValid() ? TRI->getRegPressureSetScore(MF, CandPSet) :
2892 std::numeric_limits<int>::max();
2893
Andrew Trick401b6952013-07-25 07:26:35 +00002894 // If the candidates are decreasing pressure, reverse priority.
Andrew Trick1a831342013-08-30 03:49:48 +00002895 if (TryP.getUnitInc() < 0)
Andrew Trick401b6952013-07-25 07:26:35 +00002896 std::swap(TryRank, CandRank);
2897 return tryGreater(TryRank, CandRank, TryCand, Cand, Reason);
2898}
2899
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002900unsigned getWeakLeft(const SUnit *SU, bool isTop) {
Andrew Tricka7714a02012-11-12 19:40:10 +00002901 return (isTop) ? SU->WeakPredsLeft : SU->WeakSuccsLeft;
2902}
2903
Andrew Tricke833e1c2013-04-13 06:07:40 +00002904/// Minimize physical register live ranges. Regalloc wants them adjacent to
2905/// their physreg def/use.
2906///
2907/// FIXME: This is an unnecessary check on the critical path. Most are root/leaf
2908/// copies which can be prescheduled. The rest (e.g. x86 MUL) could be bundled
2909/// with the operation that produces or consumes the physreg. We'll do this when
2910/// regalloc has support for parallel copies.
Nirav Dave1241dcb2018-11-14 21:11:53 +00002911int biasPhysReg(const SUnit *SU, bool isTop) {
Andrew Tricke833e1c2013-04-13 06:07:40 +00002912 const MachineInstr *MI = SU->getInstr();
Andrew Tricke833e1c2013-04-13 06:07:40 +00002913
Nirav Dave1241dcb2018-11-14 21:11:53 +00002914 if (MI->isCopy()) {
2915 unsigned ScheduledOper = isTop ? 1 : 0;
2916 unsigned UnscheduledOper = isTop ? 0 : 1;
2917 // If we have already scheduled the physreg produce/consumer, immediately
2918 // schedule the copy.
Daniel Sanders2bea69b2019-08-01 23:27:28 +00002919 if (Register::isPhysicalRegister(MI->getOperand(ScheduledOper).getReg()))
Nirav Dave1241dcb2018-11-14 21:11:53 +00002920 return 1;
2921 // If the physreg is at the boundary, defer it. Otherwise schedule it
2922 // immediately to free the dependent. We can hoist the copy later.
2923 bool AtBoundary = isTop ? !SU->NumSuccsLeft : !SU->NumPredsLeft;
Daniel Sanders2bea69b2019-08-01 23:27:28 +00002924 if (Register::isPhysicalRegister(MI->getOperand(UnscheduledOper).getReg()))
Nirav Dave1241dcb2018-11-14 21:11:53 +00002925 return AtBoundary ? -1 : 1;
2926 }
2927
2928 if (MI->isMoveImmediate()) {
2929 // If we have a move immediate and all successors have been assigned, bias
2930 // towards scheduling this later. Make sure all register defs are to
2931 // physical registers.
2932 bool DoBias = true;
2933 for (const MachineOperand &Op : MI->defs()) {
Daniel Sanders2bea69b2019-08-01 23:27:28 +00002934 if (Op.isReg() && !Register::isPhysicalRegister(Op.getReg())) {
Nirav Dave1241dcb2018-11-14 21:11:53 +00002935 DoBias = false;
2936 break;
2937 }
2938 }
2939
2940 if (DoBias)
2941 return isTop ? -1 : 1;
2942 }
2943
Andrew Tricke833e1c2013-04-13 06:07:40 +00002944 return 0;
2945}
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002946} // end namespace llvm
Andrew Tricke833e1c2013-04-13 06:07:40 +00002947
Matthias Braun4f573772016-04-22 19:10:15 +00002948void GenericScheduler::initCandidate(SchedCandidate &Cand, SUnit *SU,
2949 bool AtTop,
2950 const RegPressureTracker &RPTracker,
2951 RegPressureTracker &TempTracker) {
2952 Cand.SU = SU;
Matthias Braun6ad3d052016-06-25 00:23:00 +00002953 Cand.AtTop = AtTop;
Matthias Braun4f573772016-04-22 19:10:15 +00002954 if (DAG->isTrackingPressure()) {
2955 if (AtTop) {
2956 TempTracker.getMaxDownwardPressureDelta(
2957 Cand.SU->getInstr(),
2958 Cand.RPDelta,
2959 DAG->getRegionCriticalPSets(),
2960 DAG->getRegPressure().MaxSetPressure);
2961 } else {
2962 if (VerifyScheduling) {
2963 TempTracker.getMaxUpwardPressureDelta(
2964 Cand.SU->getInstr(),
2965 &DAG->getPressureDiff(Cand.SU),
2966 Cand.RPDelta,
2967 DAG->getRegionCriticalPSets(),
2968 DAG->getRegPressure().MaxSetPressure);
2969 } else {
2970 RPTracker.getUpwardPressureDelta(
2971 Cand.SU->getInstr(),
2972 DAG->getPressureDiff(Cand.SU),
2973 Cand.RPDelta,
2974 DAG->getRegionCriticalPSets(),
2975 DAG->getRegPressure().MaxSetPressure);
2976 }
2977 }
2978 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00002979 LLVM_DEBUG(if (Cand.RPDelta.Excess.isValid()) dbgs()
2980 << " Try SU(" << Cand.SU->NodeNum << ") "
2981 << TRI->getRegPressureSetName(Cand.RPDelta.Excess.getPSet()) << ":"
2982 << Cand.RPDelta.Excess.getUnitInc() << "\n");
Matthias Braun4f573772016-04-22 19:10:15 +00002983}
2984
Hiroshi Inouec73b6d62018-06-20 05:29:26 +00002985/// Apply a set of heuristics to a new candidate. Heuristics are currently
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002986/// hierarchical. This may be more efficient than a graduated cost model because
2987/// we don't need to evaluate all aspects of the model for each node in the
2988/// queue. But it's really done to make the heuristics easier to debug and
2989/// statistically analyze.
2990///
2991/// \param Cand provides the policy and current best candidate.
2992/// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
Matthias Braun6ad3d052016-06-25 00:23:00 +00002993/// \param Zone describes the scheduled zone that we are extending, or nullptr
2994// if Cand is from a different zone than TryCand.
Andrew Trick665d3ec2013-09-19 23:10:59 +00002995void GenericScheduler::tryCandidate(SchedCandidate &Cand,
Andrew Trickbb1247b2013-12-05 17:55:47 +00002996 SchedCandidate &TryCand,
Jonas Paulssone8f1ac72018-04-12 07:21:39 +00002997 SchedBoundary *Zone) const {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00002998 // Initialize the candidate if needed.
2999 if (!Cand.isValid()) {
3000 TryCand.Reason = NodeOrder;
3001 return;
3002 }
Andrew Tricke833e1c2013-04-13 06:07:40 +00003003
Nirav Dave1241dcb2018-11-14 21:11:53 +00003004 // Bias PhysReg Defs and copies to their uses and defined respectively.
3005 if (tryGreater(biasPhysReg(TryCand.SU, TryCand.AtTop),
3006 biasPhysReg(Cand.SU, Cand.AtTop), TryCand, Cand, PhysReg))
Andrew Tricke833e1c2013-04-13 06:07:40 +00003007 return;
3008
Andrew Tricke02d5da2015-05-17 23:40:27 +00003009 // Avoid exceeding the target's limit.
Andrew Trick66c3dfb2013-09-04 21:00:11 +00003010 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.Excess,
3011 Cand.RPDelta.Excess,
Tom Stellard5ce53062015-12-16 18:31:01 +00003012 TryCand, Cand, RegExcess, TRI,
3013 DAG->MF))
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003014 return;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003015
3016 // Avoid increasing the max critical pressure in the scheduled region.
Andrew Trick66c3dfb2013-09-04 21:00:11 +00003017 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CriticalMax,
3018 Cand.RPDelta.CriticalMax,
Tom Stellard5ce53062015-12-16 18:31:01 +00003019 TryCand, Cand, RegCritical, TRI,
3020 DAG->MF))
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003021 return;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003022
Matthias Braun6ad3d052016-06-25 00:23:00 +00003023 // We only compare a subset of features when comparing nodes between
3024 // Top and Bottom boundary. Some properties are simply incomparable, in many
3025 // other instances we should only override the other boundary if something
3026 // is a clear good pick on one boundary. Skip heuristics that are more
3027 // "tie-breaking" in nature.
3028 bool SameBoundary = Zone != nullptr;
3029 if (SameBoundary) {
3030 // For loops that are acyclic path limited, aggressively schedule for
Jonas Paulssonbaeb4022016-11-04 08:31:14 +00003031 // latency. Within an single cycle, whenever CurrMOps > 0, allow normal
3032 // heuristics to take precedence.
Matthias Braun6ad3d052016-06-25 00:23:00 +00003033 if (Rem.IsAcyclicLatencyLimited && !Zone->getCurrMOps() &&
3034 tryLatency(TryCand, Cand, *Zone))
3035 return;
Andrew Trickddffae92013-09-06 17:32:36 +00003036
Matthias Braun6ad3d052016-06-25 00:23:00 +00003037 // Prioritize instructions that read unbuffered resources by stall cycles.
3038 if (tryLess(Zone->getLatencyStallCycles(TryCand.SU),
3039 Zone->getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
3040 return;
3041 }
Andrew Trick880e5732013-12-05 17:55:58 +00003042
Andrew Tricka7714a02012-11-12 19:40:10 +00003043 // Keep clustered nodes together to encourage downstream peephole
3044 // optimizations which may reduce resource requirements.
3045 //
3046 // This is a best effort to set things up for a post-RA pass. Optimizations
3047 // like generating loads of multiple registers should ideally be done within
3048 // the scheduler pass by combining the loads during DAG postprocessing.
Matthias Braun6ad3d052016-06-25 00:23:00 +00003049 const SUnit *CandNextClusterSU =
3050 Cand.AtTop ? DAG->getNextClusterSucc() : DAG->getNextClusterPred();
3051 const SUnit *TryCandNextClusterSU =
3052 TryCand.AtTop ? DAG->getNextClusterSucc() : DAG->getNextClusterPred();
3053 if (tryGreater(TryCand.SU == TryCandNextClusterSU,
3054 Cand.SU == CandNextClusterSU,
Andrew Tricka7714a02012-11-12 19:40:10 +00003055 TryCand, Cand, Cluster))
3056 return;
Andrew Trick85a1d4c2013-04-24 15:54:43 +00003057
Matthias Braun6ad3d052016-06-25 00:23:00 +00003058 if (SameBoundary) {
3059 // Weak edges are for clustering and other constraints.
3060 if (tryLess(getWeakLeft(TryCand.SU, TryCand.AtTop),
3061 getWeakLeft(Cand.SU, Cand.AtTop),
3062 TryCand, Cand, Weak))
3063 return;
Andrew Tricka7714a02012-11-12 19:40:10 +00003064 }
Matthias Braun6ad3d052016-06-25 00:23:00 +00003065
Andrew Trick71f08a32013-06-17 21:45:13 +00003066 // Avoid increasing the max pressure of the entire region.
Andrew Trick66c3dfb2013-09-04 21:00:11 +00003067 if (DAG->isTrackingPressure() && tryPressure(TryCand.RPDelta.CurrentMax,
3068 Cand.RPDelta.CurrentMax,
Tom Stellard5ce53062015-12-16 18:31:01 +00003069 TryCand, Cand, RegMax, TRI,
3070 DAG->MF))
Andrew Trick71f08a32013-06-17 21:45:13 +00003071 return;
3072
Matthias Braun6ad3d052016-06-25 00:23:00 +00003073 if (SameBoundary) {
3074 // Avoid critical resource consumption and balance the schedule.
3075 TryCand.initResourceDelta(DAG, SchedModel);
3076 if (tryLess(TryCand.ResDelta.CritResources, Cand.ResDelta.CritResources,
3077 TryCand, Cand, ResourceReduce))
3078 return;
3079 if (tryGreater(TryCand.ResDelta.DemandedResources,
3080 Cand.ResDelta.DemandedResources,
3081 TryCand, Cand, ResourceDemand))
3082 return;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003083
Matthias Braun6ad3d052016-06-25 00:23:00 +00003084 // Avoid serializing long latency dependence chains.
3085 // For acyclic path limited loops, latency was already checked above.
3086 if (!RegionPolicy.DisableLatencyHeuristic && TryCand.Policy.ReduceLatency &&
3087 !Rem.IsAcyclicLatencyLimited && tryLatency(TryCand, Cand, *Zone))
3088 return;
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003089
Matthias Braun6ad3d052016-06-25 00:23:00 +00003090 // Fall through to original instruction order.
3091 if ((Zone->isTop() && TryCand.SU->NodeNum < Cand.SU->NodeNum)
3092 || (!Zone->isTop() && TryCand.SU->NodeNum > Cand.SU->NodeNum)) {
3093 TryCand.Reason = NodeOrder;
3094 }
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003095 }
3096}
Andrew Trick419eae22012-05-10 21:06:19 +00003097
Andrew Trickc573cd92013-09-06 17:32:44 +00003098/// Pick the best candidate from the queue.
Andrew Trick7ee9de52012-05-10 21:06:16 +00003099///
3100/// TODO: getMaxPressureDelta results can be mostly cached for each SUnit during
3101/// DAG building. To adjust for the current scheduling location we need to
3102/// maintain the number of vreg uses remaining to be top-scheduled.
Andrew Trick665d3ec2013-09-19 23:10:59 +00003103void GenericScheduler::pickNodeFromQueue(SchedBoundary &Zone,
Matthias Braun6ad3d052016-06-25 00:23:00 +00003104 const CandPolicy &ZonePolicy,
Andrew Trickbb1247b2013-12-05 17:55:47 +00003105 const RegPressureTracker &RPTracker,
3106 SchedCandidate &Cand) {
Andrew Trick7ee9de52012-05-10 21:06:16 +00003107 // getMaxPressureDelta temporarily modifies the tracker.
3108 RegPressureTracker &TempTracker = const_cast<RegPressureTracker&>(RPTracker);
3109
Matthias Braund29d31e2016-06-23 21:27:38 +00003110 ReadyQueue &Q = Zone.Available;
Javed Absare3a0cc22017-06-21 09:10:10 +00003111 for (SUnit *SU : Q) {
Andrew Trick7ee9de52012-05-10 21:06:16 +00003112
Matthias Braun6ad3d052016-06-25 00:23:00 +00003113 SchedCandidate TryCand(ZonePolicy);
Javed Absare3a0cc22017-06-21 09:10:10 +00003114 initCandidate(TryCand, SU, Zone.isTop(), RPTracker, TempTracker);
Matthias Braun6ad3d052016-06-25 00:23:00 +00003115 // Pass SchedBoundary only when comparing nodes from the same boundary.
3116 SchedBoundary *ZoneArg = Cand.AtTop == TryCand.AtTop ? &Zone : nullptr;
3117 tryCandidate(Cand, TryCand, ZoneArg);
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003118 if (TryCand.Reason != NoCand) {
3119 // Initialize resource delta if needed in case future heuristics query it.
3120 if (TryCand.ResDelta == SchedResourceDelta())
3121 TryCand.initResourceDelta(DAG, SchedModel);
3122 Cand.setBest(TryCand);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003123 LLVM_DEBUG(traceCandidate(Cand));
Andrew Trick22025772012-05-17 18:35:10 +00003124 }
Andrew Trick7ee9de52012-05-10 21:06:16 +00003125 }
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003126}
3127
Andrew Trick22025772012-05-17 18:35:10 +00003128/// Pick the best candidate node from either the top or bottom queue.
Andrew Trick665d3ec2013-09-19 23:10:59 +00003129SUnit *GenericScheduler::pickNodeBidirectional(bool &IsTopNode) {
Andrew Trick22025772012-05-17 18:35:10 +00003130 // Schedule as far as possible in the direction of no choice. This is most
3131 // efficient, but also provides the best heuristics for CriticalPSets.
Andrew Trick61f1a272012-05-24 22:11:09 +00003132 if (SUnit *SU = Bot.pickOnlyChoice()) {
Andrew Trick22025772012-05-17 18:35:10 +00003133 IsTopNode = false;
Matthias Braun49cb6e92016-05-27 22:14:26 +00003134 tracePick(Only1, false);
Andrew Trick61f1a272012-05-24 22:11:09 +00003135 return SU;
Andrew Trick22025772012-05-17 18:35:10 +00003136 }
Andrew Trick61f1a272012-05-24 22:11:09 +00003137 if (SUnit *SU = Top.pickOnlyChoice()) {
Andrew Trick22025772012-05-17 18:35:10 +00003138 IsTopNode = true;
Matthias Braun49cb6e92016-05-27 22:14:26 +00003139 tracePick(Only1, true);
Andrew Trick61f1a272012-05-24 22:11:09 +00003140 return SU;
Andrew Trick22025772012-05-17 18:35:10 +00003141 }
Andrew Trickfc127d12013-12-07 05:59:44 +00003142 // Set the bottom-up policy based on the state of the current bottom zone and
3143 // the instructions outside the zone, including the top zone.
Matthias Braun6ad3d052016-06-25 00:23:00 +00003144 CandPolicy BotPolicy;
3145 setPolicy(BotPolicy, /*IsPostRA=*/false, Bot, &Top);
Andrew Trickfc127d12013-12-07 05:59:44 +00003146 // Set the top-down policy based on the state of the current top zone and
3147 // the instructions outside the zone, including the bottom zone.
Matthias Braun6ad3d052016-06-25 00:23:00 +00003148 CandPolicy TopPolicy;
3149 setPolicy(TopPolicy, /*IsPostRA=*/false, Top, &Bot);
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003150
Matthias Brauncc676c42016-06-25 02:03:36 +00003151 // See if BotCand is still valid (because we previously scheduled from Top).
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003152 LLVM_DEBUG(dbgs() << "Picking from Bot:\n");
Matthias Brauncc676c42016-06-25 02:03:36 +00003153 if (!BotCand.isValid() || BotCand.SU->isScheduled ||
3154 BotCand.Policy != BotPolicy) {
3155 BotCand.reset(CandPolicy());
3156 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), BotCand);
3157 assert(BotCand.Reason != NoCand && "failed to find the first candidate");
3158 } else {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003159 LLVM_DEBUG(traceCandidate(BotCand));
Matthias Brauncc676c42016-06-25 02:03:36 +00003160#ifndef NDEBUG
3161 if (VerifyScheduling) {
3162 SchedCandidate TCand;
3163 TCand.reset(CandPolicy());
3164 pickNodeFromQueue(Bot, BotPolicy, DAG->getBotRPTracker(), TCand);
3165 assert(TCand.SU == BotCand.SU &&
3166 "Last pick result should correspond to re-picking right now");
3167 }
3168#endif
3169 }
Andrew Trick22025772012-05-17 18:35:10 +00003170
Andrew Trick22025772012-05-17 18:35:10 +00003171 // Check if the top Q has a better candidate.
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003172 LLVM_DEBUG(dbgs() << "Picking from Top:\n");
Matthias Brauncc676c42016-06-25 02:03:36 +00003173 if (!TopCand.isValid() || TopCand.SU->isScheduled ||
3174 TopCand.Policy != TopPolicy) {
3175 TopCand.reset(CandPolicy());
3176 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TopCand);
3177 assert(TopCand.Reason != NoCand && "failed to find the first candidate");
3178 } else {
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003179 LLVM_DEBUG(traceCandidate(TopCand));
Matthias Brauncc676c42016-06-25 02:03:36 +00003180#ifndef NDEBUG
3181 if (VerifyScheduling) {
3182 SchedCandidate TCand;
3183 TCand.reset(CandPolicy());
3184 pickNodeFromQueue(Top, TopPolicy, DAG->getTopRPTracker(), TCand);
3185 assert(TCand.SU == TopCand.SU &&
3186 "Last pick result should correspond to re-picking right now");
3187 }
3188#endif
3189 }
3190
3191 // Pick best from BotCand and TopCand.
3192 assert(BotCand.isValid());
3193 assert(TopCand.isValid());
3194 SchedCandidate Cand = BotCand;
3195 TopCand.Reason = NoCand;
3196 tryCandidate(Cand, TopCand, nullptr);
3197 if (TopCand.Reason != NoCand) {
3198 Cand.setBest(TopCand);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003199 LLVM_DEBUG(traceCandidate(Cand));
Matthias Brauncc676c42016-06-25 02:03:36 +00003200 }
Andrew Trick22025772012-05-17 18:35:10 +00003201
Matthias Braun6ad3d052016-06-25 00:23:00 +00003202 IsTopNode = Cand.AtTop;
3203 tracePick(Cand);
3204 return Cand.SU;
Andrew Trick22025772012-05-17 18:35:10 +00003205}
3206
3207/// Pick the best node to balance the schedule. Implements MachineSchedStrategy.
Andrew Trick665d3ec2013-09-19 23:10:59 +00003208SUnit *GenericScheduler::pickNode(bool &IsTopNode) {
Andrew Trick7ee9de52012-05-10 21:06:16 +00003209 if (DAG->top() == DAG->bottom()) {
Andrew Trick61f1a272012-05-24 22:11:09 +00003210 assert(Top.Available.empty() && Top.Pending.empty() &&
3211 Bot.Available.empty() && Bot.Pending.empty() && "ReadyQ garbage");
Craig Topperc0196b12014-04-14 00:51:57 +00003212 return nullptr;
Andrew Trick7ee9de52012-05-10 21:06:16 +00003213 }
Andrew Trick7ee9de52012-05-10 21:06:16 +00003214 SUnit *SU;
Andrew Trick984d98b2012-10-08 18:53:53 +00003215 do {
Andrew Trick75e411c2013-09-06 17:32:34 +00003216 if (RegionPolicy.OnlyTopDown) {
Andrew Trick984d98b2012-10-08 18:53:53 +00003217 SU = Top.pickOnlyChoice();
3218 if (!SU) {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003219 CandPolicy NoPolicy;
Matthias Brauncc676c42016-06-25 02:03:36 +00003220 TopCand.reset(NoPolicy);
Matthias Braun6ad3d052016-06-25 00:23:00 +00003221 pickNodeFromQueue(Top, NoPolicy, DAG->getTopRPTracker(), TopCand);
Andrew Trick1ab16d92013-09-04 21:00:13 +00003222 assert(TopCand.Reason != NoCand && "failed to find a candidate");
Matthias Braun6ad3d052016-06-25 00:23:00 +00003223 tracePick(TopCand);
Andrew Trick984d98b2012-10-08 18:53:53 +00003224 SU = TopCand.SU;
3225 }
3226 IsTopNode = true;
Matthias Braunb550b762016-04-21 01:54:13 +00003227 } else if (RegionPolicy.OnlyBottomUp) {
Andrew Trick984d98b2012-10-08 18:53:53 +00003228 SU = Bot.pickOnlyChoice();
3229 if (!SU) {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003230 CandPolicy NoPolicy;
Matthias Brauncc676c42016-06-25 02:03:36 +00003231 BotCand.reset(NoPolicy);
Matthias Braun6ad3d052016-06-25 00:23:00 +00003232 pickNodeFromQueue(Bot, NoPolicy, DAG->getBotRPTracker(), BotCand);
Andrew Trick1ab16d92013-09-04 21:00:13 +00003233 assert(BotCand.Reason != NoCand && "failed to find a candidate");
Matthias Braun6ad3d052016-06-25 00:23:00 +00003234 tracePick(BotCand);
Andrew Trick984d98b2012-10-08 18:53:53 +00003235 SU = BotCand.SU;
3236 }
3237 IsTopNode = false;
Matthias Braunb550b762016-04-21 01:54:13 +00003238 } else {
Andrew Trick3ca33ac2012-11-07 07:05:09 +00003239 SU = pickNodeBidirectional(IsTopNode);
Andrew Trick984d98b2012-10-08 18:53:53 +00003240 }
3241 } while (SU->isScheduled);
3242
Andrew Trick61f1a272012-05-24 22:11:09 +00003243 if (SU->isTopReady())
3244 Top.removeReady(SU);
3245 if (SU->isBottomReady())
3246 Bot.removeReady(SU);
Andrew Trick4e7f6a72012-05-25 02:02:39 +00003247
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003248 LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
3249 << *SU->getInstr());
Andrew Trick7ee9de52012-05-10 21:06:16 +00003250 return SU;
3251}
3252
Nirav Dave1241dcb2018-11-14 21:11:53 +00003253void GenericScheduler::reschedulePhysReg(SUnit *SU, bool isTop) {
Andrew Tricke833e1c2013-04-13 06:07:40 +00003254 MachineBasicBlock::iterator InsertPos = SU->getInstr();
3255 if (!isTop)
3256 ++InsertPos;
3257 SmallVectorImpl<SDep> &Deps = isTop ? SU->Preds : SU->Succs;
3258
3259 // Find already scheduled copies with a single physreg dependence and move
3260 // them just above the scheduled instruction.
Javed Absare3a0cc22017-06-21 09:10:10 +00003261 for (SDep &Dep : Deps) {
Daniel Sanders2bea69b2019-08-01 23:27:28 +00003262 if (Dep.getKind() != SDep::Data ||
3263 !Register::isPhysicalRegister(Dep.getReg()))
Andrew Tricke833e1c2013-04-13 06:07:40 +00003264 continue;
Javed Absare3a0cc22017-06-21 09:10:10 +00003265 SUnit *DepSU = Dep.getSUnit();
Andrew Tricke833e1c2013-04-13 06:07:40 +00003266 if (isTop ? DepSU->Succs.size() > 1 : DepSU->Preds.size() > 1)
3267 continue;
3268 MachineInstr *Copy = DepSU->getInstr();
Nirav Dave1241dcb2018-11-14 21:11:53 +00003269 if (!Copy->isCopy() && !Copy->isMoveImmediate())
Andrew Tricke833e1c2013-04-13 06:07:40 +00003270 continue;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003271 LLVM_DEBUG(dbgs() << " Rescheduling physreg copy ";
Matthias Braun726e12c2018-09-19 00:23:35 +00003272 DAG->dumpNode(*Dep.getSUnit()));
Andrew Tricke833e1c2013-04-13 06:07:40 +00003273 DAG->moveInstruction(Copy, InsertPos);
3274 }
3275}
3276
Andrew Trick61f1a272012-05-24 22:11:09 +00003277/// Update the scheduler's state after scheduling a node. This is the same node
Andrew Trickd14d7c22013-12-28 21:56:57 +00003278/// that was just returned by pickNode(). However, ScheduleDAGMILive needs to
3279/// update it's state based on the current cycle before MachineSchedStrategy
3280/// does.
Andrew Tricke833e1c2013-04-13 06:07:40 +00003281///
3282/// FIXME: Eventually, we may bundle physreg copies rather than rescheduling
Nirav Dave1241dcb2018-11-14 21:11:53 +00003283/// them here. See comments in biasPhysReg.
Andrew Trick665d3ec2013-09-19 23:10:59 +00003284void GenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
Andrew Trick45446062012-06-05 21:11:27 +00003285 if (IsTopNode) {
Andrew Trickfc127d12013-12-07 05:59:44 +00003286 SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
Andrew Trickce27bb92012-06-29 03:23:22 +00003287 Top.bumpNode(SU);
Andrew Tricke833e1c2013-04-13 06:07:40 +00003288 if (SU->hasPhysRegUses)
Nirav Dave1241dcb2018-11-14 21:11:53 +00003289 reschedulePhysReg(SU, true);
Matthias Braunb550b762016-04-21 01:54:13 +00003290 } else {
Andrew Trickfc127d12013-12-07 05:59:44 +00003291 SU->BotReadyCycle = std::max(SU->BotReadyCycle, Bot.getCurrCycle());
Andrew Trickce27bb92012-06-29 03:23:22 +00003292 Bot.bumpNode(SU);
Andrew Tricke833e1c2013-04-13 06:07:40 +00003293 if (SU->hasPhysRegDefs)
Nirav Dave1241dcb2018-11-14 21:11:53 +00003294 reschedulePhysReg(SU, false);
Andrew Trick61f1a272012-05-24 22:11:09 +00003295 }
3296}
3297
Andrew Trick8823dec2012-03-14 04:00:41 +00003298/// Create the standard converging machine scheduler. This will be used as the
3299/// default scheduler if the target does not set a default.
Matthias Braun115efcd2016-11-28 20:11:54 +00003300ScheduleDAGMILive *llvm::createGenericSchedLive(MachineSchedContext *C) {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003301 ScheduleDAGMILive *DAG =
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00003302 new ScheduleDAGMILive(C, std::make_unique<GenericScheduler>(C));
Andrew Tricka7714a02012-11-12 19:40:10 +00003303 // Register DAG post-processors.
Andrew Trick85a1d4c2013-04-24 15:54:43 +00003304 //
3305 // FIXME: extend the mutation API to allow earlier mutations to instantiate
3306 // data and pass it to later mutations. Have a single mutation that gathers
3307 // the interesting nodes in one pass.
Tom Stellard68726a52016-08-19 19:59:18 +00003308 DAG->addMutation(createCopyConstrainDAGMutation(DAG->TII, DAG->TRI));
Andrew Tricka7714a02012-11-12 19:40:10 +00003309 return DAG;
Andrew Tricke1c034f2012-01-17 06:55:03 +00003310}
Andrew Trickd14d7c22013-12-28 21:56:57 +00003311
Matthias Braun115efcd2016-11-28 20:11:54 +00003312static ScheduleDAGInstrs *createConveringSched(MachineSchedContext *C) {
3313 return createGenericSchedLive(C);
3314}
3315
Andrew Tricke1c034f2012-01-17 06:55:03 +00003316static MachineSchedRegistry
Andrew Trick665d3ec2013-09-19 23:10:59 +00003317GenericSchedRegistry("converge", "Standard converging scheduler.",
Matthias Braun115efcd2016-11-28 20:11:54 +00003318 createConveringSched);
Andrew Trickd14d7c22013-12-28 21:56:57 +00003319
3320//===----------------------------------------------------------------------===//
3321// PostGenericScheduler - Generic PostRA implementation of MachineSchedStrategy.
3322//===----------------------------------------------------------------------===//
3323
Andrew Trick3ccf71d2014-06-04 07:06:18 +00003324void PostGenericScheduler::initialize(ScheduleDAGMI *Dag) {
3325 DAG = Dag;
3326 SchedModel = DAG->getSchedModel();
3327 TRI = DAG->TRI;
Andrew Trickd14d7c22013-12-28 21:56:57 +00003328
Andrew Trick3ccf71d2014-06-04 07:06:18 +00003329 Rem.init(DAG, SchedModel);
3330 Top.init(DAG, SchedModel, &Rem);
3331 BotRoots.clear();
Andrew Trickd14d7c22013-12-28 21:56:57 +00003332
Andrew Trick3ccf71d2014-06-04 07:06:18 +00003333 // Initialize the HazardRecognizers. If itineraries don't exist, are empty,
3334 // or are disabled, then these HazardRecs will be disabled.
3335 const InstrItineraryData *Itin = SchedModel->getInstrItineraries();
Andrew Trick3ccf71d2014-06-04 07:06:18 +00003336 if (!Top.HazardRec) {
3337 Top.HazardRec =
Eric Christopher99556d72014-10-14 06:56:25 +00003338 DAG->MF.getSubtarget().getInstrInfo()->CreateTargetMIHazardRecognizer(
Eric Christopherd9134482014-08-04 21:25:23 +00003339 Itin, DAG);
Andrew Trickd14d7c22013-12-28 21:56:57 +00003340 }
Andrew Trick3ccf71d2014-06-04 07:06:18 +00003341}
Andrew Trickd14d7c22013-12-28 21:56:57 +00003342
Andrew Trickd14d7c22013-12-28 21:56:57 +00003343void PostGenericScheduler::registerRoots() {
3344 Rem.CriticalPath = DAG->ExitSU.getDepth();
3345
3346 // Some roots may not feed into ExitSU. Check all of them in case.
Javed Absare3a0cc22017-06-21 09:10:10 +00003347 for (const SUnit *SU : BotRoots) {
3348 if (SU->getDepth() > Rem.CriticalPath)
3349 Rem.CriticalPath = SU->getDepth();
Andrew Trickd14d7c22013-12-28 21:56:57 +00003350 }
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003351 LLVM_DEBUG(dbgs() << "Critical Path: (PGS-RR) " << Rem.CriticalPath << '\n');
Gerolf Hoflehnerb5220dc2014-08-07 21:49:44 +00003352 if (DumpCriticalPathLength) {
3353 errs() << "Critical Path(PGS-RR ): " << Rem.CriticalPath << " \n";
3354 }
Andrew Trickd14d7c22013-12-28 21:56:57 +00003355}
3356
Hiroshi Inouec73b6d62018-06-20 05:29:26 +00003357/// Apply a set of heuristics to a new candidate for PostRA scheduling.
Andrew Trickd14d7c22013-12-28 21:56:57 +00003358///
3359/// \param Cand provides the policy and current best candidate.
3360/// \param TryCand refers to the next SUnit candidate, otherwise uninitialized.
3361void PostGenericScheduler::tryCandidate(SchedCandidate &Cand,
3362 SchedCandidate &TryCand) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00003363 // Initialize the candidate if needed.
3364 if (!Cand.isValid()) {
3365 TryCand.Reason = NodeOrder;
3366 return;
3367 }
3368
3369 // Prioritize instructions that read unbuffered resources by stall cycles.
3370 if (tryLess(Top.getLatencyStallCycles(TryCand.SU),
3371 Top.getLatencyStallCycles(Cand.SU), TryCand, Cand, Stall))
3372 return;
3373
Florian Hahnabb42182017-05-23 09:33:34 +00003374 // Keep clustered nodes together.
3375 if (tryGreater(TryCand.SU == DAG->getNextClusterSucc(),
3376 Cand.SU == DAG->getNextClusterSucc(),
3377 TryCand, Cand, Cluster))
3378 return;
3379
Andrew Trickd14d7c22013-12-28 21:56:57 +00003380 // Avoid critical resource consumption and balance the schedule.
3381 if (tryLess(TryCand.ResDelta.CritResources, Cand.ResDelta.CritResources,
3382 TryCand, Cand, ResourceReduce))
3383 return;
3384 if (tryGreater(TryCand.ResDelta.DemandedResources,
3385 Cand.ResDelta.DemandedResources,
3386 TryCand, Cand, ResourceDemand))
3387 return;
3388
3389 // Avoid serializing long latency dependence chains.
3390 if (Cand.Policy.ReduceLatency && tryLatency(TryCand, Cand, Top)) {
3391 return;
3392 }
3393
3394 // Fall through to original instruction order.
3395 if (TryCand.SU->NodeNum < Cand.SU->NodeNum)
3396 TryCand.Reason = NodeOrder;
3397}
3398
3399void PostGenericScheduler::pickNodeFromQueue(SchedCandidate &Cand) {
3400 ReadyQueue &Q = Top.Available;
Javed Absare3a0cc22017-06-21 09:10:10 +00003401 for (SUnit *SU : Q) {
Andrew Trickd14d7c22013-12-28 21:56:57 +00003402 SchedCandidate TryCand(Cand.Policy);
Javed Absare3a0cc22017-06-21 09:10:10 +00003403 TryCand.SU = SU;
Matthias Braun6ad3d052016-06-25 00:23:00 +00003404 TryCand.AtTop = true;
Andrew Trickd14d7c22013-12-28 21:56:57 +00003405 TryCand.initResourceDelta(DAG, SchedModel);
3406 tryCandidate(Cand, TryCand);
3407 if (TryCand.Reason != NoCand) {
3408 Cand.setBest(TryCand);
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003409 LLVM_DEBUG(traceCandidate(Cand));
Andrew Trickd14d7c22013-12-28 21:56:57 +00003410 }
3411 }
3412}
3413
3414/// Pick the next node to schedule.
3415SUnit *PostGenericScheduler::pickNode(bool &IsTopNode) {
3416 if (DAG->top() == DAG->bottom()) {
3417 assert(Top.Available.empty() && Top.Pending.empty() && "ReadyQ garbage");
Craig Topperc0196b12014-04-14 00:51:57 +00003418 return nullptr;
Andrew Trickd14d7c22013-12-28 21:56:57 +00003419 }
3420 SUnit *SU;
3421 do {
3422 SU = Top.pickOnlyChoice();
Matthias Braun49cb6e92016-05-27 22:14:26 +00003423 if (SU) {
3424 tracePick(Only1, true);
3425 } else {
Andrew Trickd14d7c22013-12-28 21:56:57 +00003426 CandPolicy NoPolicy;
3427 SchedCandidate TopCand(NoPolicy);
3428 // Set the top-down policy based on the state of the current top zone and
3429 // the instructions outside the zone, including the bottom zone.
Craig Topperc0196b12014-04-14 00:51:57 +00003430 setPolicy(TopCand.Policy, /*IsPostRA=*/true, Top, nullptr);
Andrew Trickd14d7c22013-12-28 21:56:57 +00003431 pickNodeFromQueue(TopCand);
3432 assert(TopCand.Reason != NoCand && "failed to find a candidate");
Matthias Braun6ad3d052016-06-25 00:23:00 +00003433 tracePick(TopCand);
Andrew Trickd14d7c22013-12-28 21:56:57 +00003434 SU = TopCand.SU;
3435 }
3436 } while (SU->isScheduled);
3437
3438 IsTopNode = true;
3439 Top.removeReady(SU);
3440
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003441 LLVM_DEBUG(dbgs() << "Scheduling SU(" << SU->NodeNum << ") "
3442 << *SU->getInstr());
Andrew Trickd14d7c22013-12-28 21:56:57 +00003443 return SU;
3444}
3445
3446/// Called after ScheduleDAGMI has scheduled an instruction and updated
3447/// scheduled/remaining flags in the DAG nodes.
3448void PostGenericScheduler::schedNode(SUnit *SU, bool IsTopNode) {
3449 SU->TopReadyCycle = std::max(SU->TopReadyCycle, Top.getCurrCycle());
3450 Top.bumpNode(SU);
3451}
3452
Matthias Braun115efcd2016-11-28 20:11:54 +00003453ScheduleDAGMI *llvm::createGenericSchedPostRA(MachineSchedContext *C) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00003454 return new ScheduleDAGMI(C, std::make_unique<PostGenericScheduler>(C),
Jonas Paulsson28f29482016-11-09 09:59:27 +00003455 /*RemoveKillFlags=*/true);
Andrew Trickd14d7c22013-12-28 21:56:57 +00003456}
Andrew Tricke1c034f2012-01-17 06:55:03 +00003457
3458//===----------------------------------------------------------------------===//
Andrew Trick90f711d2012-10-15 18:02:27 +00003459// ILP Scheduler. Currently for experimental analysis of heuristics.
3460//===----------------------------------------------------------------------===//
3461
3462namespace {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003463
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00003464/// Order nodes by the ILP metric.
Andrew Trick90f711d2012-10-15 18:02:27 +00003465struct ILPOrder {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003466 const SchedDFSResult *DFSResult = nullptr;
3467 const BitVector *ScheduledTrees = nullptr;
Andrew Trick90f711d2012-10-15 18:02:27 +00003468 bool MaximizeILP;
3469
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003470 ILPOrder(bool MaxILP) : MaximizeILP(MaxILP) {}
Andrew Trick90f711d2012-10-15 18:02:27 +00003471
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00003472 /// Apply a less-than relation on node priority.
Andrew Trick48d392e2012-11-28 05:13:28 +00003473 ///
3474 /// (Return true if A comes after B in the Q.)
Andrew Trick90f711d2012-10-15 18:02:27 +00003475 bool operator()(const SUnit *A, const SUnit *B) const {
Andrew Trick48d392e2012-11-28 05:13:28 +00003476 unsigned SchedTreeA = DFSResult->getSubtreeID(A);
3477 unsigned SchedTreeB = DFSResult->getSubtreeID(B);
3478 if (SchedTreeA != SchedTreeB) {
3479 // Unscheduled trees have lower priority.
3480 if (ScheduledTrees->test(SchedTreeA) != ScheduledTrees->test(SchedTreeB))
3481 return ScheduledTrees->test(SchedTreeB);
3482
3483 // Trees with shallower connections have have lower priority.
3484 if (DFSResult->getSubtreeLevel(SchedTreeA)
3485 != DFSResult->getSubtreeLevel(SchedTreeB)) {
3486 return DFSResult->getSubtreeLevel(SchedTreeA)
3487 < DFSResult->getSubtreeLevel(SchedTreeB);
3488 }
3489 }
Andrew Trick90f711d2012-10-15 18:02:27 +00003490 if (MaximizeILP)
Andrew Trick48d392e2012-11-28 05:13:28 +00003491 return DFSResult->getILP(A) < DFSResult->getILP(B);
Andrew Trick90f711d2012-10-15 18:02:27 +00003492 else
Andrew Trick48d392e2012-11-28 05:13:28 +00003493 return DFSResult->getILP(A) > DFSResult->getILP(B);
Andrew Trick90f711d2012-10-15 18:02:27 +00003494 }
3495};
3496
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00003497/// Schedule based on the ILP metric.
Andrew Trick90f711d2012-10-15 18:02:27 +00003498class ILPScheduler : public MachineSchedStrategy {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003499 ScheduleDAGMILive *DAG = nullptr;
Andrew Trick90f711d2012-10-15 18:02:27 +00003500 ILPOrder Cmp;
3501
3502 std::vector<SUnit*> ReadyQ;
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003503
Andrew Trick90f711d2012-10-15 18:02:27 +00003504public:
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003505 ILPScheduler(bool MaximizeILP) : Cmp(MaximizeILP) {}
Andrew Trick90f711d2012-10-15 18:02:27 +00003506
Craig Topper4584cd52014-03-07 09:26:03 +00003507 void initialize(ScheduleDAGMI *dag) override {
Andrew Trickd7f890e2013-12-28 21:56:47 +00003508 assert(dag->hasVRegLiveness() && "ILPScheduler needs vreg liveness");
3509 DAG = static_cast<ScheduleDAGMILive*>(dag);
Andrew Tricke2c3f5c2013-01-25 06:33:57 +00003510 DAG->computeDFSResult();
Andrew Trick44f750a2013-01-25 04:01:04 +00003511 Cmp.DFSResult = DAG->getDFSResult();
3512 Cmp.ScheduledTrees = &DAG->getScheduledTrees();
Andrew Trick90f711d2012-10-15 18:02:27 +00003513 ReadyQ.clear();
Andrew Trick90f711d2012-10-15 18:02:27 +00003514 }
3515
Craig Topper4584cd52014-03-07 09:26:03 +00003516 void registerRoots() override {
Benjamin Krameraa598b32012-11-29 14:36:26 +00003517 // Restore the heap in ReadyQ with the updated DFS results.
3518 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
Andrew Trick90f711d2012-10-15 18:02:27 +00003519 }
3520
3521 /// Implement MachineSchedStrategy interface.
3522 /// -----------------------------------------
3523
Andrew Trick48d392e2012-11-28 05:13:28 +00003524 /// Callback to select the highest priority node from the ready Q.
Craig Topper4584cd52014-03-07 09:26:03 +00003525 SUnit *pickNode(bool &IsTopNode) override {
Craig Topperc0196b12014-04-14 00:51:57 +00003526 if (ReadyQ.empty()) return nullptr;
Matt Arsenault4ab769f2013-03-21 00:57:21 +00003527 std::pop_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
Andrew Trick90f711d2012-10-15 18:02:27 +00003528 SUnit *SU = ReadyQ.back();
3529 ReadyQ.pop_back();
3530 IsTopNode = false;
Nicola Zaghend34e60c2018-05-14 12:53:11 +00003531 LLVM_DEBUG(dbgs() << "Pick node "
3532 << "SU(" << SU->NodeNum << ") "
3533 << " ILP: " << DAG->getDFSResult()->getILP(SU)
3534 << " Tree: " << DAG->getDFSResult()->getSubtreeID(SU)
3535 << " @"
3536 << DAG->getDFSResult()->getSubtreeLevel(
3537 DAG->getDFSResult()->getSubtreeID(SU))
3538 << '\n'
3539 << "Scheduling " << *SU->getInstr());
Andrew Trick90f711d2012-10-15 18:02:27 +00003540 return SU;
3541 }
3542
Adrian Prantl5f8f34e42018-05-01 15:54:18 +00003543 /// Scheduler callback to notify that a new subtree is scheduled.
Craig Topper4584cd52014-03-07 09:26:03 +00003544 void scheduleTree(unsigned SubtreeID) override {
Andrew Trick44f750a2013-01-25 04:01:04 +00003545 std::make_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3546 }
3547
Andrew Trick48d392e2012-11-28 05:13:28 +00003548 /// Callback after a node is scheduled. Mark a newly scheduled tree, notify
3549 /// DFSResults, and resort the priority Q.
Craig Topper4584cd52014-03-07 09:26:03 +00003550 void schedNode(SUnit *SU, bool IsTopNode) override {
Andrew Trick48d392e2012-11-28 05:13:28 +00003551 assert(!IsTopNode && "SchedDFSResult needs bottom-up");
Andrew Trick48d392e2012-11-28 05:13:28 +00003552 }
Andrew Trick90f711d2012-10-15 18:02:27 +00003553
Craig Topper4584cd52014-03-07 09:26:03 +00003554 void releaseTopNode(SUnit *) override { /*only called for top roots*/ }
Andrew Trick90f711d2012-10-15 18:02:27 +00003555
Craig Topper4584cd52014-03-07 09:26:03 +00003556 void releaseBottomNode(SUnit *SU) override {
Andrew Trick90f711d2012-10-15 18:02:27 +00003557 ReadyQ.push_back(SU);
3558 std::push_heap(ReadyQ.begin(), ReadyQ.end(), Cmp);
3559 }
3560};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003561
3562} // end anonymous namespace
Andrew Trick90f711d2012-10-15 18:02:27 +00003563
3564static ScheduleDAGInstrs *createILPMaxScheduler(MachineSchedContext *C) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00003565 return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(true));
Andrew Trick90f711d2012-10-15 18:02:27 +00003566}
3567static ScheduleDAGInstrs *createILPMinScheduler(MachineSchedContext *C) {
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00003568 return new ScheduleDAGMILive(C, std::make_unique<ILPScheduler>(false));
Andrew Trick90f711d2012-10-15 18:02:27 +00003569}
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003570
Andrew Trick90f711d2012-10-15 18:02:27 +00003571static MachineSchedRegistry ILPMaxRegistry(
3572 "ilpmax", "Schedule bottom-up for max ILP", createILPMaxScheduler);
3573static MachineSchedRegistry ILPMinRegistry(
3574 "ilpmin", "Schedule bottom-up for min ILP", createILPMinScheduler);
3575
3576//===----------------------------------------------------------------------===//
Andrew Trick63440872012-01-14 02:17:06 +00003577// Machine Instruction Shuffler for Correctness Testing
3578//===----------------------------------------------------------------------===//
3579
Andrew Tricke77e84e2012-01-13 06:30:30 +00003580#ifndef NDEBUG
3581namespace {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003582
Andrew Trick8823dec2012-03-14 04:00:41 +00003583/// Apply a less-than relation on the node order, which corresponds to the
3584/// instruction order prior to scheduling. IsReverse implements greater-than.
3585template<bool IsReverse>
3586struct SUnitOrder {
Andrew Trick7ccdc5c2012-01-17 06:55:07 +00003587 bool operator()(SUnit *A, SUnit *B) const {
Andrew Trick8823dec2012-03-14 04:00:41 +00003588 if (IsReverse)
3589 return A->NodeNum > B->NodeNum;
3590 else
3591 return A->NodeNum < B->NodeNum;
Andrew Trick7ccdc5c2012-01-17 06:55:07 +00003592 }
3593};
3594
Andrew Tricke77e84e2012-01-13 06:30:30 +00003595/// Reorder instructions as much as possible.
Andrew Trick8823dec2012-03-14 04:00:41 +00003596class InstructionShuffler : public MachineSchedStrategy {
3597 bool IsAlternating;
3598 bool IsTopDown;
3599
3600 // Using a less-than relation (SUnitOrder<false>) for the TopQ priority
3601 // gives nodes with a higher number higher priority causing the latest
3602 // instructions to be scheduled first.
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003603 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<false>>
Andrew Trick8823dec2012-03-14 04:00:41 +00003604 TopQ;
Eugene Zelenko32a40562017-09-11 23:00:48 +00003605
Andrew Trick8823dec2012-03-14 04:00:41 +00003606 // When scheduling bottom-up, use greater-than as the queue priority.
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003607 PriorityQueue<SUnit*, std::vector<SUnit*>, SUnitOrder<true>>
Andrew Trick8823dec2012-03-14 04:00:41 +00003608 BottomQ;
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003609
Andrew Tricke77e84e2012-01-13 06:30:30 +00003610public:
Andrew Trick8823dec2012-03-14 04:00:41 +00003611 InstructionShuffler(bool alternate, bool topdown)
3612 : IsAlternating(alternate), IsTopDown(topdown) {}
Andrew Tricke77e84e2012-01-13 06:30:30 +00003613
Craig Topper9d74a5a2014-04-29 07:58:41 +00003614 void initialize(ScheduleDAGMI*) override {
Andrew Trick8823dec2012-03-14 04:00:41 +00003615 TopQ.clear();
3616 BottomQ.clear();
3617 }
Andrew Trick7ccdc5c2012-01-17 06:55:07 +00003618
Andrew Trick8823dec2012-03-14 04:00:41 +00003619 /// Implement MachineSchedStrategy interface.
3620 /// -----------------------------------------
3621
Craig Topper9d74a5a2014-04-29 07:58:41 +00003622 SUnit *pickNode(bool &IsTopNode) override {
Andrew Trick8823dec2012-03-14 04:00:41 +00003623 SUnit *SU;
3624 if (IsTopDown) {
3625 do {
Craig Topperc0196b12014-04-14 00:51:57 +00003626 if (TopQ.empty()) return nullptr;
Andrew Trick8823dec2012-03-14 04:00:41 +00003627 SU = TopQ.top();
3628 TopQ.pop();
3629 } while (SU->isScheduled);
3630 IsTopNode = true;
Matthias Braunb550b762016-04-21 01:54:13 +00003631 } else {
Andrew Trick8823dec2012-03-14 04:00:41 +00003632 do {
Craig Topperc0196b12014-04-14 00:51:57 +00003633 if (BottomQ.empty()) return nullptr;
Andrew Trick8823dec2012-03-14 04:00:41 +00003634 SU = BottomQ.top();
3635 BottomQ.pop();
3636 } while (SU->isScheduled);
3637 IsTopNode = false;
3638 }
3639 if (IsAlternating)
3640 IsTopDown = !IsTopDown;
Andrew Trick7ccdc5c2012-01-17 06:55:07 +00003641 return SU;
3642 }
3643
Craig Topper9d74a5a2014-04-29 07:58:41 +00003644 void schedNode(SUnit *SU, bool IsTopNode) override {}
Andrew Trick61f1a272012-05-24 22:11:09 +00003645
Craig Topper9d74a5a2014-04-29 07:58:41 +00003646 void releaseTopNode(SUnit *SU) override {
Andrew Trick8823dec2012-03-14 04:00:41 +00003647 TopQ.push(SU);
3648 }
Craig Topper9d74a5a2014-04-29 07:58:41 +00003649 void releaseBottomNode(SUnit *SU) override {
Andrew Trick8823dec2012-03-14 04:00:41 +00003650 BottomQ.push(SU);
Andrew Tricke77e84e2012-01-13 06:30:30 +00003651 }
3652};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003653
3654} // end anonymous namespace
Andrew Tricke77e84e2012-01-13 06:30:30 +00003655
Andrew Trick02a80da2012-03-08 01:41:12 +00003656static ScheduleDAGInstrs *createInstructionShuffler(MachineSchedContext *C) {
Andrew Trick8823dec2012-03-14 04:00:41 +00003657 bool Alternate = !ForceTopDown && !ForceBottomUp;
3658 bool TopDown = !ForceBottomUp;
Benjamin Kramer05e7a842012-03-14 11:26:37 +00003659 assert((TopDown || !ForceTopDown) &&
Andrew Trick8823dec2012-03-14 04:00:41 +00003660 "-misched-topdown incompatible with -misched-bottomup");
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003661 return new ScheduleDAGMILive(
Jonas Devlieghere0eaee542019-08-15 15:54:37 +00003662 C, std::make_unique<InstructionShuffler>(Alternate, TopDown));
Andrew Tricke77e84e2012-01-13 06:30:30 +00003663}
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003664
Andrew Trick8823dec2012-03-14 04:00:41 +00003665static MachineSchedRegistry ShufflerRegistry(
3666 "shuffle", "Shuffle machine instructions alternating directions",
3667 createInstructionShuffler);
Andrew Tricke77e84e2012-01-13 06:30:30 +00003668#endif // !NDEBUG
Andrew Trickea9fd952013-01-25 07:45:29 +00003669
3670//===----------------------------------------------------------------------===//
Andrew Trickd7f890e2013-12-28 21:56:47 +00003671// GraphWriter support for ScheduleDAGMILive.
Andrew Trickea9fd952013-01-25 07:45:29 +00003672//===----------------------------------------------------------------------===//
3673
3674#ifndef NDEBUG
3675namespace llvm {
3676
3677template<> struct GraphTraits<
3678 ScheduleDAGMI*> : public GraphTraits<ScheduleDAG*> {};
3679
3680template<>
3681struct DOTGraphTraits<ScheduleDAGMI*> : public DefaultDOTGraphTraits {
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003682 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
Andrew Trickea9fd952013-01-25 07:45:29 +00003683
3684 static std::string getGraphName(const ScheduleDAG *G) {
3685 return G->MF.getName();
3686 }
3687
3688 static bool renderGraphFromBottomUp() {
3689 return true;
3690 }
3691
3692 static bool isNodeHidden(const SUnit *Node) {
Matthias Braund78ee542015-09-17 21:09:59 +00003693 if (ViewMISchedCutoff == 0)
3694 return false;
3695 return (Node->Preds.size() > ViewMISchedCutoff
3696 || Node->Succs.size() > ViewMISchedCutoff);
Andrew Trickea9fd952013-01-25 07:45:29 +00003697 }
3698
Andrew Trickea9fd952013-01-25 07:45:29 +00003699 /// If you want to override the dot attributes printed for a particular
3700 /// edge, override this method.
3701 static std::string getEdgeAttributes(const SUnit *Node,
3702 SUnitIterator EI,
3703 const ScheduleDAG *Graph) {
3704 if (EI.isArtificialDep())
3705 return "color=cyan,style=dashed";
3706 if (EI.isCtrlDep())
3707 return "color=blue,style=dashed";
3708 return "";
3709 }
3710
3711 static std::string getNodeLabel(const SUnit *SU, const ScheduleDAG *G) {
Alp Tokere69170a2014-06-26 22:52:05 +00003712 std::string Str;
3713 raw_string_ostream SS(Str);
Andrew Trickd7f890e2013-12-28 21:56:47 +00003714 const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
3715 const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
Craig Topperc0196b12014-04-14 00:51:57 +00003716 static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
Andrew Trick7609b7d2013-09-06 17:32:42 +00003717 SS << "SU:" << SU->NodeNum;
3718 if (DFS)
3719 SS << " I:" << DFS->getNumInstrs(SU);
Andrew Trickea9fd952013-01-25 07:45:29 +00003720 return SS.str();
3721 }
Eugene Zelenko32a40562017-09-11 23:00:48 +00003722
Andrew Trickea9fd952013-01-25 07:45:29 +00003723 static std::string getNodeDescription(const SUnit *SU, const ScheduleDAG *G) {
3724 return G->getGraphNodeLabel(SU);
3725 }
3726
Andrew Trickd7f890e2013-12-28 21:56:47 +00003727 static std::string getNodeAttributes(const SUnit *N, const ScheduleDAG *G) {
Andrew Trickea9fd952013-01-25 07:45:29 +00003728 std::string Str("shape=Mrecord");
Andrew Trickd7f890e2013-12-28 21:56:47 +00003729 const ScheduleDAGMI *DAG = static_cast<const ScheduleDAGMI*>(G);
3730 const SchedDFSResult *DFS = DAG->hasVRegLiveness() ?
Craig Topperc0196b12014-04-14 00:51:57 +00003731 static_cast<const ScheduleDAGMILive*>(G)->getDFSResult() : nullptr;
Andrew Trickea9fd952013-01-25 07:45:29 +00003732 if (DFS) {
3733 Str += ",style=filled,fillcolor=\"#";
3734 Str += DOT::getColorString(DFS->getSubtreeID(N));
3735 Str += '"';
3736 }
3737 return Str;
3738 }
3739};
Eugene Zelenkodb56e5a2017-02-22 22:32:51 +00003740
3741} // end namespace llvm
Andrew Trickea9fd952013-01-25 07:45:29 +00003742#endif // NDEBUG
3743
3744/// viewGraph - Pop up a ghostview window with the reachable parts of the DAG
3745/// rendered using 'dot'.
Andrew Trickea9fd952013-01-25 07:45:29 +00003746void ScheduleDAGMI::viewGraph(const Twine &Name, const Twine &Title) {
3747#ifndef NDEBUG
3748 ViewGraph(this, Name, false, Title);
3749#else
3750 errs() << "ScheduleDAGMI::viewGraph is only available in debug builds on "
3751 << "systems with Graphviz or gv!\n";
3752#endif // NDEBUG
3753}
3754
3755/// Out-of-line implementation with no arguments is handy for gdb.
3756void ScheduleDAGMI::viewGraph() {
3757 viewGraph(getDAGName(), "Scheduling-Units Graph for " + getDAGName());
3758}