LLVM 20.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
50
51namespace llvm {
52
54 WS_Off, /// Turn off window algorithm.
55 WS_On, /// Use window algorithm after SMS algorithm fails.
56 WS_Force /// Use window algorithm instead of SMS algorithm.
57};
58
59/// The main class in the implementation of the target independent window
60/// scheduler.
62protected:
64 MachineFunction *MF = nullptr;
68 const TargetInstrInfo *TII = nullptr;
69 const TargetRegisterInfo *TRI = nullptr;
71
72 /// To innovatively identify the dependencies between MIs across two trips, we
73 /// construct a DAG for a new MBB, which is created by copying the original
74 /// MBB three times. We refer to this new MBB as 'TripleMBB' and the
75 /// corresponding DAG as 'TripleDAG'.
76 /// If the dependencies are more than two trips, we avoid applying window
77 /// algorithm by identifying successive phis in the old MBB.
78 std::unique_ptr<ScheduleDAGInstrs> TripleDAG;
79 /// OriMIs keeps the MIs removed from the original MBB.
81 /// TriMIs keeps the MIs of TripleMBB, which is used to restore TripleMBB.
83 /// TriToOri keeps the mappings between the MI clones in TripleMBB and their
84 /// original MI.
86 /// OriToCycle keeps the mappings between the original MI and its issue cycle.
88 /// SchedResult keeps the result of each list scheduling, and the format of
89 /// the tuple is <MI pointer, Cycle, Stage, Order ID>.
91 /// SchedPhiNum records the number of phi in the original MBB, and the
92 /// scheduling starts with MI after phis.
93 unsigned SchedPhiNum = 0;
94 /// SchedInstrNum records the MIs involved in scheduling in the original MBB,
95 /// excluding debug instructions.
96 unsigned SchedInstrNum = 0;
97 /// BestII and BestOffset record the characteristics of the best scheduling
98 /// result and are used together with SchedResult as the final window
99 /// scheduling result.
100 unsigned BestII = UINT_MAX;
101 unsigned BestOffset = 0;
102 /// BaseII is the II obtained when the window offset is SchedPhiNum. This
103 /// offset is the initial position of the sliding window.
104 unsigned BaseII = 0;
105
106public:
108 virtual ~WindowScheduler() {}
109
110 bool run();
111
112protected:
113 /// Two types of ScheduleDAGs are needed, one for creating dependency graphs
114 /// only, and the other for list scheduling as determined by the target.
115 virtual ScheduleDAGInstrs *
116 createMachineScheduler(bool OnlyBuildGraph = false);
117 /// Initializes the algorithm and determines if it can be executed.
118 virtual bool initialize();
119 /// Add some related processing before running window scheduling.
120 virtual void preProcess();
121 /// Add some related processing after running window scheduling.
122 virtual void postProcess();
123 /// Back up the MIs in the original MBB and remove them from MBB.
124 void backupMBB();
125 /// Erase the MIs in current MBB and restore the original MIs.
126 void restoreMBB();
127 /// Make three copies of the original MBB to generate a new TripleMBB.
128 virtual void generateTripleMBB();
129 /// Restore the order of MIs in TripleMBB after each list scheduling.
130 virtual void restoreTripleMBB();
131 /// Give the folding position in the window algorithm, where different
132 /// heuristics can be used. It determines the performance and compilation time
133 /// of the algorithm.
134 virtual SmallVector<unsigned> getSearchIndexes(unsigned SearchNum,
135 unsigned SearchRatio);
136 /// Calculate MIs execution cycle after list scheduling.
137 virtual int calculateMaxCycle(ScheduleDAGInstrs &DAG, unsigned Offset);
138 /// Calculate the stall cycle between two trips after list scheduling.
139 virtual int calculateStallCycle(unsigned Offset, int MaxCycle);
140 /// Analyzes the II value after each list scheduling.
141 virtual unsigned analyseII(ScheduleDAGInstrs &DAG, unsigned Offset);
142 /// Phis are scheduled separately after each list scheduling.
143 virtual void schedulePhi(int Offset, unsigned &II);
144 /// Get the final issue order of all scheduled MIs including phis.
146 /// Update the scheduling result after each list scheduling.
147 virtual void updateScheduleResult(unsigned Offset, unsigned II);
148 /// Check whether the final result of window scheduling is valid.
149 virtual bool isScheduleValid() { return BestOffset != SchedPhiNum; }
150 /// Using the scheduling infrastructure to expand the results of window
151 /// scheduling. It is usually necessary to add prologue and epilogue MBBs.
152 virtual void expand();
153 /// Update the live intervals for all registers used within MBB.
154 virtual void updateLiveIntervals();
155 /// Estimate a II value at which all MIs will be scheduled successfully.
157 /// Gets the iterator range of MIs in the scheduling window.
159 unsigned Num);
160 /// Get the issue cycle of the new MI based on the cycle of the original MI.
161 int getOriCycle(MachineInstr *NewMI);
162 /// Get the original MI from which the new MI is cloned.
164 /// Get the scheduling stage, where the stage of the new MI is identical to
165 /// the original MI.
166 unsigned getOriStage(MachineInstr *OriMI, unsigned Offset);
167 /// Gets the register in phi which is generated from the current MBB.
169};
170} // namespace llvm
171#endif
uint64_t IntrinsicInst * II
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
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.
Definition: SmallVector.h:1209
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.
The main class in the implementation of the target independent window scheduler.
MachineInstr * getOriMI(MachineInstr *NewMI)
Get the original MI from which the new MI is cloned.
virtual ScheduleDAGInstrs * createMachineScheduler(bool OnlyBuildGraph=false)
Two types of ScheduleDAGs are needed, one for creating dependency graphs only, and the other for list...
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.
MachineSchedContext * Context
virtual void restoreTripleMBB()
Restore the order of MIs in TripleMBB after each list scheduling.
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
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 *, MachineInstr * > TriToOri
TriToOri keeps the mappings between the MI clones in TripleMBB and their original MI.
int getEstimatedII(ScheduleDAGInstrs &DAG)
Estimate a II value at which all MIs will be scheduled successfully.
virtual void expand()
Using the scheduling infrastructure to expand the results of window scheduling.
DenseMap< MachineInstr *, int > getIssueOrder(unsigned Offset, unsigned II)
Get the final issue order of all scheduled MIs including phis.
Register getAntiRegister(MachineInstr *Phi)
Gets the register in phi which is generated from the current MBB.
unsigned getOriStage(MachineInstr *OriMI, unsigned Offset)
Get the scheduling stage, where the stage of the new MI is identical to the original MI.
const TargetRegisterInfo * TRI
virtual void updateLiveIntervals()
Update the live intervals for all registers used within MBB.
const TargetSubtargetInfo * Subtarget
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.
virtual void schedulePhi(int Offset, unsigned &II)
Phis are scheduled separately after each list scheduling.
MachineFunction * MF
virtual unsigned analyseII(ScheduleDAGInstrs &DAG, unsigned Offset)
Analyzes the II value after each list scheduling.
int getOriCycle(MachineInstr *NewMI)
Get the issue cycle of the new MI based on the cycle of the original MI.
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.
iterator_range< MachineBasicBlock::iterator > getScheduleRange(unsigned Offset, unsigned Num)
Gets the iterator range of MIs in the scheduling window.
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.
virtual bool initialize()
Initializes the algorithm and determines if it can be executed.
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.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
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...