LLVM 24.0.0git
WindowScheduler.h
Go to the documentation of this file.
1//======----------- WindowScheduler.cpp - window scheduler -------------======//
2//
3// 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
6//
7//===----------------------------------------------------------------------===//
8//
9// An implementation of the Window Scheduling software pipelining algorithm.
10//
11// The concept of the window algorithm was first unveiled in Steven Muchnick's
12// book, "Advanced Compiler Design And Implementation", and later elaborated
13// upon in Venkatraman Govindaraju's report, "Implementation of Software
14// Pipelining Using Window Scheduling".
15//
16// The window algorithm can be perceived as a modulo scheduling algorithm with a
17// stage count of 2. It boasts a higher scheduling success rate in targets with
18// severe resource conflicts when compared to the classic Swing Modulo
19// Scheduling (SMS) algorithm. To align with the LLVM scheduling framework, we
20// have enhanced the original window algorithm. The primary steps are as
21// follows:
22//
23// 1. Instead of duplicating the original MBB twice as mentioned in the
24// literature, we copy it three times, generating TripleMBB and the
25// corresponding TripleDAG.
26//
27// 2. We establish a scheduling window on TripleMBB and execute list scheduling
28// within it.
29//
30// 3. After multiple list scheduling, we select the best outcome and expand it
31// into the final scheduling result.
32//
33// To cater to the needs of various targets, we have developed the window
34// scheduler in a form that is easily derivable. We recommend employing this
35// algorithm in targets with severe resource conflicts, and it can be utilized
36// either before or after the Register Allocator (RA).
37//
38// The default implementation provided here is before RA. If it is to be used
39// after RA, certain critical algorithm functions will need to be derived.
40//
41//===----------------------------------------------------------------------===//
42#ifndef LLVM_CODEGEN_WINDOWSCHEDULER_H
43#define LLVM_CODEGEN_WINDOWSCHEDULER_H
44
45#include "llvm/ADT/DenseSet.h"
51
52namespace llvm {
53
55
57 WS_Off, /// Turn off window algorithm.
58 WS_On, /// Use window algorithm after SMS algorithm fails.
59 WS_Force /// Use window algorithm instead of SMS algorithm.
60};
61
62/// TriCloneInfo describes an MI clone in TripleMBB: the original MI it was
63/// cloned from and the index of the copy (0, 1, or 2) it belongs to.
65 MachineInstr *Ori = nullptr;
66 unsigned Copy = 0;
67};
68
69/// The main class in the implementation of the target independent window
70/// scheduler.
72protected:
74 MachineFunction *MF = nullptr;
78 const TargetInstrInfo *TII = nullptr;
79 const TargetRegisterInfo *TRI = nullptr;
82
83 /// To innovatively identify the dependencies between MIs across two trips, we
84 /// construct a DAG for a new MBB, which is created by copying the original
85 /// MBB three times. We refer to this new MBB as 'TripleMBB' and the
86 /// corresponding DAG as 'TripleDAG'.
87 /// If the dependencies are more than two trips, we avoid applying window
88 /// algorithm by identifying successive phis in the old MBB.
89 std::unique_ptr<ScheduleDAGInstrs> TripleDAG;
90 /// OriMIs keeps the MIs removed from the original MBB.
92 /// TriMIs keeps the MIs of TripleMBB, which is used to restore TripleMBB.
94 /// TriToOri keeps the mappings between the MI clones in TripleMBB and the
95 /// information about their original MI and copy index.
97 /// OriToCycle keeps the mappings between the original MI and its issue cycle.
99 /// LoopCarriedMemDeps keeps ordered pairs (Pred, Succ) of original memory MIs
100 /// such that the iteration-N access Pred must be ordered before the
101 /// iteration-(N+1) access Succ.
103 /// MemDepEdgeFailed is set when enforcing a loop-carried memory dependence as
104 /// an artificial DAG edge would have created a cycle, so the edge could not
105 /// be added. In that case the current window must be abandoned, as its
106 /// schedule would not honor the dependence.
107 bool MemDepEdgeFailed = false;
108 /// SchedResult keeps the result of each list scheduling, and the format of
109 /// the tuple is <MI pointer, Cycle, Stage, Order ID>.
111 /// SchedPhiNum records the number of phi in the original MBB, and the
112 /// scheduling starts with MI after phis.
113 unsigned SchedPhiNum = 0;
114 /// SchedInstrNum records the MIs involved in scheduling in the original MBB,
115 /// excluding debug instructions.
116 unsigned SchedInstrNum = 0;
117 /// BestII and BestOffset record the characteristics of the best scheduling
118 /// result and are used together with SchedResult as the final window
119 /// scheduling result.
120 unsigned BestII = UINT_MAX;
121 unsigned BestOffset = 0;
122 /// BaseII is the II obtained when the window offset is SchedPhiNum. This
123 /// offset is the initial position of the sliding window.
124 unsigned BaseII = 0;
125
126public:
128 MachineDominatorTree *MDT = nullptr);
129 virtual ~WindowScheduler() = default;
130
131 bool run();
132
133protected:
134 /// Two types of ScheduleDAGs are needed, one for creating dependency graphs
135 /// only, and the other for list scheduling as determined by the target.
136 virtual ScheduleDAGInstrs *
137 createMachineScheduler(bool OnlyBuildGraph = false);
138 /// Initializes the algorithm and determines if it can be executed.
139 virtual bool initialize();
140 /// Add some related processing before running window scheduling.
141 virtual void preProcess();
142 /// Detect loop-carried memory dependences in the original MBB that must be
143 /// preserved across loop iterations. This must run on the live MBB before
144 /// backupMBB(), as it analyzes the induction recurrence of memory accesses.
145 /// The hazardous pairs of original MIs are recorded in LoopCarriedMemDeps.
147 /// Add some related processing after running window scheduling.
148 virtual void postProcess();
149 /// Back up the MIs in the original MBB and remove them from MBB.
150 void backupMBB();
151 /// Erase the MIs in current MBB and restore the original MIs.
152 void restoreMBB();
153 /// Make three copies of the original MBB to generate a new TripleMBB.
154 virtual void generateTripleMBB();
155 /// Restore the order of MIs in TripleMBB after each list scheduling.
156 virtual void restoreTripleMBB();
157 /// Give the folding position in the window algorithm, where different
158 /// heuristics can be used. It determines the performance and compilation time
159 /// of the algorithm.
160 virtual SmallVector<unsigned> getSearchIndexes(unsigned SearchNum,
161 unsigned SearchRatio);
162 /// Calculate MIs execution cycle after list scheduling.
163 virtual int calculateMaxCycle(ScheduleDAGInstrs &DAG, unsigned Offset);
164 /// Calculate the stall cycle between two trips after list scheduling.
165 virtual int calculateStallCycle(unsigned Offset, int MaxCycle);
166 /// Analyzes the II value after each list scheduling.
167 virtual unsigned analyseII(ScheduleDAGInstrs &DAG, unsigned Offset);
168 /// Phis are scheduled separately after each list scheduling.
169 virtual void schedulePhi(int Offset, unsigned &II);
170 /// Get the final issue order of all scheduled MIs including phis.
172 /// Update the scheduling result after each list scheduling.
173 virtual void updateScheduleResult(unsigned Offset, unsigned II);
174 /// Check whether the final result of window scheduling is valid.
175 virtual bool isScheduleValid() { return BestOffset != SchedPhiNum; }
176 /// Using the scheduling infrastructure to expand the results of window
177 /// scheduling. It is usually necessary to add prologue and epilogue MBBs.
178 virtual void expand();
179 /// Update the live intervals for all registers used within MBB.
180 virtual void updateLiveIntervals();
181 /// Estimate a II value at which all MIs will be scheduled successfully.
182 int getEstimatedII(ScheduleDAGInstrs &DAG);
183 /// Gets the iterator range of MIs in the scheduling window.
184 iterator_range<MachineBasicBlock::iterator> getScheduleRange(unsigned Offset,
185 unsigned Num);
186 /// Get the issue cycle of the new MI based on the cycle of the original MI.
187 int getOriCycle(MachineInstr *NewMI);
188 /// Get the original MI from which the new MI is cloned.
189 MachineInstr *getOriMI(MachineInstr *NewMI);
190 /// Get the scheduling stage, where the stage of the new MI is identical to
191 /// the original MI.
192 unsigned getOriStage(MachineInstr *OriMI, unsigned Offset);
193 /// Gets the register in phi which is generated from the current MBB.
194 Register getAntiRegister(MachineInstr *Phi);
195};
196} // namespace llvm
197#endif
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:211
This file defines the DenseSet and SmallDenseSet classes.
static Expected< BitVector > expand(StringRef S, StringRef Original)
uint64_t IntrinsicInst * II
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition Register.h:20
A ScheduleDAG for scheduling lists of MachineInstr.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual ScheduleDAGInstrs * createMachineScheduler(bool OnlyBuildGraph=false)
Two types of ScheduleDAGs are needed, one for creating dependency graphs only, and the other for list...
virtual ~WindowScheduler()=default
unsigned SchedPhiNum
SchedPhiNum records the number of phi in the original MBB, and the scheduling starts with MI after ph...
virtual void preProcess()
Add some related processing before running window scheduling.
void collectLoopCarriedMemDeps()
Detect loop-carried memory dependences in the original MBB that must be preserved across loop iterati...
MachineSchedContext * Context
virtual void restoreTripleMBB()
Restore the order of MIs in TripleMBB after each list scheduling.
WindowScheduler(MachineSchedContext *C, MachineLoop &ML, MachineDominatorTree *MDT=nullptr)
virtual void postProcess()
Add some related processing after running window scheduling.
DenseMap< MachineInstr *, int > OriToCycle
OriToCycle keeps the mappings between the original MI and its issue cycle.
virtual int calculateMaxCycle(ScheduleDAGInstrs &DAG, unsigned Offset)
Calculate MIs execution cycle after list scheduling.
MachineRegisterInfo * MRI
MachineDominatorTree * MDT
MachineBasicBlock * MBB
unsigned BestII
BestII and BestOffset record the characteristics of the best scheduling result and are used together ...
void backupMBB()
Back up the MIs in the original MBB and remove them from MBB.
DenseMap< MachineInstr *, int > getIssueOrder(unsigned Offset, unsigned II)
Get the final issue order of all scheduled MIs including phis.
const TargetRegisterInfo * TRI
const TargetSubtargetInfo * Subtarget
bool MemDepEdgeFailed
MemDepEdgeFailed is set when enforcing a loop-carried memory dependence as an artificial DAG edge wou...
std::unique_ptr< ScheduleDAGInstrs > TripleDAG
To innovatively identify the dependencies between MIs across two trips, we construct a DAG for a new ...
unsigned BaseII
BaseII is the II obtained when the window offset is SchedPhiNum.
DenseSet< std::pair< MachineInstr *, MachineInstr * > > LoopCarriedMemDeps
LoopCarriedMemDeps keeps ordered pairs (Pred, Succ) of original memory MIs such that the iteration-N ...
virtual void schedulePhi(int Offset, unsigned &II)
Phis are scheduled separately after each list scheduling.
MachineFunction * MF
DenseMap< MachineInstr *, TriCloneInfo > TriToOri
TriToOri keeps the mappings between the MI clones in TripleMBB and the information about their origin...
virtual unsigned analyseII(ScheduleDAGInstrs &DAG, unsigned Offset)
Analyzes the II value after each list scheduling.
unsigned SchedInstrNum
SchedInstrNum records the MIs involved in scheduling in the original MBB, excluding debug instruction...
const TargetInstrInfo * TII
virtual void generateTripleMBB()
Make three copies of the original MBB to generate a new TripleMBB.
virtual bool isScheduleValid()
Check whether the final result of window scheduling is valid.
virtual int calculateStallCycle(unsigned Offset, int MaxCycle)
Calculate the stall cycle between two trips after list scheduling.
virtual void updateScheduleResult(unsigned Offset, unsigned II)
Update the scheduling result after each list scheduling.
SmallVector< MachineInstr * > OriMIs
OriMIs keeps the MIs removed from the original MBB.
SmallVector< std::tuple< MachineInstr *, int, int, int >, 256 > SchedResult
SchedResult keeps the result of each list scheduling, and the format of the tuple is <MI pointer,...
virtual SmallVector< unsigned > getSearchIndexes(unsigned SearchNum, unsigned SearchRatio)
Give the folding position in the window algorithm, where different heuristics can be used.
void restoreMBB()
Erase the MIs in current MBB and restore the original MIs.
SmallVector< MachineInstr * > TriMIs
TriMIs keeps the MIs of TripleMBB, which is used to restore TripleMBB.
A range adaptor for a pair of iterators.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
WindowSchedulingFlag
@ WS_Force
Use window algorithm after SMS algorithm fails.
@ WS_On
Turn off window algorithm.
MachineSchedContext provides enough context from the MachineScheduler pass for the target to instanti...
TriCloneInfo describes an MI clone in TripleMBB: the original MI it was cloned from and the index of ...
MachineInstr * Ori