1*9880d681SAndroid Build Coastguard Worker //===-- MachinePipeliner.cpp - Machine Software Pipeliner Pass ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // An implementation of the Swing Modulo Scheduling (SMS) software pipeliner.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker // Software pipelining (SWP) is an instruction scheduling technique for loops
13*9880d681SAndroid Build Coastguard Worker // that overlap loop iterations and explioits ILP via a compiler transformation.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker // Swing Modulo Scheduling is an implementation of software pipelining
16*9880d681SAndroid Build Coastguard Worker // that generates schedules that are near optimal in terms of initiation
17*9880d681SAndroid Build Coastguard Worker // interval, register requirements, and stage count. See the papers:
18*9880d681SAndroid Build Coastguard Worker //
19*9880d681SAndroid Build Coastguard Worker // "Swing Modulo Scheduling: A Lifetime-Sensitive Approach", by J. Llosa,
20*9880d681SAndroid Build Coastguard Worker // A. Gonzalez, E. Ayguade, and M. Valero. In PACT '96 Processings of the 1996
21*9880d681SAndroid Build Coastguard Worker // Conference on Parallel Architectures and Compilation Techiniques.
22*9880d681SAndroid Build Coastguard Worker //
23*9880d681SAndroid Build Coastguard Worker // "Lifetime-Sensitive Modulo Scheduling in a Production Environment", by J.
24*9880d681SAndroid Build Coastguard Worker // Llosa, E. Ayguade, A. Gonzalez, M. Valero, and J. Eckhardt. In IEEE
25*9880d681SAndroid Build Coastguard Worker // Transactions on Computers, Vol. 50, No. 3, 2001.
26*9880d681SAndroid Build Coastguard Worker //
27*9880d681SAndroid Build Coastguard Worker // "An Implementation of Swing Modulo Scheduling With Extensions for
28*9880d681SAndroid Build Coastguard Worker // Superblocks", by T. Lattner, Master's Thesis, University of Illinois at
29*9880d681SAndroid Build Coastguard Worker // Urbana-Chambpain, 2005.
30*9880d681SAndroid Build Coastguard Worker //
31*9880d681SAndroid Build Coastguard Worker //
32*9880d681SAndroid Build Coastguard Worker // The SMS algorithm consists of three main steps after computing the minimal
33*9880d681SAndroid Build Coastguard Worker // initiation interval (MII).
34*9880d681SAndroid Build Coastguard Worker // 1) Analyze the dependence graph and compute information about each
35*9880d681SAndroid Build Coastguard Worker // instruction in the graph.
36*9880d681SAndroid Build Coastguard Worker // 2) Order the nodes (instructions) by priority based upon the heuristics
37*9880d681SAndroid Build Coastguard Worker // described in the algorithm.
38*9880d681SAndroid Build Coastguard Worker // 3) Attempt to schedule the nodes in the specified order using the MII.
39*9880d681SAndroid Build Coastguard Worker //
40*9880d681SAndroid Build Coastguard Worker // This SMS implementation is a target-independent back-end pass. When enabled,
41*9880d681SAndroid Build Coastguard Worker // the pass runs just prior to the register allocation pass, while the machine
42*9880d681SAndroid Build Coastguard Worker // IR is in SSA form. If software pipelining is successful, then the original
43*9880d681SAndroid Build Coastguard Worker // loop is replaced by the optimized loop. The optimized loop contains one or
44*9880d681SAndroid Build Coastguard Worker // more prolog blocks, the pipelined kernel, and one or more epilog blocks. If
45*9880d681SAndroid Build Coastguard Worker // the instructions cannot be scheduled in a given MII, we increase the MII by
46*9880d681SAndroid Build Coastguard Worker // one and try again.
47*9880d681SAndroid Build Coastguard Worker //
48*9880d681SAndroid Build Coastguard Worker // The SMS implementation is an extension of the ScheduleDAGInstrs class. We
49*9880d681SAndroid Build Coastguard Worker // represent loop carried dependences in the DAG as order edges to the Phi
50*9880d681SAndroid Build Coastguard Worker // nodes. We also perform several passes over the DAG to eliminate unnecessary
51*9880d681SAndroid Build Coastguard Worker // edges that inhibit the ability to pipeline. The implementation uses the
52*9880d681SAndroid Build Coastguard Worker // DFAPacketizer class to compute the minimum initiation interval and the check
53*9880d681SAndroid Build Coastguard Worker // where an instruction may be inserted in the pipelined schedule.
54*9880d681SAndroid Build Coastguard Worker //
55*9880d681SAndroid Build Coastguard Worker // In order for the SMS pass to work, several target specific hooks need to be
56*9880d681SAndroid Build Coastguard Worker // implemented to get information about the loop structure and to rewrite
57*9880d681SAndroid Build Coastguard Worker // instructions.
58*9880d681SAndroid Build Coastguard Worker //
59*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
60*9880d681SAndroid Build Coastguard Worker
61*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/DenseMap.h"
62*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/MapVector.h"
63*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/PriorityQueue.h"
64*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SetVector.h"
65*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallPtrSet.h"
66*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/SmallSet.h"
67*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
68*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/AliasAnalysis.h"
69*9880d681SAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
70*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/DFAPacketizer.h"
71*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/LiveIntervalAnalysis.h"
72*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineBasicBlock.h"
73*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
74*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
75*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
76*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
77*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
78*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterClassInfo.h"
79*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/RegisterPressure.h"
80*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ScheduleDAGInstrs.h"
81*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCInstrItineraries.h"
82*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
83*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
84*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
85*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
86*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
87*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
88*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
89*9880d681SAndroid Build Coastguard Worker #include <climits>
90*9880d681SAndroid Build Coastguard Worker #include <deque>
91*9880d681SAndroid Build Coastguard Worker #include <map>
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker using namespace llvm;
94*9880d681SAndroid Build Coastguard Worker
95*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "pipeliner"
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker STATISTIC(NumTrytoPipeline, "Number of loops that we attempt to pipeline");
98*9880d681SAndroid Build Coastguard Worker STATISTIC(NumPipelined, "Number of loops software pipelined");
99*9880d681SAndroid Build Coastguard Worker
100*9880d681SAndroid Build Coastguard Worker /// A command line option to turn software pipelining on or off.
101*9880d681SAndroid Build Coastguard Worker cl::opt<bool> EnableSWP("enable-pipeliner", cl::Hidden, cl::init(true),
102*9880d681SAndroid Build Coastguard Worker cl::ZeroOrMore, cl::desc("Enable Software Pipelining"));
103*9880d681SAndroid Build Coastguard Worker
104*9880d681SAndroid Build Coastguard Worker /// A command line option to enable SWP at -Os.
105*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> EnableSWPOptSize("enable-pipeliner-opt-size",
106*9880d681SAndroid Build Coastguard Worker cl::desc("Enable SWP at Os."), cl::Hidden,
107*9880d681SAndroid Build Coastguard Worker cl::init(false));
108*9880d681SAndroid Build Coastguard Worker
109*9880d681SAndroid Build Coastguard Worker /// A command line argument to limit minimum initial interval for pipelining.
110*9880d681SAndroid Build Coastguard Worker static cl::opt<int> SwpMaxMii("pipeliner-max-mii",
111*9880d681SAndroid Build Coastguard Worker cl::desc("Size limit for the the MII."),
112*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::init(27));
113*9880d681SAndroid Build Coastguard Worker
114*9880d681SAndroid Build Coastguard Worker /// A command line argument to limit the number of stages in the pipeline.
115*9880d681SAndroid Build Coastguard Worker static cl::opt<int>
116*9880d681SAndroid Build Coastguard Worker SwpMaxStages("pipeliner-max-stages",
117*9880d681SAndroid Build Coastguard Worker cl::desc("Maximum stages allowed in the generated scheduled."),
118*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::init(3));
119*9880d681SAndroid Build Coastguard Worker
120*9880d681SAndroid Build Coastguard Worker /// A command line option to disable the pruning of chain dependences due to
121*9880d681SAndroid Build Coastguard Worker /// an unrelated Phi.
122*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
123*9880d681SAndroid Build Coastguard Worker SwpPruneDeps("pipeliner-prune-deps",
124*9880d681SAndroid Build Coastguard Worker cl::desc("Prune dependences between unrelated Phi nodes."),
125*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::init(true));
126*9880d681SAndroid Build Coastguard Worker
127*9880d681SAndroid Build Coastguard Worker /// A command line option to disable the pruning of loop carried order
128*9880d681SAndroid Build Coastguard Worker /// dependences.
129*9880d681SAndroid Build Coastguard Worker static cl::opt<bool>
130*9880d681SAndroid Build Coastguard Worker SwpPruneLoopCarried("pipeliner-prune-loop-carried",
131*9880d681SAndroid Build Coastguard Worker cl::desc("Prune loop carried order dependences."),
132*9880d681SAndroid Build Coastguard Worker cl::Hidden, cl::init(true));
133*9880d681SAndroid Build Coastguard Worker
134*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
135*9880d681SAndroid Build Coastguard Worker static cl::opt<int> SwpLoopLimit("pipeliner-max", cl::Hidden, cl::init(-1));
136*9880d681SAndroid Build Coastguard Worker #endif
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> SwpIgnoreRecMII("pipeliner-ignore-recmii",
139*9880d681SAndroid Build Coastguard Worker cl::ReallyHidden, cl::init(false),
140*9880d681SAndroid Build Coastguard Worker cl::ZeroOrMore, cl::desc("Ignore RecMII"));
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker namespace {
143*9880d681SAndroid Build Coastguard Worker
144*9880d681SAndroid Build Coastguard Worker class NodeSet;
145*9880d681SAndroid Build Coastguard Worker class SMSchedule;
146*9880d681SAndroid Build Coastguard Worker class SwingSchedulerDAG;
147*9880d681SAndroid Build Coastguard Worker
148*9880d681SAndroid Build Coastguard Worker /// The main class in the implementation of the target independent
149*9880d681SAndroid Build Coastguard Worker /// software pipeliner pass.
150*9880d681SAndroid Build Coastguard Worker class MachinePipeliner : public MachineFunctionPass {
151*9880d681SAndroid Build Coastguard Worker public:
152*9880d681SAndroid Build Coastguard Worker MachineFunction *MF = nullptr;
153*9880d681SAndroid Build Coastguard Worker const MachineLoopInfo *MLI = nullptr;
154*9880d681SAndroid Build Coastguard Worker const MachineDominatorTree *MDT = nullptr;
155*9880d681SAndroid Build Coastguard Worker const InstrItineraryData *InstrItins;
156*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII = nullptr;
157*9880d681SAndroid Build Coastguard Worker RegisterClassInfo RegClassInfo;
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
160*9880d681SAndroid Build Coastguard Worker static int NumTries;
161*9880d681SAndroid Build Coastguard Worker #endif
162*9880d681SAndroid Build Coastguard Worker /// Cache the target analysis information about the loop.
163*9880d681SAndroid Build Coastguard Worker struct LoopInfo {
164*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = nullptr;
165*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *FBB = nullptr;
166*9880d681SAndroid Build Coastguard Worker SmallVector<MachineOperand, 4> BrCond;
167*9880d681SAndroid Build Coastguard Worker MachineInstr *LoopInductionVar = nullptr;
168*9880d681SAndroid Build Coastguard Worker MachineInstr *LoopCompare = nullptr;
169*9880d681SAndroid Build Coastguard Worker };
170*9880d681SAndroid Build Coastguard Worker LoopInfo LI;
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker static char ID;
MachinePipeliner()173*9880d681SAndroid Build Coastguard Worker MachinePipeliner() : MachineFunctionPass(ID) {
174*9880d681SAndroid Build Coastguard Worker initializeMachinePipelinerPass(*PassRegistry::getPassRegistry());
175*9880d681SAndroid Build Coastguard Worker }
176*9880d681SAndroid Build Coastguard Worker
177*9880d681SAndroid Build Coastguard Worker virtual bool runOnMachineFunction(MachineFunction &MF);
178*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const179*9880d681SAndroid Build Coastguard Worker virtual void getAnalysisUsage(AnalysisUsage &AU) const {
180*9880d681SAndroid Build Coastguard Worker AU.addRequired<AAResultsWrapperPass>();
181*9880d681SAndroid Build Coastguard Worker AU.addPreserved<AAResultsWrapperPass>();
182*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineLoopInfo>();
183*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineDominatorTree>();
184*9880d681SAndroid Build Coastguard Worker AU.addRequired<LiveIntervals>();
185*9880d681SAndroid Build Coastguard Worker MachineFunctionPass::getAnalysisUsage(AU);
186*9880d681SAndroid Build Coastguard Worker }
187*9880d681SAndroid Build Coastguard Worker
188*9880d681SAndroid Build Coastguard Worker private:
189*9880d681SAndroid Build Coastguard Worker bool canPipelineLoop(MachineLoop &L);
190*9880d681SAndroid Build Coastguard Worker bool scheduleLoop(MachineLoop &L);
191*9880d681SAndroid Build Coastguard Worker bool swingModuloScheduler(MachineLoop &L);
192*9880d681SAndroid Build Coastguard Worker };
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker /// This class builds the dependence graph for the instructions in a loop,
195*9880d681SAndroid Build Coastguard Worker /// and attempts to schedule the instructions using the SMS algorithm.
196*9880d681SAndroid Build Coastguard Worker class SwingSchedulerDAG : public ScheduleDAGInstrs {
197*9880d681SAndroid Build Coastguard Worker MachinePipeliner &Pass;
198*9880d681SAndroid Build Coastguard Worker /// The minimum initiation interval between iterations for this schedule.
199*9880d681SAndroid Build Coastguard Worker unsigned MII;
200*9880d681SAndroid Build Coastguard Worker /// Set to true if a valid pipelined schedule is found for the loop.
201*9880d681SAndroid Build Coastguard Worker bool Scheduled;
202*9880d681SAndroid Build Coastguard Worker MachineLoop &Loop;
203*9880d681SAndroid Build Coastguard Worker LiveIntervals &LIS;
204*9880d681SAndroid Build Coastguard Worker const RegisterClassInfo &RegClassInfo;
205*9880d681SAndroid Build Coastguard Worker
206*9880d681SAndroid Build Coastguard Worker /// A toplogical ordering of the SUnits, which is needed for changing
207*9880d681SAndroid Build Coastguard Worker /// dependences and iterating over the SUnits.
208*9880d681SAndroid Build Coastguard Worker ScheduleDAGTopologicalSort Topo;
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker struct NodeInfo {
211*9880d681SAndroid Build Coastguard Worker int ASAP;
212*9880d681SAndroid Build Coastguard Worker int ALAP;
NodeInfo__anon269b60a90111::SwingSchedulerDAG::NodeInfo213*9880d681SAndroid Build Coastguard Worker NodeInfo() : ASAP(0), ALAP(0) {}
214*9880d681SAndroid Build Coastguard Worker };
215*9880d681SAndroid Build Coastguard Worker /// Computed properties for each node in the graph.
216*9880d681SAndroid Build Coastguard Worker std::vector<NodeInfo> ScheduleInfo;
217*9880d681SAndroid Build Coastguard Worker
218*9880d681SAndroid Build Coastguard Worker enum OrderKind { BottomUp = 0, TopDown = 1 };
219*9880d681SAndroid Build Coastguard Worker /// Computed node ordering for scheduling.
220*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> NodeOrder;
221*9880d681SAndroid Build Coastguard Worker
222*9880d681SAndroid Build Coastguard Worker typedef SmallVector<NodeSet, 8> NodeSetType;
223*9880d681SAndroid Build Coastguard Worker typedef DenseMap<unsigned, unsigned> ValueMapTy;
224*9880d681SAndroid Build Coastguard Worker typedef SmallVectorImpl<MachineBasicBlock *> MBBVectorTy;
225*9880d681SAndroid Build Coastguard Worker typedef DenseMap<MachineInstr *, MachineInstr *> InstrMapTy;
226*9880d681SAndroid Build Coastguard Worker
227*9880d681SAndroid Build Coastguard Worker /// Instructions to change when emitting the final schedule.
228*9880d681SAndroid Build Coastguard Worker DenseMap<SUnit *, std::pair<unsigned, int64_t>> InstrChanges;
229*9880d681SAndroid Build Coastguard Worker
230*9880d681SAndroid Build Coastguard Worker /// We may create a new instruction, so remember it because it
231*9880d681SAndroid Build Coastguard Worker /// must be deleted when the pass is finished.
232*9880d681SAndroid Build Coastguard Worker SmallPtrSet<MachineInstr *, 4> NewMIs;
233*9880d681SAndroid Build Coastguard Worker
234*9880d681SAndroid Build Coastguard Worker /// Helper class to implement Johnson's circuit finding algorithm.
235*9880d681SAndroid Build Coastguard Worker class Circuits {
236*9880d681SAndroid Build Coastguard Worker std::vector<SUnit> &SUnits;
237*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> Stack;
238*9880d681SAndroid Build Coastguard Worker BitVector Blocked;
239*9880d681SAndroid Build Coastguard Worker SmallVector<SmallPtrSet<SUnit *, 4>, 10> B;
240*9880d681SAndroid Build Coastguard Worker SmallVector<SmallVector<int, 4>, 16> AdjK;
241*9880d681SAndroid Build Coastguard Worker unsigned NumPaths;
242*9880d681SAndroid Build Coastguard Worker static unsigned MaxPaths;
243*9880d681SAndroid Build Coastguard Worker
244*9880d681SAndroid Build Coastguard Worker public:
Circuits(std::vector<SUnit> & SUs)245*9880d681SAndroid Build Coastguard Worker Circuits(std::vector<SUnit> &SUs)
246*9880d681SAndroid Build Coastguard Worker : SUnits(SUs), Stack(), Blocked(SUs.size()), B(SUs.size()),
247*9880d681SAndroid Build Coastguard Worker AdjK(SUs.size()) {}
248*9880d681SAndroid Build Coastguard Worker /// Reset the data structures used in the circuit algorithm.
reset()249*9880d681SAndroid Build Coastguard Worker void reset() {
250*9880d681SAndroid Build Coastguard Worker Stack.clear();
251*9880d681SAndroid Build Coastguard Worker Blocked.reset();
252*9880d681SAndroid Build Coastguard Worker B.assign(SUnits.size(), SmallPtrSet<SUnit *, 4>());
253*9880d681SAndroid Build Coastguard Worker NumPaths = 0;
254*9880d681SAndroid Build Coastguard Worker }
255*9880d681SAndroid Build Coastguard Worker void createAdjacencyStructure(SwingSchedulerDAG *DAG);
256*9880d681SAndroid Build Coastguard Worker bool circuit(int V, int S, NodeSetType &NodeSets, bool HasBackedge = false);
257*9880d681SAndroid Build Coastguard Worker void unblock(int U);
258*9880d681SAndroid Build Coastguard Worker };
259*9880d681SAndroid Build Coastguard Worker
260*9880d681SAndroid Build Coastguard Worker public:
SwingSchedulerDAG(MachinePipeliner & P,MachineLoop & L,LiveIntervals & lis,const RegisterClassInfo & rci)261*9880d681SAndroid Build Coastguard Worker SwingSchedulerDAG(MachinePipeliner &P, MachineLoop &L, LiveIntervals &lis,
262*9880d681SAndroid Build Coastguard Worker const RegisterClassInfo &rci)
263*9880d681SAndroid Build Coastguard Worker : ScheduleDAGInstrs(*P.MF, P.MLI, false), Pass(P), MII(0),
264*9880d681SAndroid Build Coastguard Worker Scheduled(false), Loop(L), LIS(lis), RegClassInfo(rci),
265*9880d681SAndroid Build Coastguard Worker Topo(SUnits, &ExitSU) {}
266*9880d681SAndroid Build Coastguard Worker
267*9880d681SAndroid Build Coastguard Worker void schedule();
268*9880d681SAndroid Build Coastguard Worker void finishBlock();
269*9880d681SAndroid Build Coastguard Worker
270*9880d681SAndroid Build Coastguard Worker /// Return true if the loop kernel has been scheduled.
hasNewSchedule()271*9880d681SAndroid Build Coastguard Worker bool hasNewSchedule() { return Scheduled; }
272*9880d681SAndroid Build Coastguard Worker
273*9880d681SAndroid Build Coastguard Worker /// Return the earliest time an instruction may be scheduled.
getASAP(SUnit * Node)274*9880d681SAndroid Build Coastguard Worker int getASAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ASAP; }
275*9880d681SAndroid Build Coastguard Worker
276*9880d681SAndroid Build Coastguard Worker /// Return the latest time an instruction my be scheduled.
getALAP(SUnit * Node)277*9880d681SAndroid Build Coastguard Worker int getALAP(SUnit *Node) { return ScheduleInfo[Node->NodeNum].ALAP; }
278*9880d681SAndroid Build Coastguard Worker
279*9880d681SAndroid Build Coastguard Worker /// The mobility function, which the the number of slots in which
280*9880d681SAndroid Build Coastguard Worker /// an instruction may be scheduled.
getMOV(SUnit * Node)281*9880d681SAndroid Build Coastguard Worker int getMOV(SUnit *Node) { return getALAP(Node) - getASAP(Node); }
282*9880d681SAndroid Build Coastguard Worker
283*9880d681SAndroid Build Coastguard Worker /// The depth, in the dependence graph, for a node.
getDepth(SUnit * Node)284*9880d681SAndroid Build Coastguard Worker int getDepth(SUnit *Node) { return Node->getDepth(); }
285*9880d681SAndroid Build Coastguard Worker
286*9880d681SAndroid Build Coastguard Worker /// The height, in the dependence graph, for a node.
getHeight(SUnit * Node)287*9880d681SAndroid Build Coastguard Worker int getHeight(SUnit *Node) { return Node->getHeight(); }
288*9880d681SAndroid Build Coastguard Worker
289*9880d681SAndroid Build Coastguard Worker /// Return true if the dependence is a back-edge in the data dependence graph.
290*9880d681SAndroid Build Coastguard Worker /// Since the DAG doesn't contain cycles, we represent a cycle in the graph
291*9880d681SAndroid Build Coastguard Worker /// using an anti dependence from a Phi to an instruction.
isBackedge(SUnit * Source,const SDep & Dep)292*9880d681SAndroid Build Coastguard Worker bool isBackedge(SUnit *Source, const SDep &Dep) {
293*9880d681SAndroid Build Coastguard Worker if (Dep.getKind() != SDep::Anti)
294*9880d681SAndroid Build Coastguard Worker return false;
295*9880d681SAndroid Build Coastguard Worker return Source->getInstr()->isPHI() || Dep.getSUnit()->getInstr()->isPHI();
296*9880d681SAndroid Build Coastguard Worker }
297*9880d681SAndroid Build Coastguard Worker
298*9880d681SAndroid Build Coastguard Worker /// Return true if the dependence is an order dependence between non-Phis.
isOrder(SUnit * Source,const SDep & Dep)299*9880d681SAndroid Build Coastguard Worker static bool isOrder(SUnit *Source, const SDep &Dep) {
300*9880d681SAndroid Build Coastguard Worker if (Dep.getKind() != SDep::Order)
301*9880d681SAndroid Build Coastguard Worker return false;
302*9880d681SAndroid Build Coastguard Worker return (!Source->getInstr()->isPHI() &&
303*9880d681SAndroid Build Coastguard Worker !Dep.getSUnit()->getInstr()->isPHI());
304*9880d681SAndroid Build Coastguard Worker }
305*9880d681SAndroid Build Coastguard Worker
306*9880d681SAndroid Build Coastguard Worker bool isLoopCarriedOrder(SUnit *Source, const SDep &Dep, bool isSucc = true);
307*9880d681SAndroid Build Coastguard Worker
308*9880d681SAndroid Build Coastguard Worker /// The latency of the dependence.
getLatency(SUnit * Source,const SDep & Dep)309*9880d681SAndroid Build Coastguard Worker unsigned getLatency(SUnit *Source, const SDep &Dep) {
310*9880d681SAndroid Build Coastguard Worker // Anti dependences represent recurrences, so use the latency of the
311*9880d681SAndroid Build Coastguard Worker // instruction on the back-edge.
312*9880d681SAndroid Build Coastguard Worker if (Dep.getKind() == SDep::Anti) {
313*9880d681SAndroid Build Coastguard Worker if (Source->getInstr()->isPHI())
314*9880d681SAndroid Build Coastguard Worker return Dep.getSUnit()->Latency;
315*9880d681SAndroid Build Coastguard Worker if (Dep.getSUnit()->getInstr()->isPHI())
316*9880d681SAndroid Build Coastguard Worker return Source->Latency;
317*9880d681SAndroid Build Coastguard Worker return Dep.getLatency();
318*9880d681SAndroid Build Coastguard Worker }
319*9880d681SAndroid Build Coastguard Worker return Dep.getLatency();
320*9880d681SAndroid Build Coastguard Worker }
321*9880d681SAndroid Build Coastguard Worker
322*9880d681SAndroid Build Coastguard Worker /// The distance function, which indicates that operation V of iteration I
323*9880d681SAndroid Build Coastguard Worker /// depends on operations U of iteration I-distance.
getDistance(SUnit * U,SUnit * V,const SDep & Dep)324*9880d681SAndroid Build Coastguard Worker unsigned getDistance(SUnit *U, SUnit *V, const SDep &Dep) {
325*9880d681SAndroid Build Coastguard Worker // Instructions that feed a Phi have a distance of 1. Computing larger
326*9880d681SAndroid Build Coastguard Worker // values for arrays requires data dependence information.
327*9880d681SAndroid Build Coastguard Worker if (V->getInstr()->isPHI() && Dep.getKind() == SDep::Anti)
328*9880d681SAndroid Build Coastguard Worker return 1;
329*9880d681SAndroid Build Coastguard Worker return 0;
330*9880d681SAndroid Build Coastguard Worker }
331*9880d681SAndroid Build Coastguard Worker
332*9880d681SAndroid Build Coastguard Worker /// Set the Minimum Initiation Interval for this schedule attempt.
setMII(unsigned mii)333*9880d681SAndroid Build Coastguard Worker void setMII(unsigned mii) { MII = mii; }
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker MachineInstr *applyInstrChange(MachineInstr *MI, SMSchedule &Schedule,
336*9880d681SAndroid Build Coastguard Worker bool UpdateDAG = false);
337*9880d681SAndroid Build Coastguard Worker
338*9880d681SAndroid Build Coastguard Worker /// Return the new base register that was stored away for the changed
339*9880d681SAndroid Build Coastguard Worker /// instruction.
getInstrBaseReg(SUnit * SU)340*9880d681SAndroid Build Coastguard Worker unsigned getInstrBaseReg(SUnit *SU) {
341*9880d681SAndroid Build Coastguard Worker DenseMap<SUnit *, std::pair<unsigned, int64_t>>::iterator It =
342*9880d681SAndroid Build Coastguard Worker InstrChanges.find(SU);
343*9880d681SAndroid Build Coastguard Worker if (It != InstrChanges.end())
344*9880d681SAndroid Build Coastguard Worker return It->second.first;
345*9880d681SAndroid Build Coastguard Worker return 0;
346*9880d681SAndroid Build Coastguard Worker }
347*9880d681SAndroid Build Coastguard Worker
348*9880d681SAndroid Build Coastguard Worker private:
349*9880d681SAndroid Build Coastguard Worker void addLoopCarriedDependences(AliasAnalysis *AA);
350*9880d681SAndroid Build Coastguard Worker void updatePhiDependences();
351*9880d681SAndroid Build Coastguard Worker void changeDependences();
352*9880d681SAndroid Build Coastguard Worker unsigned calculateResMII();
353*9880d681SAndroid Build Coastguard Worker unsigned calculateRecMII(NodeSetType &RecNodeSets);
354*9880d681SAndroid Build Coastguard Worker void findCircuits(NodeSetType &NodeSets);
355*9880d681SAndroid Build Coastguard Worker void fuseRecs(NodeSetType &NodeSets);
356*9880d681SAndroid Build Coastguard Worker void removeDuplicateNodes(NodeSetType &NodeSets);
357*9880d681SAndroid Build Coastguard Worker void computeNodeFunctions(NodeSetType &NodeSets);
358*9880d681SAndroid Build Coastguard Worker void registerPressureFilter(NodeSetType &NodeSets);
359*9880d681SAndroid Build Coastguard Worker void colocateNodeSets(NodeSetType &NodeSets);
360*9880d681SAndroid Build Coastguard Worker void checkNodeSets(NodeSetType &NodeSets);
361*9880d681SAndroid Build Coastguard Worker void groupRemainingNodes(NodeSetType &NodeSets);
362*9880d681SAndroid Build Coastguard Worker void addConnectedNodes(SUnit *SU, NodeSet &NewSet,
363*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> &NodesAdded);
364*9880d681SAndroid Build Coastguard Worker void computeNodeOrder(NodeSetType &NodeSets);
365*9880d681SAndroid Build Coastguard Worker bool schedulePipeline(SMSchedule &Schedule);
366*9880d681SAndroid Build Coastguard Worker void generatePipelinedLoop(SMSchedule &Schedule);
367*9880d681SAndroid Build Coastguard Worker void generateProlog(SMSchedule &Schedule, unsigned LastStage,
368*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB, ValueMapTy *VRMap,
369*9880d681SAndroid Build Coastguard Worker MBBVectorTy &PrologBBs);
370*9880d681SAndroid Build Coastguard Worker void generateEpilog(SMSchedule &Schedule, unsigned LastStage,
371*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB, ValueMapTy *VRMap,
372*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs, MBBVectorTy &PrologBBs);
373*9880d681SAndroid Build Coastguard Worker void generateExistingPhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1,
374*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB2, MachineBasicBlock *KernelBB,
375*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule, ValueMapTy *VRMap,
376*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap, unsigned LastStageNum,
377*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum, bool IsLast);
378*9880d681SAndroid Build Coastguard Worker void generatePhis(MachineBasicBlock *NewBB, MachineBasicBlock *BB1,
379*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB2, MachineBasicBlock *KernelBB,
380*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule, ValueMapTy *VRMap,
381*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap, unsigned LastStageNum,
382*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum, bool IsLast);
383*9880d681SAndroid Build Coastguard Worker void removeDeadInstructions(MachineBasicBlock *KernelBB,
384*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs);
385*9880d681SAndroid Build Coastguard Worker void splitLifetimes(MachineBasicBlock *KernelBB, MBBVectorTy &EpilogBBs,
386*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule);
387*9880d681SAndroid Build Coastguard Worker void addBranches(MBBVectorTy &PrologBBs, MachineBasicBlock *KernelBB,
388*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs, SMSchedule &Schedule,
389*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap);
390*9880d681SAndroid Build Coastguard Worker bool computeDelta(MachineInstr &MI, unsigned &Delta);
391*9880d681SAndroid Build Coastguard Worker void updateMemOperands(MachineInstr &NewMI, MachineInstr &OldMI,
392*9880d681SAndroid Build Coastguard Worker unsigned Num);
393*9880d681SAndroid Build Coastguard Worker MachineInstr *cloneInstr(MachineInstr *OldMI, unsigned CurStageNum,
394*9880d681SAndroid Build Coastguard Worker unsigned InstStageNum);
395*9880d681SAndroid Build Coastguard Worker MachineInstr *cloneAndChangeInstr(MachineInstr *OldMI, unsigned CurStageNum,
396*9880d681SAndroid Build Coastguard Worker unsigned InstStageNum,
397*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule);
398*9880d681SAndroid Build Coastguard Worker void updateInstruction(MachineInstr *NewMI, bool LastDef,
399*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum, unsigned InstStageNum,
400*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule, ValueMapTy *VRMap);
401*9880d681SAndroid Build Coastguard Worker MachineInstr *findDefInLoop(unsigned Reg);
402*9880d681SAndroid Build Coastguard Worker unsigned getPrevMapVal(unsigned StageNum, unsigned PhiStage, unsigned LoopVal,
403*9880d681SAndroid Build Coastguard Worker unsigned LoopStage, ValueMapTy *VRMap,
404*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB);
405*9880d681SAndroid Build Coastguard Worker void rewritePhiValues(MachineBasicBlock *NewBB, unsigned StageNum,
406*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule, ValueMapTy *VRMap,
407*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap);
408*9880d681SAndroid Build Coastguard Worker void rewriteScheduledInstr(MachineBasicBlock *BB, SMSchedule &Schedule,
409*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap, unsigned CurStageNum,
410*9880d681SAndroid Build Coastguard Worker unsigned PhiNum, MachineInstr *Phi,
411*9880d681SAndroid Build Coastguard Worker unsigned OldReg, unsigned NewReg,
412*9880d681SAndroid Build Coastguard Worker unsigned PrevReg = 0);
413*9880d681SAndroid Build Coastguard Worker bool canUseLastOffsetValue(MachineInstr *MI, unsigned &BasePos,
414*9880d681SAndroid Build Coastguard Worker unsigned &OffsetPos, unsigned &NewBase,
415*9880d681SAndroid Build Coastguard Worker int64_t &NewOffset);
416*9880d681SAndroid Build Coastguard Worker };
417*9880d681SAndroid Build Coastguard Worker
418*9880d681SAndroid Build Coastguard Worker /// A NodeSet contains a set of SUnit DAG nodes with additional information
419*9880d681SAndroid Build Coastguard Worker /// that assigns a priority to the set.
420*9880d681SAndroid Build Coastguard Worker class NodeSet {
421*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> Nodes;
422*9880d681SAndroid Build Coastguard Worker bool HasRecurrence;
423*9880d681SAndroid Build Coastguard Worker unsigned RecMII = 0;
424*9880d681SAndroid Build Coastguard Worker int MaxMOV = 0;
425*9880d681SAndroid Build Coastguard Worker int MaxDepth = 0;
426*9880d681SAndroid Build Coastguard Worker unsigned Colocate = 0;
427*9880d681SAndroid Build Coastguard Worker SUnit *ExceedPressure = nullptr;
428*9880d681SAndroid Build Coastguard Worker
429*9880d681SAndroid Build Coastguard Worker public:
430*9880d681SAndroid Build Coastguard Worker typedef SetVector<SUnit *>::const_iterator iterator;
431*9880d681SAndroid Build Coastguard Worker
NodeSet()432*9880d681SAndroid Build Coastguard Worker NodeSet() : Nodes(), HasRecurrence(false) {}
433*9880d681SAndroid Build Coastguard Worker
NodeSet(iterator S,iterator E)434*9880d681SAndroid Build Coastguard Worker NodeSet(iterator S, iterator E) : Nodes(S, E), HasRecurrence(true) {}
435*9880d681SAndroid Build Coastguard Worker
insert(SUnit * SU)436*9880d681SAndroid Build Coastguard Worker bool insert(SUnit *SU) { return Nodes.insert(SU); }
437*9880d681SAndroid Build Coastguard Worker
insert(iterator S,iterator E)438*9880d681SAndroid Build Coastguard Worker void insert(iterator S, iterator E) { Nodes.insert(S, E); }
439*9880d681SAndroid Build Coastguard Worker
remove_if(UnaryPredicate P)440*9880d681SAndroid Build Coastguard Worker template <typename UnaryPredicate> bool remove_if(UnaryPredicate P) {
441*9880d681SAndroid Build Coastguard Worker return Nodes.remove_if(P);
442*9880d681SAndroid Build Coastguard Worker }
443*9880d681SAndroid Build Coastguard Worker
count(SUnit * SU) const444*9880d681SAndroid Build Coastguard Worker unsigned count(SUnit *SU) const { return Nodes.count(SU); }
445*9880d681SAndroid Build Coastguard Worker
hasRecurrence()446*9880d681SAndroid Build Coastguard Worker bool hasRecurrence() { return HasRecurrence; };
447*9880d681SAndroid Build Coastguard Worker
size() const448*9880d681SAndroid Build Coastguard Worker unsigned size() const { return Nodes.size(); }
449*9880d681SAndroid Build Coastguard Worker
empty() const450*9880d681SAndroid Build Coastguard Worker bool empty() const { return Nodes.empty(); }
451*9880d681SAndroid Build Coastguard Worker
getNode(unsigned i) const452*9880d681SAndroid Build Coastguard Worker SUnit *getNode(unsigned i) const { return Nodes[i]; };
453*9880d681SAndroid Build Coastguard Worker
setRecMII(unsigned mii)454*9880d681SAndroid Build Coastguard Worker void setRecMII(unsigned mii) { RecMII = mii; };
455*9880d681SAndroid Build Coastguard Worker
setColocate(unsigned c)456*9880d681SAndroid Build Coastguard Worker void setColocate(unsigned c) { Colocate = c; };
457*9880d681SAndroid Build Coastguard Worker
setExceedPressure(SUnit * SU)458*9880d681SAndroid Build Coastguard Worker void setExceedPressure(SUnit *SU) { ExceedPressure = SU; }
459*9880d681SAndroid Build Coastguard Worker
isExceedSU(SUnit * SU)460*9880d681SAndroid Build Coastguard Worker bool isExceedSU(SUnit *SU) { return ExceedPressure == SU; }
461*9880d681SAndroid Build Coastguard Worker
compareRecMII(NodeSet & RHS)462*9880d681SAndroid Build Coastguard Worker int compareRecMII(NodeSet &RHS) { return RecMII - RHS.RecMII; }
463*9880d681SAndroid Build Coastguard Worker
getRecMII()464*9880d681SAndroid Build Coastguard Worker int getRecMII() { return RecMII; }
465*9880d681SAndroid Build Coastguard Worker
466*9880d681SAndroid Build Coastguard Worker /// Summarize node functions for the entire node set.
computeNodeSetInfo(SwingSchedulerDAG * SSD)467*9880d681SAndroid Build Coastguard Worker void computeNodeSetInfo(SwingSchedulerDAG *SSD) {
468*9880d681SAndroid Build Coastguard Worker for (SUnit *SU : *this) {
469*9880d681SAndroid Build Coastguard Worker MaxMOV = std::max(MaxMOV, SSD->getMOV(SU));
470*9880d681SAndroid Build Coastguard Worker MaxDepth = std::max(MaxDepth, SSD->getDepth(SU));
471*9880d681SAndroid Build Coastguard Worker }
472*9880d681SAndroid Build Coastguard Worker }
473*9880d681SAndroid Build Coastguard Worker
clear()474*9880d681SAndroid Build Coastguard Worker void clear() {
475*9880d681SAndroid Build Coastguard Worker Nodes.clear();
476*9880d681SAndroid Build Coastguard Worker RecMII = 0;
477*9880d681SAndroid Build Coastguard Worker HasRecurrence = false;
478*9880d681SAndroid Build Coastguard Worker MaxMOV = 0;
479*9880d681SAndroid Build Coastguard Worker MaxDepth = 0;
480*9880d681SAndroid Build Coastguard Worker Colocate = 0;
481*9880d681SAndroid Build Coastguard Worker ExceedPressure = nullptr;
482*9880d681SAndroid Build Coastguard Worker }
483*9880d681SAndroid Build Coastguard Worker
operator SetVector<SUnit*>&()484*9880d681SAndroid Build Coastguard Worker operator SetVector<SUnit *> &() { return Nodes; }
485*9880d681SAndroid Build Coastguard Worker
486*9880d681SAndroid Build Coastguard Worker /// Sort the node sets by importance. First, rank them by recurrence MII,
487*9880d681SAndroid Build Coastguard Worker /// then by mobility (least mobile done first), and finally by depth.
488*9880d681SAndroid Build Coastguard Worker /// Each node set may contain a colocate value which is used as the first
489*9880d681SAndroid Build Coastguard Worker /// tie breaker, if it's set.
operator >(const NodeSet & RHS) const490*9880d681SAndroid Build Coastguard Worker bool operator>(const NodeSet &RHS) const {
491*9880d681SAndroid Build Coastguard Worker if (RecMII == RHS.RecMII) {
492*9880d681SAndroid Build Coastguard Worker if (Colocate != 0 && RHS.Colocate != 0 && Colocate != RHS.Colocate)
493*9880d681SAndroid Build Coastguard Worker return Colocate < RHS.Colocate;
494*9880d681SAndroid Build Coastguard Worker if (MaxMOV == RHS.MaxMOV)
495*9880d681SAndroid Build Coastguard Worker return MaxDepth > RHS.MaxDepth;
496*9880d681SAndroid Build Coastguard Worker return MaxMOV < RHS.MaxMOV;
497*9880d681SAndroid Build Coastguard Worker }
498*9880d681SAndroid Build Coastguard Worker return RecMII > RHS.RecMII;
499*9880d681SAndroid Build Coastguard Worker }
500*9880d681SAndroid Build Coastguard Worker
operator ==(const NodeSet & RHS) const501*9880d681SAndroid Build Coastguard Worker bool operator==(const NodeSet &RHS) const {
502*9880d681SAndroid Build Coastguard Worker return RecMII == RHS.RecMII && MaxMOV == RHS.MaxMOV &&
503*9880d681SAndroid Build Coastguard Worker MaxDepth == RHS.MaxDepth;
504*9880d681SAndroid Build Coastguard Worker }
505*9880d681SAndroid Build Coastguard Worker
operator !=(const NodeSet & RHS) const506*9880d681SAndroid Build Coastguard Worker bool operator!=(const NodeSet &RHS) const { return !operator==(RHS); }
507*9880d681SAndroid Build Coastguard Worker
begin()508*9880d681SAndroid Build Coastguard Worker iterator begin() { return Nodes.begin(); }
end()509*9880d681SAndroid Build Coastguard Worker iterator end() { return Nodes.end(); }
510*9880d681SAndroid Build Coastguard Worker
print(raw_ostream & os) const511*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &os) const {
512*9880d681SAndroid Build Coastguard Worker os << "Num nodes " << size() << " rec " << RecMII << " mov " << MaxMOV
513*9880d681SAndroid Build Coastguard Worker << " depth " << MaxDepth << " col " << Colocate << "\n";
514*9880d681SAndroid Build Coastguard Worker for (const auto &I : Nodes)
515*9880d681SAndroid Build Coastguard Worker os << " SU(" << I->NodeNum << ") " << *(I->getInstr());
516*9880d681SAndroid Build Coastguard Worker os << "\n";
517*9880d681SAndroid Build Coastguard Worker }
518*9880d681SAndroid Build Coastguard Worker
dump() const519*9880d681SAndroid Build Coastguard Worker void dump() const { print(dbgs()); }
520*9880d681SAndroid Build Coastguard Worker };
521*9880d681SAndroid Build Coastguard Worker
522*9880d681SAndroid Build Coastguard Worker /// This class repesents the scheduled code. The main data structure is a
523*9880d681SAndroid Build Coastguard Worker /// map from scheduled cycle to instructions. During scheduling, the
524*9880d681SAndroid Build Coastguard Worker /// data structure explicitly represents all stages/iterations. When
525*9880d681SAndroid Build Coastguard Worker /// the algorithm finshes, the schedule is collapsed into a single stage,
526*9880d681SAndroid Build Coastguard Worker /// which represents instructions from different loop iterations.
527*9880d681SAndroid Build Coastguard Worker ///
528*9880d681SAndroid Build Coastguard Worker /// The SMS algorithm allows negative values for cycles, so the first cycle
529*9880d681SAndroid Build Coastguard Worker /// in the schedule is the smallest cycle value.
530*9880d681SAndroid Build Coastguard Worker class SMSchedule {
531*9880d681SAndroid Build Coastguard Worker private:
532*9880d681SAndroid Build Coastguard Worker /// Map from execution cycle to instructions.
533*9880d681SAndroid Build Coastguard Worker DenseMap<int, std::deque<SUnit *>> ScheduledInstrs;
534*9880d681SAndroid Build Coastguard Worker
535*9880d681SAndroid Build Coastguard Worker /// Map from instruction to execution cycle.
536*9880d681SAndroid Build Coastguard Worker std::map<SUnit *, int> InstrToCycle;
537*9880d681SAndroid Build Coastguard Worker
538*9880d681SAndroid Build Coastguard Worker /// Map for each register and the max difference between its uses and def.
539*9880d681SAndroid Build Coastguard Worker /// The first element in the pair is the max difference in stages. The
540*9880d681SAndroid Build Coastguard Worker /// second is true if the register defines a Phi value and loop value is
541*9880d681SAndroid Build Coastguard Worker /// scheduled before the Phi.
542*9880d681SAndroid Build Coastguard Worker std::map<unsigned, std::pair<unsigned, bool>> RegToStageDiff;
543*9880d681SAndroid Build Coastguard Worker
544*9880d681SAndroid Build Coastguard Worker /// Keep track of the first cycle value in the schedule. It starts
545*9880d681SAndroid Build Coastguard Worker /// as zero, but the algorithm allows negative values.
546*9880d681SAndroid Build Coastguard Worker int FirstCycle;
547*9880d681SAndroid Build Coastguard Worker
548*9880d681SAndroid Build Coastguard Worker /// Keep track of the last cycle value in the schedule.
549*9880d681SAndroid Build Coastguard Worker int LastCycle;
550*9880d681SAndroid Build Coastguard Worker
551*9880d681SAndroid Build Coastguard Worker /// The initiation interval (II) for the schedule.
552*9880d681SAndroid Build Coastguard Worker int InitiationInterval;
553*9880d681SAndroid Build Coastguard Worker
554*9880d681SAndroid Build Coastguard Worker /// Target machine information.
555*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &ST;
556*9880d681SAndroid Build Coastguard Worker
557*9880d681SAndroid Build Coastguard Worker /// Virtual register information.
558*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI;
559*9880d681SAndroid Build Coastguard Worker
560*9880d681SAndroid Build Coastguard Worker DFAPacketizer *Resources;
561*9880d681SAndroid Build Coastguard Worker
562*9880d681SAndroid Build Coastguard Worker public:
SMSchedule(MachineFunction * mf)563*9880d681SAndroid Build Coastguard Worker SMSchedule(MachineFunction *mf)
564*9880d681SAndroid Build Coastguard Worker : ST(mf->getSubtarget()), MRI(mf->getRegInfo()),
565*9880d681SAndroid Build Coastguard Worker Resources(ST.getInstrInfo()->CreateTargetScheduleState(ST)) {
566*9880d681SAndroid Build Coastguard Worker FirstCycle = 0;
567*9880d681SAndroid Build Coastguard Worker LastCycle = 0;
568*9880d681SAndroid Build Coastguard Worker InitiationInterval = 0;
569*9880d681SAndroid Build Coastguard Worker }
570*9880d681SAndroid Build Coastguard Worker
~SMSchedule()571*9880d681SAndroid Build Coastguard Worker ~SMSchedule() {
572*9880d681SAndroid Build Coastguard Worker ScheduledInstrs.clear();
573*9880d681SAndroid Build Coastguard Worker InstrToCycle.clear();
574*9880d681SAndroid Build Coastguard Worker RegToStageDiff.clear();
575*9880d681SAndroid Build Coastguard Worker delete Resources;
576*9880d681SAndroid Build Coastguard Worker }
577*9880d681SAndroid Build Coastguard Worker
reset()578*9880d681SAndroid Build Coastguard Worker void reset() {
579*9880d681SAndroid Build Coastguard Worker ScheduledInstrs.clear();
580*9880d681SAndroid Build Coastguard Worker InstrToCycle.clear();
581*9880d681SAndroid Build Coastguard Worker RegToStageDiff.clear();
582*9880d681SAndroid Build Coastguard Worker FirstCycle = 0;
583*9880d681SAndroid Build Coastguard Worker LastCycle = 0;
584*9880d681SAndroid Build Coastguard Worker InitiationInterval = 0;
585*9880d681SAndroid Build Coastguard Worker }
586*9880d681SAndroid Build Coastguard Worker
587*9880d681SAndroid Build Coastguard Worker /// Set the initiation interval for this schedule.
setInitiationInterval(int ii)588*9880d681SAndroid Build Coastguard Worker void setInitiationInterval(int ii) { InitiationInterval = ii; }
589*9880d681SAndroid Build Coastguard Worker
590*9880d681SAndroid Build Coastguard Worker /// Return the first cycle in the completed schedule. This
591*9880d681SAndroid Build Coastguard Worker /// can be a negative value.
getFirstCycle() const592*9880d681SAndroid Build Coastguard Worker int getFirstCycle() const { return FirstCycle; }
593*9880d681SAndroid Build Coastguard Worker
594*9880d681SAndroid Build Coastguard Worker /// Return the last cycle in the finalized schedule.
getFinalCycle() const595*9880d681SAndroid Build Coastguard Worker int getFinalCycle() const { return FirstCycle + InitiationInterval - 1; }
596*9880d681SAndroid Build Coastguard Worker
597*9880d681SAndroid Build Coastguard Worker /// Return the cycle of the earliest scheduled instruction in the dependence
598*9880d681SAndroid Build Coastguard Worker /// chain.
599*9880d681SAndroid Build Coastguard Worker int earliestCycleInChain(const SDep &Dep);
600*9880d681SAndroid Build Coastguard Worker
601*9880d681SAndroid Build Coastguard Worker /// Return the cycle of the latest scheduled instruction in the dependence
602*9880d681SAndroid Build Coastguard Worker /// chain.
603*9880d681SAndroid Build Coastguard Worker int latestCycleInChain(const SDep &Dep);
604*9880d681SAndroid Build Coastguard Worker
605*9880d681SAndroid Build Coastguard Worker void computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart,
606*9880d681SAndroid Build Coastguard Worker int *MinEnd, int *MaxStart, int II, SwingSchedulerDAG *DAG);
607*9880d681SAndroid Build Coastguard Worker bool insert(SUnit *SU, int StartCycle, int EndCycle, int II);
608*9880d681SAndroid Build Coastguard Worker
609*9880d681SAndroid Build Coastguard Worker /// Iterators for the cycle to instruction map.
610*9880d681SAndroid Build Coastguard Worker typedef DenseMap<int, std::deque<SUnit *>>::iterator sched_iterator;
611*9880d681SAndroid Build Coastguard Worker typedef DenseMap<int, std::deque<SUnit *>>::const_iterator
612*9880d681SAndroid Build Coastguard Worker const_sched_iterator;
613*9880d681SAndroid Build Coastguard Worker
614*9880d681SAndroid Build Coastguard Worker /// Return true if the instruction is scheduled at the specified stage.
isScheduledAtStage(SUnit * SU,unsigned StageNum)615*9880d681SAndroid Build Coastguard Worker bool isScheduledAtStage(SUnit *SU, unsigned StageNum) {
616*9880d681SAndroid Build Coastguard Worker return (stageScheduled(SU) == (int)StageNum);
617*9880d681SAndroid Build Coastguard Worker }
618*9880d681SAndroid Build Coastguard Worker
619*9880d681SAndroid Build Coastguard Worker /// Return the stage for a scheduled instruction. Return -1 if
620*9880d681SAndroid Build Coastguard Worker /// the instruction has not been scheduled.
stageScheduled(SUnit * SU) const621*9880d681SAndroid Build Coastguard Worker int stageScheduled(SUnit *SU) const {
622*9880d681SAndroid Build Coastguard Worker std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
623*9880d681SAndroid Build Coastguard Worker if (it == InstrToCycle.end())
624*9880d681SAndroid Build Coastguard Worker return -1;
625*9880d681SAndroid Build Coastguard Worker return (it->second - FirstCycle) / InitiationInterval;
626*9880d681SAndroid Build Coastguard Worker }
627*9880d681SAndroid Build Coastguard Worker
628*9880d681SAndroid Build Coastguard Worker /// Return the cycle for a scheduled instruction. This function normalizes
629*9880d681SAndroid Build Coastguard Worker /// the first cycle to be 0.
cycleScheduled(SUnit * SU) const630*9880d681SAndroid Build Coastguard Worker unsigned cycleScheduled(SUnit *SU) const {
631*9880d681SAndroid Build Coastguard Worker std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SU);
632*9880d681SAndroid Build Coastguard Worker assert(it != InstrToCycle.end() && "Instruction hasn't been scheduled.");
633*9880d681SAndroid Build Coastguard Worker return (it->second - FirstCycle) % InitiationInterval;
634*9880d681SAndroid Build Coastguard Worker }
635*9880d681SAndroid Build Coastguard Worker
636*9880d681SAndroid Build Coastguard Worker /// Return the maximum stage count needed for this schedule.
getMaxStageCount()637*9880d681SAndroid Build Coastguard Worker unsigned getMaxStageCount() {
638*9880d681SAndroid Build Coastguard Worker return (LastCycle - FirstCycle) / InitiationInterval;
639*9880d681SAndroid Build Coastguard Worker }
640*9880d681SAndroid Build Coastguard Worker
641*9880d681SAndroid Build Coastguard Worker /// Return the max. number of stages/iterations that can occur between a
642*9880d681SAndroid Build Coastguard Worker /// register definition and its uses.
getStagesForReg(int Reg,unsigned CurStage)643*9880d681SAndroid Build Coastguard Worker unsigned getStagesForReg(int Reg, unsigned CurStage) {
644*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, bool> Stages = RegToStageDiff[Reg];
645*9880d681SAndroid Build Coastguard Worker if (CurStage > getMaxStageCount() && Stages.first == 0 && Stages.second)
646*9880d681SAndroid Build Coastguard Worker return 1;
647*9880d681SAndroid Build Coastguard Worker return Stages.first;
648*9880d681SAndroid Build Coastguard Worker }
649*9880d681SAndroid Build Coastguard Worker
650*9880d681SAndroid Build Coastguard Worker /// The number of stages for a Phi is a little different than other
651*9880d681SAndroid Build Coastguard Worker /// instructions. The minimum value computed in RegToStageDiff is 1
652*9880d681SAndroid Build Coastguard Worker /// because we assume the Phi is needed for at least 1 iteration.
653*9880d681SAndroid Build Coastguard Worker /// This is not the case if the loop value is scheduled prior to the
654*9880d681SAndroid Build Coastguard Worker /// Phi in the same stage. This function returns the number of stages
655*9880d681SAndroid Build Coastguard Worker /// or iterations needed between the Phi definition and any uses.
getStagesForPhi(int Reg)656*9880d681SAndroid Build Coastguard Worker unsigned getStagesForPhi(int Reg) {
657*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, bool> Stages = RegToStageDiff[Reg];
658*9880d681SAndroid Build Coastguard Worker if (Stages.second)
659*9880d681SAndroid Build Coastguard Worker return Stages.first;
660*9880d681SAndroid Build Coastguard Worker return Stages.first - 1;
661*9880d681SAndroid Build Coastguard Worker }
662*9880d681SAndroid Build Coastguard Worker
663*9880d681SAndroid Build Coastguard Worker /// Return the instructions that are scheduled at the specified cycle.
getInstructions(int cycle)664*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &getInstructions(int cycle) {
665*9880d681SAndroid Build Coastguard Worker return ScheduledInstrs[cycle];
666*9880d681SAndroid Build Coastguard Worker }
667*9880d681SAndroid Build Coastguard Worker
668*9880d681SAndroid Build Coastguard Worker bool isValidSchedule(SwingSchedulerDAG *SSD);
669*9880d681SAndroid Build Coastguard Worker void finalizeSchedule(SwingSchedulerDAG *SSD);
670*9880d681SAndroid Build Coastguard Worker bool orderDependence(SwingSchedulerDAG *SSD, SUnit *SU,
671*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &Insts);
672*9880d681SAndroid Build Coastguard Worker bool isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi);
673*9880d681SAndroid Build Coastguard Worker bool isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD, MachineInstr *Inst,
674*9880d681SAndroid Build Coastguard Worker MachineOperand &MO);
675*9880d681SAndroid Build Coastguard Worker void print(raw_ostream &os) const;
676*9880d681SAndroid Build Coastguard Worker void dump() const;
677*9880d681SAndroid Build Coastguard Worker };
678*9880d681SAndroid Build Coastguard Worker
679*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
680*9880d681SAndroid Build Coastguard Worker
681*9880d681SAndroid Build Coastguard Worker unsigned SwingSchedulerDAG::Circuits::MaxPaths = 5;
682*9880d681SAndroid Build Coastguard Worker char MachinePipeliner::ID = 0;
683*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
684*9880d681SAndroid Build Coastguard Worker int MachinePipeliner::NumTries = 0;
685*9880d681SAndroid Build Coastguard Worker #endif
686*9880d681SAndroid Build Coastguard Worker char &llvm::MachinePipelinerID = MachinePipeliner::ID;
687*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(MachinePipeliner, "pipeliner",
688*9880d681SAndroid Build Coastguard Worker "Modulo Software Pipelining", false, false)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)689*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
690*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
691*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
692*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
693*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(MachinePipeliner, "pipeliner",
694*9880d681SAndroid Build Coastguard Worker "Modulo Software Pipelining", false, false)
695*9880d681SAndroid Build Coastguard Worker
696*9880d681SAndroid Build Coastguard Worker /// The "main" function for implementing Swing Modulo Scheduling.
697*9880d681SAndroid Build Coastguard Worker bool MachinePipeliner::runOnMachineFunction(MachineFunction &mf) {
698*9880d681SAndroid Build Coastguard Worker if (skipFunction(*mf.getFunction()))
699*9880d681SAndroid Build Coastguard Worker return false;
700*9880d681SAndroid Build Coastguard Worker
701*9880d681SAndroid Build Coastguard Worker if (!EnableSWP)
702*9880d681SAndroid Build Coastguard Worker return false;
703*9880d681SAndroid Build Coastguard Worker
704*9880d681SAndroid Build Coastguard Worker if (mf.getFunction()->getAttributes().hasAttribute(
705*9880d681SAndroid Build Coastguard Worker AttributeSet::FunctionIndex, Attribute::OptimizeForSize) &&
706*9880d681SAndroid Build Coastguard Worker !EnableSWPOptSize.getPosition())
707*9880d681SAndroid Build Coastguard Worker return false;
708*9880d681SAndroid Build Coastguard Worker
709*9880d681SAndroid Build Coastguard Worker MF = &mf;
710*9880d681SAndroid Build Coastguard Worker MLI = &getAnalysis<MachineLoopInfo>();
711*9880d681SAndroid Build Coastguard Worker MDT = &getAnalysis<MachineDominatorTree>();
712*9880d681SAndroid Build Coastguard Worker TII = MF->getSubtarget().getInstrInfo();
713*9880d681SAndroid Build Coastguard Worker RegClassInfo.runOnMachineFunction(*MF);
714*9880d681SAndroid Build Coastguard Worker
715*9880d681SAndroid Build Coastguard Worker for (auto &L : *MLI)
716*9880d681SAndroid Build Coastguard Worker scheduleLoop(*L);
717*9880d681SAndroid Build Coastguard Worker
718*9880d681SAndroid Build Coastguard Worker return false;
719*9880d681SAndroid Build Coastguard Worker }
720*9880d681SAndroid Build Coastguard Worker
721*9880d681SAndroid Build Coastguard Worker /// Attempt to perform the SMS algorithm on the specified loop. This function is
722*9880d681SAndroid Build Coastguard Worker /// the main entry point for the algorithm. The function identifies candidate
723*9880d681SAndroid Build Coastguard Worker /// loops, calculates the minimum initiation interval, and attempts to schedule
724*9880d681SAndroid Build Coastguard Worker /// the loop.
scheduleLoop(MachineLoop & L)725*9880d681SAndroid Build Coastguard Worker bool MachinePipeliner::scheduleLoop(MachineLoop &L) {
726*9880d681SAndroid Build Coastguard Worker bool Changed = false;
727*9880d681SAndroid Build Coastguard Worker for (auto &InnerLoop : L)
728*9880d681SAndroid Build Coastguard Worker Changed |= scheduleLoop(*InnerLoop);
729*9880d681SAndroid Build Coastguard Worker
730*9880d681SAndroid Build Coastguard Worker #ifndef NDEBUG
731*9880d681SAndroid Build Coastguard Worker // Stop trying after reaching the limit (if any).
732*9880d681SAndroid Build Coastguard Worker int Limit = SwpLoopLimit;
733*9880d681SAndroid Build Coastguard Worker if (Limit >= 0) {
734*9880d681SAndroid Build Coastguard Worker if (NumTries >= SwpLoopLimit)
735*9880d681SAndroid Build Coastguard Worker return Changed;
736*9880d681SAndroid Build Coastguard Worker NumTries++;
737*9880d681SAndroid Build Coastguard Worker }
738*9880d681SAndroid Build Coastguard Worker #endif
739*9880d681SAndroid Build Coastguard Worker
740*9880d681SAndroid Build Coastguard Worker if (!canPipelineLoop(L))
741*9880d681SAndroid Build Coastguard Worker return Changed;
742*9880d681SAndroid Build Coastguard Worker
743*9880d681SAndroid Build Coastguard Worker ++NumTrytoPipeline;
744*9880d681SAndroid Build Coastguard Worker
745*9880d681SAndroid Build Coastguard Worker Changed = swingModuloScheduler(L);
746*9880d681SAndroid Build Coastguard Worker
747*9880d681SAndroid Build Coastguard Worker return Changed;
748*9880d681SAndroid Build Coastguard Worker }
749*9880d681SAndroid Build Coastguard Worker
750*9880d681SAndroid Build Coastguard Worker /// Return true if the loop can be software pipelined. The algorithm is
751*9880d681SAndroid Build Coastguard Worker /// restricted to loops with a single basic block. Make sure that the
752*9880d681SAndroid Build Coastguard Worker /// branch in the loop can be analyzed.
canPipelineLoop(MachineLoop & L)753*9880d681SAndroid Build Coastguard Worker bool MachinePipeliner::canPipelineLoop(MachineLoop &L) {
754*9880d681SAndroid Build Coastguard Worker if (L.getNumBlocks() != 1)
755*9880d681SAndroid Build Coastguard Worker return false;
756*9880d681SAndroid Build Coastguard Worker
757*9880d681SAndroid Build Coastguard Worker // Check if the branch can't be understood because we can't do pipelining
758*9880d681SAndroid Build Coastguard Worker // if that's the case.
759*9880d681SAndroid Build Coastguard Worker LI.TBB = nullptr;
760*9880d681SAndroid Build Coastguard Worker LI.FBB = nullptr;
761*9880d681SAndroid Build Coastguard Worker LI.BrCond.clear();
762*9880d681SAndroid Build Coastguard Worker if (TII->analyzeBranch(*L.getHeader(), LI.TBB, LI.FBB, LI.BrCond))
763*9880d681SAndroid Build Coastguard Worker return false;
764*9880d681SAndroid Build Coastguard Worker
765*9880d681SAndroid Build Coastguard Worker LI.LoopInductionVar = nullptr;
766*9880d681SAndroid Build Coastguard Worker LI.LoopCompare = nullptr;
767*9880d681SAndroid Build Coastguard Worker if (TII->analyzeLoop(L, LI.LoopInductionVar, LI.LoopCompare))
768*9880d681SAndroid Build Coastguard Worker return false;
769*9880d681SAndroid Build Coastguard Worker
770*9880d681SAndroid Build Coastguard Worker if (!L.getLoopPreheader())
771*9880d681SAndroid Build Coastguard Worker return false;
772*9880d681SAndroid Build Coastguard Worker
773*9880d681SAndroid Build Coastguard Worker // If any of the Phis contain subregs, then we can't pipeline
774*9880d681SAndroid Build Coastguard Worker // because we don't know how to maintain subreg information in the
775*9880d681SAndroid Build Coastguard Worker // VMap structure.
776*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = L.getHeader();
777*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = MBB->instr_begin(),
778*9880d681SAndroid Build Coastguard Worker BBE = MBB->getFirstNonPHI();
779*9880d681SAndroid Build Coastguard Worker BBI != BBE; ++BBI)
780*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1; i != BBI->getNumOperands(); i += 2)
781*9880d681SAndroid Build Coastguard Worker if (BBI->getOperand(i).getSubReg() != 0)
782*9880d681SAndroid Build Coastguard Worker return false;
783*9880d681SAndroid Build Coastguard Worker
784*9880d681SAndroid Build Coastguard Worker return true;
785*9880d681SAndroid Build Coastguard Worker }
786*9880d681SAndroid Build Coastguard Worker
787*9880d681SAndroid Build Coastguard Worker /// The SMS algorithm consists of the following main steps:
788*9880d681SAndroid Build Coastguard Worker /// 1. Computation and analysis of the dependence graph.
789*9880d681SAndroid Build Coastguard Worker /// 2. Ordering of the nodes (instructions).
790*9880d681SAndroid Build Coastguard Worker /// 3. Attempt to Schedule the loop.
swingModuloScheduler(MachineLoop & L)791*9880d681SAndroid Build Coastguard Worker bool MachinePipeliner::swingModuloScheduler(MachineLoop &L) {
792*9880d681SAndroid Build Coastguard Worker assert(L.getBlocks().size() == 1 && "SMS works on single blocks only.");
793*9880d681SAndroid Build Coastguard Worker
794*9880d681SAndroid Build Coastguard Worker SwingSchedulerDAG SMS(*this, L, getAnalysis<LiveIntervals>(), RegClassInfo);
795*9880d681SAndroid Build Coastguard Worker
796*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = L.getHeader();
797*9880d681SAndroid Build Coastguard Worker // The kernel should not include any terminator instructions. These
798*9880d681SAndroid Build Coastguard Worker // will be added back later.
799*9880d681SAndroid Build Coastguard Worker SMS.startBlock(MBB);
800*9880d681SAndroid Build Coastguard Worker
801*9880d681SAndroid Build Coastguard Worker // Compute the number of 'real' instructions in the basic block by
802*9880d681SAndroid Build Coastguard Worker // ignoring terminators.
803*9880d681SAndroid Build Coastguard Worker unsigned size = MBB->size();
804*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator I = MBB->getFirstTerminator(),
805*9880d681SAndroid Build Coastguard Worker E = MBB->instr_end();
806*9880d681SAndroid Build Coastguard Worker I != E; ++I, --size)
807*9880d681SAndroid Build Coastguard Worker ;
808*9880d681SAndroid Build Coastguard Worker
809*9880d681SAndroid Build Coastguard Worker SMS.enterRegion(MBB, MBB->begin(), MBB->getFirstTerminator(), size);
810*9880d681SAndroid Build Coastguard Worker SMS.schedule();
811*9880d681SAndroid Build Coastguard Worker SMS.exitRegion();
812*9880d681SAndroid Build Coastguard Worker
813*9880d681SAndroid Build Coastguard Worker SMS.finishBlock();
814*9880d681SAndroid Build Coastguard Worker return SMS.hasNewSchedule();
815*9880d681SAndroid Build Coastguard Worker }
816*9880d681SAndroid Build Coastguard Worker
817*9880d681SAndroid Build Coastguard Worker /// We override the schedule function in ScheduleDAGInstrs to implement the
818*9880d681SAndroid Build Coastguard Worker /// scheduling part of the Swing Modulo Scheduling algorithm.
schedule()819*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::schedule() {
820*9880d681SAndroid Build Coastguard Worker AliasAnalysis *AA = &Pass.getAnalysis<AAResultsWrapperPass>().getAAResults();
821*9880d681SAndroid Build Coastguard Worker buildSchedGraph(AA);
822*9880d681SAndroid Build Coastguard Worker addLoopCarriedDependences(AA);
823*9880d681SAndroid Build Coastguard Worker updatePhiDependences();
824*9880d681SAndroid Build Coastguard Worker Topo.InitDAGTopologicalSorting();
825*9880d681SAndroid Build Coastguard Worker changeDependences();
826*9880d681SAndroid Build Coastguard Worker DEBUG({
827*9880d681SAndroid Build Coastguard Worker for (unsigned su = 0, e = SUnits.size(); su != e; ++su)
828*9880d681SAndroid Build Coastguard Worker SUnits[su].dumpAll(this);
829*9880d681SAndroid Build Coastguard Worker });
830*9880d681SAndroid Build Coastguard Worker
831*9880d681SAndroid Build Coastguard Worker NodeSetType NodeSets;
832*9880d681SAndroid Build Coastguard Worker findCircuits(NodeSets);
833*9880d681SAndroid Build Coastguard Worker
834*9880d681SAndroid Build Coastguard Worker // Calculate the MII.
835*9880d681SAndroid Build Coastguard Worker unsigned ResMII = calculateResMII();
836*9880d681SAndroid Build Coastguard Worker unsigned RecMII = calculateRecMII(NodeSets);
837*9880d681SAndroid Build Coastguard Worker
838*9880d681SAndroid Build Coastguard Worker fuseRecs(NodeSets);
839*9880d681SAndroid Build Coastguard Worker
840*9880d681SAndroid Build Coastguard Worker // This flag is used for testing and can cause correctness problems.
841*9880d681SAndroid Build Coastguard Worker if (SwpIgnoreRecMII)
842*9880d681SAndroid Build Coastguard Worker RecMII = 0;
843*9880d681SAndroid Build Coastguard Worker
844*9880d681SAndroid Build Coastguard Worker MII = std::max(ResMII, RecMII);
845*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "MII = " << MII << " (rec=" << RecMII << ", res=" << ResMII
846*9880d681SAndroid Build Coastguard Worker << ")\n");
847*9880d681SAndroid Build Coastguard Worker
848*9880d681SAndroid Build Coastguard Worker // Can't schedule a loop without a valid MII.
849*9880d681SAndroid Build Coastguard Worker if (MII == 0)
850*9880d681SAndroid Build Coastguard Worker return;
851*9880d681SAndroid Build Coastguard Worker
852*9880d681SAndroid Build Coastguard Worker // Don't pipeline large loops.
853*9880d681SAndroid Build Coastguard Worker if (SwpMaxMii != -1 && (int)MII > SwpMaxMii)
854*9880d681SAndroid Build Coastguard Worker return;
855*9880d681SAndroid Build Coastguard Worker
856*9880d681SAndroid Build Coastguard Worker computeNodeFunctions(NodeSets);
857*9880d681SAndroid Build Coastguard Worker
858*9880d681SAndroid Build Coastguard Worker registerPressureFilter(NodeSets);
859*9880d681SAndroid Build Coastguard Worker
860*9880d681SAndroid Build Coastguard Worker colocateNodeSets(NodeSets);
861*9880d681SAndroid Build Coastguard Worker
862*9880d681SAndroid Build Coastguard Worker checkNodeSets(NodeSets);
863*9880d681SAndroid Build Coastguard Worker
864*9880d681SAndroid Build Coastguard Worker DEBUG({
865*9880d681SAndroid Build Coastguard Worker for (auto &I : NodeSets) {
866*9880d681SAndroid Build Coastguard Worker dbgs() << " Rec NodeSet ";
867*9880d681SAndroid Build Coastguard Worker I.dump();
868*9880d681SAndroid Build Coastguard Worker }
869*9880d681SAndroid Build Coastguard Worker });
870*9880d681SAndroid Build Coastguard Worker
871*9880d681SAndroid Build Coastguard Worker std::sort(NodeSets.begin(), NodeSets.end(), std::greater<NodeSet>());
872*9880d681SAndroid Build Coastguard Worker
873*9880d681SAndroid Build Coastguard Worker groupRemainingNodes(NodeSets);
874*9880d681SAndroid Build Coastguard Worker
875*9880d681SAndroid Build Coastguard Worker removeDuplicateNodes(NodeSets);
876*9880d681SAndroid Build Coastguard Worker
877*9880d681SAndroid Build Coastguard Worker DEBUG({
878*9880d681SAndroid Build Coastguard Worker for (auto &I : NodeSets) {
879*9880d681SAndroid Build Coastguard Worker dbgs() << " NodeSet ";
880*9880d681SAndroid Build Coastguard Worker I.dump();
881*9880d681SAndroid Build Coastguard Worker }
882*9880d681SAndroid Build Coastguard Worker });
883*9880d681SAndroid Build Coastguard Worker
884*9880d681SAndroid Build Coastguard Worker computeNodeOrder(NodeSets);
885*9880d681SAndroid Build Coastguard Worker
886*9880d681SAndroid Build Coastguard Worker SMSchedule Schedule(Pass.MF);
887*9880d681SAndroid Build Coastguard Worker Scheduled = schedulePipeline(Schedule);
888*9880d681SAndroid Build Coastguard Worker
889*9880d681SAndroid Build Coastguard Worker if (!Scheduled)
890*9880d681SAndroid Build Coastguard Worker return;
891*9880d681SAndroid Build Coastguard Worker
892*9880d681SAndroid Build Coastguard Worker unsigned numStages = Schedule.getMaxStageCount();
893*9880d681SAndroid Build Coastguard Worker // No need to generate pipeline if there are no overlapped iterations.
894*9880d681SAndroid Build Coastguard Worker if (numStages == 0)
895*9880d681SAndroid Build Coastguard Worker return;
896*9880d681SAndroid Build Coastguard Worker
897*9880d681SAndroid Build Coastguard Worker // Check that the maximum stage count is less than user-defined limit.
898*9880d681SAndroid Build Coastguard Worker if (SwpMaxStages > -1 && (int)numStages > SwpMaxStages)
899*9880d681SAndroid Build Coastguard Worker return;
900*9880d681SAndroid Build Coastguard Worker
901*9880d681SAndroid Build Coastguard Worker generatePipelinedLoop(Schedule);
902*9880d681SAndroid Build Coastguard Worker ++NumPipelined;
903*9880d681SAndroid Build Coastguard Worker }
904*9880d681SAndroid Build Coastguard Worker
905*9880d681SAndroid Build Coastguard Worker /// Clean up after the software pipeliner runs.
finishBlock()906*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::finishBlock() {
907*9880d681SAndroid Build Coastguard Worker for (MachineInstr *I : NewMIs)
908*9880d681SAndroid Build Coastguard Worker MF.DeleteMachineInstr(I);
909*9880d681SAndroid Build Coastguard Worker NewMIs.clear();
910*9880d681SAndroid Build Coastguard Worker
911*9880d681SAndroid Build Coastguard Worker // Call the superclass.
912*9880d681SAndroid Build Coastguard Worker ScheduleDAGInstrs::finishBlock();
913*9880d681SAndroid Build Coastguard Worker }
914*9880d681SAndroid Build Coastguard Worker
915*9880d681SAndroid Build Coastguard Worker /// Return the register values for the operands of a Phi instruction.
916*9880d681SAndroid Build Coastguard Worker /// This function assume the instruction is a Phi.
getPhiRegs(MachineInstr & Phi,MachineBasicBlock * Loop,unsigned & InitVal,unsigned & LoopVal)917*9880d681SAndroid Build Coastguard Worker static void getPhiRegs(MachineInstr &Phi, MachineBasicBlock *Loop,
918*9880d681SAndroid Build Coastguard Worker unsigned &InitVal, unsigned &LoopVal) {
919*9880d681SAndroid Build Coastguard Worker assert(Phi.isPHI() && "Expecting a Phi.");
920*9880d681SAndroid Build Coastguard Worker
921*9880d681SAndroid Build Coastguard Worker InitVal = 0;
922*9880d681SAndroid Build Coastguard Worker LoopVal = 0;
923*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
924*9880d681SAndroid Build Coastguard Worker if (Phi.getOperand(i + 1).getMBB() != Loop)
925*9880d681SAndroid Build Coastguard Worker InitVal = Phi.getOperand(i).getReg();
926*9880d681SAndroid Build Coastguard Worker else if (Phi.getOperand(i + 1).getMBB() == Loop)
927*9880d681SAndroid Build Coastguard Worker LoopVal = Phi.getOperand(i).getReg();
928*9880d681SAndroid Build Coastguard Worker
929*9880d681SAndroid Build Coastguard Worker assert(InitVal != 0 && LoopVal != 0 && "Unexpected Phi structure.");
930*9880d681SAndroid Build Coastguard Worker }
931*9880d681SAndroid Build Coastguard Worker
932*9880d681SAndroid Build Coastguard Worker /// Return the Phi register value that comes from the incoming block.
getInitPhiReg(MachineInstr & Phi,MachineBasicBlock * LoopBB)933*9880d681SAndroid Build Coastguard Worker static unsigned getInitPhiReg(MachineInstr &Phi, MachineBasicBlock *LoopBB) {
934*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
935*9880d681SAndroid Build Coastguard Worker if (Phi.getOperand(i + 1).getMBB() != LoopBB)
936*9880d681SAndroid Build Coastguard Worker return Phi.getOperand(i).getReg();
937*9880d681SAndroid Build Coastguard Worker return 0;
938*9880d681SAndroid Build Coastguard Worker }
939*9880d681SAndroid Build Coastguard Worker
940*9880d681SAndroid Build Coastguard Worker /// Return the Phi register value that comes the the loop block.
getLoopPhiReg(MachineInstr & Phi,MachineBasicBlock * LoopBB)941*9880d681SAndroid Build Coastguard Worker static unsigned getLoopPhiReg(MachineInstr &Phi, MachineBasicBlock *LoopBB) {
942*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = Phi.getNumOperands(); i != e; i += 2)
943*9880d681SAndroid Build Coastguard Worker if (Phi.getOperand(i + 1).getMBB() == LoopBB)
944*9880d681SAndroid Build Coastguard Worker return Phi.getOperand(i).getReg();
945*9880d681SAndroid Build Coastguard Worker return 0;
946*9880d681SAndroid Build Coastguard Worker }
947*9880d681SAndroid Build Coastguard Worker
948*9880d681SAndroid Build Coastguard Worker /// Return true if SUb can be reached from SUa following the chain edges.
isSuccOrder(SUnit * SUa,SUnit * SUb)949*9880d681SAndroid Build Coastguard Worker static bool isSuccOrder(SUnit *SUa, SUnit *SUb) {
950*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 8> Visited;
951*9880d681SAndroid Build Coastguard Worker SmallVector<SUnit *, 8> Worklist;
952*9880d681SAndroid Build Coastguard Worker Worklist.push_back(SUa);
953*9880d681SAndroid Build Coastguard Worker while (!Worklist.empty()) {
954*9880d681SAndroid Build Coastguard Worker const SUnit *SU = Worklist.pop_back_val();
955*9880d681SAndroid Build Coastguard Worker for (auto &SI : SU->Succs) {
956*9880d681SAndroid Build Coastguard Worker SUnit *SuccSU = SI.getSUnit();
957*9880d681SAndroid Build Coastguard Worker if (SI.getKind() == SDep::Order) {
958*9880d681SAndroid Build Coastguard Worker if (Visited.count(SuccSU))
959*9880d681SAndroid Build Coastguard Worker continue;
960*9880d681SAndroid Build Coastguard Worker if (SuccSU == SUb)
961*9880d681SAndroid Build Coastguard Worker return true;
962*9880d681SAndroid Build Coastguard Worker Worklist.push_back(SuccSU);
963*9880d681SAndroid Build Coastguard Worker Visited.insert(SuccSU);
964*9880d681SAndroid Build Coastguard Worker }
965*9880d681SAndroid Build Coastguard Worker }
966*9880d681SAndroid Build Coastguard Worker }
967*9880d681SAndroid Build Coastguard Worker return false;
968*9880d681SAndroid Build Coastguard Worker }
969*9880d681SAndroid Build Coastguard Worker
970*9880d681SAndroid Build Coastguard Worker /// Return true if the instruction causes a chain between memory
971*9880d681SAndroid Build Coastguard Worker /// references before and after it.
isDependenceBarrier(MachineInstr & MI,AliasAnalysis * AA)972*9880d681SAndroid Build Coastguard Worker static bool isDependenceBarrier(MachineInstr &MI, AliasAnalysis *AA) {
973*9880d681SAndroid Build Coastguard Worker return MI.isCall() || MI.hasUnmodeledSideEffects() ||
974*9880d681SAndroid Build Coastguard Worker (MI.hasOrderedMemoryRef() &&
975*9880d681SAndroid Build Coastguard Worker (!MI.mayLoad() || !MI.isInvariantLoad(AA)));
976*9880d681SAndroid Build Coastguard Worker }
977*9880d681SAndroid Build Coastguard Worker
978*9880d681SAndroid Build Coastguard Worker /// Return the underlying objects for the memory references of an instruction.
979*9880d681SAndroid Build Coastguard Worker /// This function calls the code in ValueTracking, but first checks that the
980*9880d681SAndroid Build Coastguard Worker /// instruction has a memory operand.
getUnderlyingObjects(MachineInstr * MI,SmallVectorImpl<Value * > & Objs,const DataLayout & DL)981*9880d681SAndroid Build Coastguard Worker static void getUnderlyingObjects(MachineInstr *MI,
982*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<Value *> &Objs,
983*9880d681SAndroid Build Coastguard Worker const DataLayout &DL) {
984*9880d681SAndroid Build Coastguard Worker if (!MI->hasOneMemOperand())
985*9880d681SAndroid Build Coastguard Worker return;
986*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MM = *MI->memoperands_begin();
987*9880d681SAndroid Build Coastguard Worker if (!MM->getValue())
988*9880d681SAndroid Build Coastguard Worker return;
989*9880d681SAndroid Build Coastguard Worker GetUnderlyingObjects(const_cast<Value *>(MM->getValue()), Objs, DL);
990*9880d681SAndroid Build Coastguard Worker }
991*9880d681SAndroid Build Coastguard Worker
992*9880d681SAndroid Build Coastguard Worker /// Add a chain edge between a load and store if the store can be an
993*9880d681SAndroid Build Coastguard Worker /// alias of the load on a subsequent iteration, i.e., a loop carried
994*9880d681SAndroid Build Coastguard Worker /// dependence. This code is very similar to the code in ScheduleDAGInstrs
995*9880d681SAndroid Build Coastguard Worker /// but that code doesn't create loop carried dependences.
addLoopCarriedDependences(AliasAnalysis * AA)996*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::addLoopCarriedDependences(AliasAnalysis *AA) {
997*9880d681SAndroid Build Coastguard Worker MapVector<Value *, SmallVector<SUnit *, 4>> PendingLoads;
998*9880d681SAndroid Build Coastguard Worker for (auto &SU : SUnits) {
999*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *SU.getInstr();
1000*9880d681SAndroid Build Coastguard Worker if (isDependenceBarrier(MI, AA))
1001*9880d681SAndroid Build Coastguard Worker PendingLoads.clear();
1002*9880d681SAndroid Build Coastguard Worker else if (MI.mayLoad()) {
1003*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> Objs;
1004*9880d681SAndroid Build Coastguard Worker getUnderlyingObjects(&MI, Objs, MF.getDataLayout());
1005*9880d681SAndroid Build Coastguard Worker for (auto V : Objs) {
1006*9880d681SAndroid Build Coastguard Worker SmallVector<SUnit *, 4> &SUs = PendingLoads[V];
1007*9880d681SAndroid Build Coastguard Worker SUs.push_back(&SU);
1008*9880d681SAndroid Build Coastguard Worker }
1009*9880d681SAndroid Build Coastguard Worker } else if (MI.mayStore()) {
1010*9880d681SAndroid Build Coastguard Worker SmallVector<Value *, 4> Objs;
1011*9880d681SAndroid Build Coastguard Worker getUnderlyingObjects(&MI, Objs, MF.getDataLayout());
1012*9880d681SAndroid Build Coastguard Worker for (auto V : Objs) {
1013*9880d681SAndroid Build Coastguard Worker MapVector<Value *, SmallVector<SUnit *, 4>>::iterator I =
1014*9880d681SAndroid Build Coastguard Worker PendingLoads.find(V);
1015*9880d681SAndroid Build Coastguard Worker if (I == PendingLoads.end())
1016*9880d681SAndroid Build Coastguard Worker continue;
1017*9880d681SAndroid Build Coastguard Worker for (auto Load : I->second) {
1018*9880d681SAndroid Build Coastguard Worker if (isSuccOrder(Load, &SU))
1019*9880d681SAndroid Build Coastguard Worker continue;
1020*9880d681SAndroid Build Coastguard Worker MachineInstr &LdMI = *Load->getInstr();
1021*9880d681SAndroid Build Coastguard Worker // First, perform the cheaper check that compares the base register.
1022*9880d681SAndroid Build Coastguard Worker // If they are the same and the load offset is less than the store
1023*9880d681SAndroid Build Coastguard Worker // offset, then mark the dependence as loop carried potentially.
1024*9880d681SAndroid Build Coastguard Worker unsigned BaseReg1, BaseReg2;
1025*9880d681SAndroid Build Coastguard Worker int64_t Offset1, Offset2;
1026*9880d681SAndroid Build Coastguard Worker if (!TII->getMemOpBaseRegImmOfs(LdMI, BaseReg1, Offset1, TRI) ||
1027*9880d681SAndroid Build Coastguard Worker !TII->getMemOpBaseRegImmOfs(MI, BaseReg2, Offset2, TRI)) {
1028*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1029*9880d681SAndroid Build Coastguard Worker continue;
1030*9880d681SAndroid Build Coastguard Worker }
1031*9880d681SAndroid Build Coastguard Worker if (BaseReg1 == BaseReg2 && (int)Offset1 < (int)Offset2) {
1032*9880d681SAndroid Build Coastguard Worker assert(TII->areMemAccessesTriviallyDisjoint(LdMI, MI, AA) &&
1033*9880d681SAndroid Build Coastguard Worker "What happened to the chain edge?");
1034*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1035*9880d681SAndroid Build Coastguard Worker continue;
1036*9880d681SAndroid Build Coastguard Worker }
1037*9880d681SAndroid Build Coastguard Worker // Second, the more expensive check that uses alias analysis on the
1038*9880d681SAndroid Build Coastguard Worker // base registers. If they alias, and the load offset is less than
1039*9880d681SAndroid Build Coastguard Worker // the store offset, the mark the dependence as loop carried.
1040*9880d681SAndroid Build Coastguard Worker if (!AA) {
1041*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1042*9880d681SAndroid Build Coastguard Worker continue;
1043*9880d681SAndroid Build Coastguard Worker }
1044*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO1 = *LdMI.memoperands_begin();
1045*9880d681SAndroid Build Coastguard Worker MachineMemOperand *MMO2 = *MI.memoperands_begin();
1046*9880d681SAndroid Build Coastguard Worker if (!MMO1->getValue() || !MMO2->getValue()) {
1047*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1048*9880d681SAndroid Build Coastguard Worker continue;
1049*9880d681SAndroid Build Coastguard Worker }
1050*9880d681SAndroid Build Coastguard Worker if (MMO1->getValue() == MMO2->getValue() &&
1051*9880d681SAndroid Build Coastguard Worker MMO1->getOffset() <= MMO2->getOffset()) {
1052*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1053*9880d681SAndroid Build Coastguard Worker continue;
1054*9880d681SAndroid Build Coastguard Worker }
1055*9880d681SAndroid Build Coastguard Worker AliasResult AAResult = AA->alias(
1056*9880d681SAndroid Build Coastguard Worker MemoryLocation(MMO1->getValue(), MemoryLocation::UnknownSize,
1057*9880d681SAndroid Build Coastguard Worker MMO1->getAAInfo()),
1058*9880d681SAndroid Build Coastguard Worker MemoryLocation(MMO2->getValue(), MemoryLocation::UnknownSize,
1059*9880d681SAndroid Build Coastguard Worker MMO2->getAAInfo()));
1060*9880d681SAndroid Build Coastguard Worker
1061*9880d681SAndroid Build Coastguard Worker if (AAResult != NoAlias)
1062*9880d681SAndroid Build Coastguard Worker SU.addPred(SDep(Load, SDep::Barrier));
1063*9880d681SAndroid Build Coastguard Worker }
1064*9880d681SAndroid Build Coastguard Worker }
1065*9880d681SAndroid Build Coastguard Worker }
1066*9880d681SAndroid Build Coastguard Worker }
1067*9880d681SAndroid Build Coastguard Worker }
1068*9880d681SAndroid Build Coastguard Worker
1069*9880d681SAndroid Build Coastguard Worker /// Update the phi dependences to the DAG because ScheduleDAGInstrs no longer
1070*9880d681SAndroid Build Coastguard Worker /// processes dependences for PHIs. This function adds true dependences
1071*9880d681SAndroid Build Coastguard Worker /// from a PHI to a use, and a loop carried dependence from the use to the
1072*9880d681SAndroid Build Coastguard Worker /// PHI. The loop carried dependence is represented as an anti dependence
1073*9880d681SAndroid Build Coastguard Worker /// edge. This function also removes chain dependences between unrelated
1074*9880d681SAndroid Build Coastguard Worker /// PHIs.
updatePhiDependences()1075*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::updatePhiDependences() {
1076*9880d681SAndroid Build Coastguard Worker SmallVector<SDep, 4> RemoveDeps;
1077*9880d681SAndroid Build Coastguard Worker const TargetSubtargetInfo &ST = MF.getSubtarget<TargetSubtargetInfo>();
1078*9880d681SAndroid Build Coastguard Worker
1079*9880d681SAndroid Build Coastguard Worker // Iterate over each DAG node.
1080*9880d681SAndroid Build Coastguard Worker for (SUnit &I : SUnits) {
1081*9880d681SAndroid Build Coastguard Worker RemoveDeps.clear();
1082*9880d681SAndroid Build Coastguard Worker // Set to true if the instruction has an operand defined by a Phi.
1083*9880d681SAndroid Build Coastguard Worker unsigned HasPhiUse = 0;
1084*9880d681SAndroid Build Coastguard Worker unsigned HasPhiDef = 0;
1085*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = I.getInstr();
1086*9880d681SAndroid Build Coastguard Worker // Iterate over each operand, and we process the definitions.
1087*9880d681SAndroid Build Coastguard Worker for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
1088*9880d681SAndroid Build Coastguard Worker MOE = MI->operands_end();
1089*9880d681SAndroid Build Coastguard Worker MOI != MOE; ++MOI) {
1090*9880d681SAndroid Build Coastguard Worker if (!MOI->isReg())
1091*9880d681SAndroid Build Coastguard Worker continue;
1092*9880d681SAndroid Build Coastguard Worker unsigned Reg = MOI->getReg();
1093*9880d681SAndroid Build Coastguard Worker if (MOI->isDef()) {
1094*9880d681SAndroid Build Coastguard Worker // If the register is used by a Phi, then create an anti dependence.
1095*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_instr_iterator
1096*9880d681SAndroid Build Coastguard Worker UI = MRI.use_instr_begin(Reg),
1097*9880d681SAndroid Build Coastguard Worker UE = MRI.use_instr_end();
1098*9880d681SAndroid Build Coastguard Worker UI != UE; ++UI) {
1099*9880d681SAndroid Build Coastguard Worker MachineInstr *UseMI = &*UI;
1100*9880d681SAndroid Build Coastguard Worker SUnit *SU = getSUnit(UseMI);
1101*9880d681SAndroid Build Coastguard Worker if (SU != 0 && UseMI->isPHI()) {
1102*9880d681SAndroid Build Coastguard Worker if (!MI->isPHI()) {
1103*9880d681SAndroid Build Coastguard Worker SDep Dep(SU, SDep::Anti, Reg);
1104*9880d681SAndroid Build Coastguard Worker I.addPred(Dep);
1105*9880d681SAndroid Build Coastguard Worker } else {
1106*9880d681SAndroid Build Coastguard Worker HasPhiDef = Reg;
1107*9880d681SAndroid Build Coastguard Worker // Add a chain edge to a dependent Phi that isn't an existing
1108*9880d681SAndroid Build Coastguard Worker // predecessor.
1109*9880d681SAndroid Build Coastguard Worker if (SU->NodeNum < I.NodeNum && !I.isPred(SU))
1110*9880d681SAndroid Build Coastguard Worker I.addPred(SDep(SU, SDep::Barrier));
1111*9880d681SAndroid Build Coastguard Worker }
1112*9880d681SAndroid Build Coastguard Worker }
1113*9880d681SAndroid Build Coastguard Worker }
1114*9880d681SAndroid Build Coastguard Worker } else if (MOI->isUse()) {
1115*9880d681SAndroid Build Coastguard Worker // If the register is defined by a Phi, then create a true dependence.
1116*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = MRI.getUniqueVRegDef(Reg);
1117*9880d681SAndroid Build Coastguard Worker if (DefMI == 0)
1118*9880d681SAndroid Build Coastguard Worker continue;
1119*9880d681SAndroid Build Coastguard Worker SUnit *SU = getSUnit(DefMI);
1120*9880d681SAndroid Build Coastguard Worker if (SU != 0 && DefMI->isPHI()) {
1121*9880d681SAndroid Build Coastguard Worker if (!MI->isPHI()) {
1122*9880d681SAndroid Build Coastguard Worker SDep Dep(SU, SDep::Data, Reg);
1123*9880d681SAndroid Build Coastguard Worker Dep.setLatency(0);
1124*9880d681SAndroid Build Coastguard Worker ST.adjustSchedDependency(SU, &I, Dep);
1125*9880d681SAndroid Build Coastguard Worker I.addPred(Dep);
1126*9880d681SAndroid Build Coastguard Worker } else {
1127*9880d681SAndroid Build Coastguard Worker HasPhiUse = Reg;
1128*9880d681SAndroid Build Coastguard Worker // Add a chain edge to a dependent Phi that isn't an existing
1129*9880d681SAndroid Build Coastguard Worker // predecessor.
1130*9880d681SAndroid Build Coastguard Worker if (SU->NodeNum < I.NodeNum && !I.isPred(SU))
1131*9880d681SAndroid Build Coastguard Worker I.addPred(SDep(SU, SDep::Barrier));
1132*9880d681SAndroid Build Coastguard Worker }
1133*9880d681SAndroid Build Coastguard Worker }
1134*9880d681SAndroid Build Coastguard Worker }
1135*9880d681SAndroid Build Coastguard Worker }
1136*9880d681SAndroid Build Coastguard Worker // Remove order dependences from an unrelated Phi.
1137*9880d681SAndroid Build Coastguard Worker if (!SwpPruneDeps)
1138*9880d681SAndroid Build Coastguard Worker continue;
1139*9880d681SAndroid Build Coastguard Worker for (auto &PI : I.Preds) {
1140*9880d681SAndroid Build Coastguard Worker MachineInstr *PMI = PI.getSUnit()->getInstr();
1141*9880d681SAndroid Build Coastguard Worker if (PMI->isPHI() && PI.getKind() == SDep::Order) {
1142*9880d681SAndroid Build Coastguard Worker if (I.getInstr()->isPHI()) {
1143*9880d681SAndroid Build Coastguard Worker if (PMI->getOperand(0).getReg() == HasPhiUse)
1144*9880d681SAndroid Build Coastguard Worker continue;
1145*9880d681SAndroid Build Coastguard Worker if (getLoopPhiReg(*PMI, PMI->getParent()) == HasPhiDef)
1146*9880d681SAndroid Build Coastguard Worker continue;
1147*9880d681SAndroid Build Coastguard Worker }
1148*9880d681SAndroid Build Coastguard Worker RemoveDeps.push_back(PI);
1149*9880d681SAndroid Build Coastguard Worker }
1150*9880d681SAndroid Build Coastguard Worker }
1151*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = RemoveDeps.size(); i != e; ++i)
1152*9880d681SAndroid Build Coastguard Worker I.removePred(RemoveDeps[i]);
1153*9880d681SAndroid Build Coastguard Worker }
1154*9880d681SAndroid Build Coastguard Worker }
1155*9880d681SAndroid Build Coastguard Worker
1156*9880d681SAndroid Build Coastguard Worker /// Iterate over each DAG node and see if we can change any dependences
1157*9880d681SAndroid Build Coastguard Worker /// in order to reduce the recurrence MII.
changeDependences()1158*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::changeDependences() {
1159*9880d681SAndroid Build Coastguard Worker // See if an instruction can use a value from the previous iteration.
1160*9880d681SAndroid Build Coastguard Worker // If so, we update the base and offset of the instruction and change
1161*9880d681SAndroid Build Coastguard Worker // the dependences.
1162*9880d681SAndroid Build Coastguard Worker for (SUnit &I : SUnits) {
1163*9880d681SAndroid Build Coastguard Worker unsigned BasePos = 0, OffsetPos = 0, NewBase = 0;
1164*9880d681SAndroid Build Coastguard Worker int64_t NewOffset = 0;
1165*9880d681SAndroid Build Coastguard Worker if (!canUseLastOffsetValue(I.getInstr(), BasePos, OffsetPos, NewBase,
1166*9880d681SAndroid Build Coastguard Worker NewOffset))
1167*9880d681SAndroid Build Coastguard Worker continue;
1168*9880d681SAndroid Build Coastguard Worker
1169*9880d681SAndroid Build Coastguard Worker // Get the MI and SUnit for the instruction that defines the original base.
1170*9880d681SAndroid Build Coastguard Worker unsigned OrigBase = I.getInstr()->getOperand(BasePos).getReg();
1171*9880d681SAndroid Build Coastguard Worker MachineInstr *DefMI = MRI.getUniqueVRegDef(OrigBase);
1172*9880d681SAndroid Build Coastguard Worker if (!DefMI)
1173*9880d681SAndroid Build Coastguard Worker continue;
1174*9880d681SAndroid Build Coastguard Worker SUnit *DefSU = getSUnit(DefMI);
1175*9880d681SAndroid Build Coastguard Worker if (!DefSU)
1176*9880d681SAndroid Build Coastguard Worker continue;
1177*9880d681SAndroid Build Coastguard Worker // Get the MI and SUnit for the instruction that defins the new base.
1178*9880d681SAndroid Build Coastguard Worker MachineInstr *LastMI = MRI.getUniqueVRegDef(NewBase);
1179*9880d681SAndroid Build Coastguard Worker if (!LastMI)
1180*9880d681SAndroid Build Coastguard Worker continue;
1181*9880d681SAndroid Build Coastguard Worker SUnit *LastSU = getSUnit(LastMI);
1182*9880d681SAndroid Build Coastguard Worker if (!LastSU)
1183*9880d681SAndroid Build Coastguard Worker continue;
1184*9880d681SAndroid Build Coastguard Worker
1185*9880d681SAndroid Build Coastguard Worker if (Topo.IsReachable(&I, LastSU))
1186*9880d681SAndroid Build Coastguard Worker continue;
1187*9880d681SAndroid Build Coastguard Worker
1188*9880d681SAndroid Build Coastguard Worker // Remove the dependence. The value now depends on a prior iteration.
1189*9880d681SAndroid Build Coastguard Worker SmallVector<SDep, 4> Deps;
1190*9880d681SAndroid Build Coastguard Worker for (SUnit::pred_iterator P = I.Preds.begin(), E = I.Preds.end(); P != E;
1191*9880d681SAndroid Build Coastguard Worker ++P)
1192*9880d681SAndroid Build Coastguard Worker if (P->getSUnit() == DefSU)
1193*9880d681SAndroid Build Coastguard Worker Deps.push_back(*P);
1194*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = Deps.size(); i != e; i++) {
1195*9880d681SAndroid Build Coastguard Worker Topo.RemovePred(&I, Deps[i].getSUnit());
1196*9880d681SAndroid Build Coastguard Worker I.removePred(Deps[i]);
1197*9880d681SAndroid Build Coastguard Worker }
1198*9880d681SAndroid Build Coastguard Worker // Remove the chain dependence between the instructions.
1199*9880d681SAndroid Build Coastguard Worker Deps.clear();
1200*9880d681SAndroid Build Coastguard Worker for (auto &P : LastSU->Preds)
1201*9880d681SAndroid Build Coastguard Worker if (P.getSUnit() == &I && P.getKind() == SDep::Order)
1202*9880d681SAndroid Build Coastguard Worker Deps.push_back(P);
1203*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = Deps.size(); i != e; i++) {
1204*9880d681SAndroid Build Coastguard Worker Topo.RemovePred(LastSU, Deps[i].getSUnit());
1205*9880d681SAndroid Build Coastguard Worker LastSU->removePred(Deps[i]);
1206*9880d681SAndroid Build Coastguard Worker }
1207*9880d681SAndroid Build Coastguard Worker
1208*9880d681SAndroid Build Coastguard Worker // Add a dependence between the new instruction and the instruction
1209*9880d681SAndroid Build Coastguard Worker // that defines the new base.
1210*9880d681SAndroid Build Coastguard Worker SDep Dep(&I, SDep::Anti, NewBase);
1211*9880d681SAndroid Build Coastguard Worker LastSU->addPred(Dep);
1212*9880d681SAndroid Build Coastguard Worker
1213*9880d681SAndroid Build Coastguard Worker // Remember the base and offset information so that we can update the
1214*9880d681SAndroid Build Coastguard Worker // instruction during code generation.
1215*9880d681SAndroid Build Coastguard Worker InstrChanges[&I] = std::make_pair(NewBase, NewOffset);
1216*9880d681SAndroid Build Coastguard Worker }
1217*9880d681SAndroid Build Coastguard Worker }
1218*9880d681SAndroid Build Coastguard Worker
1219*9880d681SAndroid Build Coastguard Worker namespace {
1220*9880d681SAndroid Build Coastguard Worker // FuncUnitSorter - Comparison operator used to sort instructions by
1221*9880d681SAndroid Build Coastguard Worker // the number of functional unit choices.
1222*9880d681SAndroid Build Coastguard Worker struct FuncUnitSorter {
1223*9880d681SAndroid Build Coastguard Worker const InstrItineraryData *InstrItins;
1224*9880d681SAndroid Build Coastguard Worker DenseMap<unsigned, unsigned> Resources;
1225*9880d681SAndroid Build Coastguard Worker
1226*9880d681SAndroid Build Coastguard Worker // Compute the number of functional unit alternatives needed
1227*9880d681SAndroid Build Coastguard Worker // at each stage, and take the minimum value. We prioritize the
1228*9880d681SAndroid Build Coastguard Worker // instructions by the least number of choices first.
minFuncUnits__anon269b60a90211::FuncUnitSorter1229*9880d681SAndroid Build Coastguard Worker unsigned minFuncUnits(const MachineInstr *Inst, unsigned &F) const {
1230*9880d681SAndroid Build Coastguard Worker unsigned schedClass = Inst->getDesc().getSchedClass();
1231*9880d681SAndroid Build Coastguard Worker unsigned min = UINT_MAX;
1232*9880d681SAndroid Build Coastguard Worker for (const InstrStage *IS = InstrItins->beginStage(schedClass),
1233*9880d681SAndroid Build Coastguard Worker *IE = InstrItins->endStage(schedClass);
1234*9880d681SAndroid Build Coastguard Worker IS != IE; ++IS) {
1235*9880d681SAndroid Build Coastguard Worker unsigned funcUnits = IS->getUnits();
1236*9880d681SAndroid Build Coastguard Worker unsigned numAlternatives = countPopulation(funcUnits);
1237*9880d681SAndroid Build Coastguard Worker if (numAlternatives < min) {
1238*9880d681SAndroid Build Coastguard Worker min = numAlternatives;
1239*9880d681SAndroid Build Coastguard Worker F = funcUnits;
1240*9880d681SAndroid Build Coastguard Worker }
1241*9880d681SAndroid Build Coastguard Worker }
1242*9880d681SAndroid Build Coastguard Worker return min;
1243*9880d681SAndroid Build Coastguard Worker }
1244*9880d681SAndroid Build Coastguard Worker
1245*9880d681SAndroid Build Coastguard Worker // Compute the critical resources needed by the instruction. This
1246*9880d681SAndroid Build Coastguard Worker // function records the functional units needed by instructions that
1247*9880d681SAndroid Build Coastguard Worker // must use only one functional unit. We use this as a tie breaker
1248*9880d681SAndroid Build Coastguard Worker // for computing the resource MII. The instrutions that require
1249*9880d681SAndroid Build Coastguard Worker // the same, highly used, functional unit have high priority.
calcCriticalResources__anon269b60a90211::FuncUnitSorter1250*9880d681SAndroid Build Coastguard Worker void calcCriticalResources(MachineInstr &MI) {
1251*9880d681SAndroid Build Coastguard Worker unsigned SchedClass = MI.getDesc().getSchedClass();
1252*9880d681SAndroid Build Coastguard Worker for (const InstrStage *IS = InstrItins->beginStage(SchedClass),
1253*9880d681SAndroid Build Coastguard Worker *IE = InstrItins->endStage(SchedClass);
1254*9880d681SAndroid Build Coastguard Worker IS != IE; ++IS) {
1255*9880d681SAndroid Build Coastguard Worker unsigned FuncUnits = IS->getUnits();
1256*9880d681SAndroid Build Coastguard Worker if (countPopulation(FuncUnits) == 1)
1257*9880d681SAndroid Build Coastguard Worker Resources[FuncUnits]++;
1258*9880d681SAndroid Build Coastguard Worker }
1259*9880d681SAndroid Build Coastguard Worker }
1260*9880d681SAndroid Build Coastguard Worker
FuncUnitSorter__anon269b60a90211::FuncUnitSorter1261*9880d681SAndroid Build Coastguard Worker FuncUnitSorter(const InstrItineraryData *IID) : InstrItins(IID) {}
1262*9880d681SAndroid Build Coastguard Worker /// Return true if IS1 has less priority than IS2.
operator ()__anon269b60a90211::FuncUnitSorter1263*9880d681SAndroid Build Coastguard Worker bool operator()(const MachineInstr *IS1, const MachineInstr *IS2) const {
1264*9880d681SAndroid Build Coastguard Worker unsigned F1 = 0, F2 = 0;
1265*9880d681SAndroid Build Coastguard Worker unsigned MFUs1 = minFuncUnits(IS1, F1);
1266*9880d681SAndroid Build Coastguard Worker unsigned MFUs2 = minFuncUnits(IS2, F2);
1267*9880d681SAndroid Build Coastguard Worker if (MFUs1 == 1 && MFUs2 == 1)
1268*9880d681SAndroid Build Coastguard Worker return Resources.lookup(F1) < Resources.lookup(F2);
1269*9880d681SAndroid Build Coastguard Worker return MFUs1 > MFUs2;
1270*9880d681SAndroid Build Coastguard Worker }
1271*9880d681SAndroid Build Coastguard Worker };
1272*9880d681SAndroid Build Coastguard Worker }
1273*9880d681SAndroid Build Coastguard Worker
1274*9880d681SAndroid Build Coastguard Worker /// Calculate the resource constrained minimum initiation interval for the
1275*9880d681SAndroid Build Coastguard Worker /// specified loop. We use the DFA to model the resources needed for
1276*9880d681SAndroid Build Coastguard Worker /// each instruction, and we ignore dependences. A different DFA is created
1277*9880d681SAndroid Build Coastguard Worker /// for each cycle that is required. When adding a new instruction, we attempt
1278*9880d681SAndroid Build Coastguard Worker /// to add it to each existing DFA, until a legal space is found. If the
1279*9880d681SAndroid Build Coastguard Worker /// instruction cannot be reserved in an existing DFA, we create a new one.
calculateResMII()1280*9880d681SAndroid Build Coastguard Worker unsigned SwingSchedulerDAG::calculateResMII() {
1281*9880d681SAndroid Build Coastguard Worker SmallVector<DFAPacketizer *, 8> Resources;
1282*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = Loop.getHeader();
1283*9880d681SAndroid Build Coastguard Worker Resources.push_back(TII->CreateTargetScheduleState(MF.getSubtarget()));
1284*9880d681SAndroid Build Coastguard Worker
1285*9880d681SAndroid Build Coastguard Worker // Sort the instructions by the number of available choices for scheduling,
1286*9880d681SAndroid Build Coastguard Worker // least to most. Use the number of critical resources as the tie breaker.
1287*9880d681SAndroid Build Coastguard Worker FuncUnitSorter FUS =
1288*9880d681SAndroid Build Coastguard Worker FuncUnitSorter(MF.getSubtarget().getInstrItineraryData());
1289*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator I = MBB->getFirstNonPHI(),
1290*9880d681SAndroid Build Coastguard Worker E = MBB->getFirstTerminator();
1291*9880d681SAndroid Build Coastguard Worker I != E; ++I)
1292*9880d681SAndroid Build Coastguard Worker FUS.calcCriticalResources(*I);
1293*9880d681SAndroid Build Coastguard Worker PriorityQueue<MachineInstr *, std::vector<MachineInstr *>, FuncUnitSorter>
1294*9880d681SAndroid Build Coastguard Worker FuncUnitOrder(FUS);
1295*9880d681SAndroid Build Coastguard Worker
1296*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator I = MBB->getFirstNonPHI(),
1297*9880d681SAndroid Build Coastguard Worker E = MBB->getFirstTerminator();
1298*9880d681SAndroid Build Coastguard Worker I != E; ++I)
1299*9880d681SAndroid Build Coastguard Worker FuncUnitOrder.push(&*I);
1300*9880d681SAndroid Build Coastguard Worker
1301*9880d681SAndroid Build Coastguard Worker while (!FuncUnitOrder.empty()) {
1302*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = FuncUnitOrder.top();
1303*9880d681SAndroid Build Coastguard Worker FuncUnitOrder.pop();
1304*9880d681SAndroid Build Coastguard Worker if (TII->isZeroCost(MI->getOpcode()))
1305*9880d681SAndroid Build Coastguard Worker continue;
1306*9880d681SAndroid Build Coastguard Worker // Attempt to reserve the instruction in an existing DFA. At least one
1307*9880d681SAndroid Build Coastguard Worker // DFA is needed for each cycle.
1308*9880d681SAndroid Build Coastguard Worker unsigned NumCycles = getSUnit(MI)->Latency;
1309*9880d681SAndroid Build Coastguard Worker unsigned ReservedCycles = 0;
1310*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<DFAPacketizer *>::iterator RI = Resources.begin();
1311*9880d681SAndroid Build Coastguard Worker SmallVectorImpl<DFAPacketizer *>::iterator RE = Resources.end();
1312*9880d681SAndroid Build Coastguard Worker for (unsigned C = 0; C < NumCycles; ++C)
1313*9880d681SAndroid Build Coastguard Worker while (RI != RE) {
1314*9880d681SAndroid Build Coastguard Worker if ((*RI++)->canReserveResources(*MI)) {
1315*9880d681SAndroid Build Coastguard Worker ++ReservedCycles;
1316*9880d681SAndroid Build Coastguard Worker break;
1317*9880d681SAndroid Build Coastguard Worker }
1318*9880d681SAndroid Build Coastguard Worker }
1319*9880d681SAndroid Build Coastguard Worker // Start reserving resources using existing DFAs.
1320*9880d681SAndroid Build Coastguard Worker for (unsigned C = 0; C < ReservedCycles; ++C) {
1321*9880d681SAndroid Build Coastguard Worker --RI;
1322*9880d681SAndroid Build Coastguard Worker (*RI)->reserveResources(*MI);
1323*9880d681SAndroid Build Coastguard Worker }
1324*9880d681SAndroid Build Coastguard Worker // Add new DFAs, if needed, to reserve resources.
1325*9880d681SAndroid Build Coastguard Worker for (unsigned C = ReservedCycles; C < NumCycles; ++C) {
1326*9880d681SAndroid Build Coastguard Worker DFAPacketizer *NewResource =
1327*9880d681SAndroid Build Coastguard Worker TII->CreateTargetScheduleState(MF.getSubtarget());
1328*9880d681SAndroid Build Coastguard Worker assert(NewResource->canReserveResources(*MI) && "Reserve error.");
1329*9880d681SAndroid Build Coastguard Worker NewResource->reserveResources(*MI);
1330*9880d681SAndroid Build Coastguard Worker Resources.push_back(NewResource);
1331*9880d681SAndroid Build Coastguard Worker }
1332*9880d681SAndroid Build Coastguard Worker }
1333*9880d681SAndroid Build Coastguard Worker int Resmii = Resources.size();
1334*9880d681SAndroid Build Coastguard Worker // Delete the memory for each of the DFAs that were created earlier.
1335*9880d681SAndroid Build Coastguard Worker for (DFAPacketizer *RI : Resources) {
1336*9880d681SAndroid Build Coastguard Worker DFAPacketizer *D = RI;
1337*9880d681SAndroid Build Coastguard Worker delete D;
1338*9880d681SAndroid Build Coastguard Worker }
1339*9880d681SAndroid Build Coastguard Worker Resources.clear();
1340*9880d681SAndroid Build Coastguard Worker return Resmii;
1341*9880d681SAndroid Build Coastguard Worker }
1342*9880d681SAndroid Build Coastguard Worker
1343*9880d681SAndroid Build Coastguard Worker /// Calculate the recurrence-constrainted minimum initiation interval.
1344*9880d681SAndroid Build Coastguard Worker /// Iterate over each circuit. Compute the delay(c) and distance(c)
1345*9880d681SAndroid Build Coastguard Worker /// for each circuit. The II needs to satisfy the inequality
1346*9880d681SAndroid Build Coastguard Worker /// delay(c) - II*distance(c) <= 0. For each circuit, choose the smallest
1347*9880d681SAndroid Build Coastguard Worker /// II that satistifies the inequality, and the RecMII is the maximum
1348*9880d681SAndroid Build Coastguard Worker /// of those values.
calculateRecMII(NodeSetType & NodeSets)1349*9880d681SAndroid Build Coastguard Worker unsigned SwingSchedulerDAG::calculateRecMII(NodeSetType &NodeSets) {
1350*9880d681SAndroid Build Coastguard Worker unsigned RecMII = 0;
1351*9880d681SAndroid Build Coastguard Worker
1352*9880d681SAndroid Build Coastguard Worker for (NodeSet &Nodes : NodeSets) {
1353*9880d681SAndroid Build Coastguard Worker if (Nodes.size() == 0)
1354*9880d681SAndroid Build Coastguard Worker continue;
1355*9880d681SAndroid Build Coastguard Worker
1356*9880d681SAndroid Build Coastguard Worker unsigned Delay = Nodes.size() - 1;
1357*9880d681SAndroid Build Coastguard Worker unsigned Distance = 1;
1358*9880d681SAndroid Build Coastguard Worker
1359*9880d681SAndroid Build Coastguard Worker // ii = ceil(delay / distance)
1360*9880d681SAndroid Build Coastguard Worker unsigned CurMII = (Delay + Distance - 1) / Distance;
1361*9880d681SAndroid Build Coastguard Worker Nodes.setRecMII(CurMII);
1362*9880d681SAndroid Build Coastguard Worker if (CurMII > RecMII)
1363*9880d681SAndroid Build Coastguard Worker RecMII = CurMII;
1364*9880d681SAndroid Build Coastguard Worker }
1365*9880d681SAndroid Build Coastguard Worker
1366*9880d681SAndroid Build Coastguard Worker return RecMII;
1367*9880d681SAndroid Build Coastguard Worker }
1368*9880d681SAndroid Build Coastguard Worker
1369*9880d681SAndroid Build Coastguard Worker /// Swap all the anti dependences in the DAG. That means it is no longer a DAG,
1370*9880d681SAndroid Build Coastguard Worker /// but we do this to find the circuits, and then change them back.
swapAntiDependences(std::vector<SUnit> & SUnits)1371*9880d681SAndroid Build Coastguard Worker static void swapAntiDependences(std::vector<SUnit> &SUnits) {
1372*9880d681SAndroid Build Coastguard Worker SmallVector<std::pair<SUnit *, SDep>, 8> DepsAdded;
1373*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = SUnits.size(); i != e; ++i) {
1374*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SUnits[i];
1375*9880d681SAndroid Build Coastguard Worker for (SUnit::pred_iterator IP = SU->Preds.begin(), EP = SU->Preds.end();
1376*9880d681SAndroid Build Coastguard Worker IP != EP; ++IP) {
1377*9880d681SAndroid Build Coastguard Worker if (IP->getKind() != SDep::Anti)
1378*9880d681SAndroid Build Coastguard Worker continue;
1379*9880d681SAndroid Build Coastguard Worker DepsAdded.push_back(std::make_pair(SU, *IP));
1380*9880d681SAndroid Build Coastguard Worker }
1381*9880d681SAndroid Build Coastguard Worker }
1382*9880d681SAndroid Build Coastguard Worker for (SmallVector<std::pair<SUnit *, SDep>, 8>::iterator I = DepsAdded.begin(),
1383*9880d681SAndroid Build Coastguard Worker E = DepsAdded.end();
1384*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1385*9880d681SAndroid Build Coastguard Worker // Remove this anti dependency and add one in the reverse direction.
1386*9880d681SAndroid Build Coastguard Worker SUnit *SU = I->first;
1387*9880d681SAndroid Build Coastguard Worker SDep &D = I->second;
1388*9880d681SAndroid Build Coastguard Worker SUnit *TargetSU = D.getSUnit();
1389*9880d681SAndroid Build Coastguard Worker unsigned Reg = D.getReg();
1390*9880d681SAndroid Build Coastguard Worker unsigned Lat = D.getLatency();
1391*9880d681SAndroid Build Coastguard Worker SU->removePred(D);
1392*9880d681SAndroid Build Coastguard Worker SDep Dep(SU, SDep::Anti, Reg);
1393*9880d681SAndroid Build Coastguard Worker Dep.setLatency(Lat);
1394*9880d681SAndroid Build Coastguard Worker TargetSU->addPred(Dep);
1395*9880d681SAndroid Build Coastguard Worker }
1396*9880d681SAndroid Build Coastguard Worker }
1397*9880d681SAndroid Build Coastguard Worker
1398*9880d681SAndroid Build Coastguard Worker /// Create the adjacency structure of the nodes in the graph.
createAdjacencyStructure(SwingSchedulerDAG * DAG)1399*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::Circuits::createAdjacencyStructure(
1400*9880d681SAndroid Build Coastguard Worker SwingSchedulerDAG *DAG) {
1401*9880d681SAndroid Build Coastguard Worker BitVector Added(SUnits.size());
1402*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = SUnits.size(); i != e; ++i) {
1403*9880d681SAndroid Build Coastguard Worker Added.reset();
1404*9880d681SAndroid Build Coastguard Worker // Add any successor to the adjacency matrix and exclude duplicates.
1405*9880d681SAndroid Build Coastguard Worker for (auto &SI : SUnits[i].Succs) {
1406*9880d681SAndroid Build Coastguard Worker // Do not process a boundary node and a back-edge is processed only
1407*9880d681SAndroid Build Coastguard Worker // if it goes to a Phi.
1408*9880d681SAndroid Build Coastguard Worker if (SI.getSUnit()->isBoundaryNode() ||
1409*9880d681SAndroid Build Coastguard Worker (SI.getKind() == SDep::Anti && !SI.getSUnit()->getInstr()->isPHI()))
1410*9880d681SAndroid Build Coastguard Worker continue;
1411*9880d681SAndroid Build Coastguard Worker int N = SI.getSUnit()->NodeNum;
1412*9880d681SAndroid Build Coastguard Worker if (!Added.test(N)) {
1413*9880d681SAndroid Build Coastguard Worker AdjK[i].push_back(N);
1414*9880d681SAndroid Build Coastguard Worker Added.set(N);
1415*9880d681SAndroid Build Coastguard Worker }
1416*9880d681SAndroid Build Coastguard Worker }
1417*9880d681SAndroid Build Coastguard Worker // A chain edge between a store and a load is treated as a back-edge in the
1418*9880d681SAndroid Build Coastguard Worker // adjacency matrix.
1419*9880d681SAndroid Build Coastguard Worker for (auto &PI : SUnits[i].Preds) {
1420*9880d681SAndroid Build Coastguard Worker if (!SUnits[i].getInstr()->mayStore() ||
1421*9880d681SAndroid Build Coastguard Worker !DAG->isLoopCarriedOrder(&SUnits[i], PI, false))
1422*9880d681SAndroid Build Coastguard Worker continue;
1423*9880d681SAndroid Build Coastguard Worker if (PI.getKind() == SDep::Order && PI.getSUnit()->getInstr()->mayLoad()) {
1424*9880d681SAndroid Build Coastguard Worker int N = PI.getSUnit()->NodeNum;
1425*9880d681SAndroid Build Coastguard Worker if (!Added.test(N)) {
1426*9880d681SAndroid Build Coastguard Worker AdjK[i].push_back(N);
1427*9880d681SAndroid Build Coastguard Worker Added.set(N);
1428*9880d681SAndroid Build Coastguard Worker }
1429*9880d681SAndroid Build Coastguard Worker }
1430*9880d681SAndroid Build Coastguard Worker }
1431*9880d681SAndroid Build Coastguard Worker }
1432*9880d681SAndroid Build Coastguard Worker }
1433*9880d681SAndroid Build Coastguard Worker
1434*9880d681SAndroid Build Coastguard Worker /// Identify an elementary circuit in the dependence graph starting at the
1435*9880d681SAndroid Build Coastguard Worker /// specified node.
circuit(int V,int S,NodeSetType & NodeSets,bool HasBackedge)1436*9880d681SAndroid Build Coastguard Worker bool SwingSchedulerDAG::Circuits::circuit(int V, int S, NodeSetType &NodeSets,
1437*9880d681SAndroid Build Coastguard Worker bool HasBackedge) {
1438*9880d681SAndroid Build Coastguard Worker SUnit *SV = &SUnits[V];
1439*9880d681SAndroid Build Coastguard Worker bool F = false;
1440*9880d681SAndroid Build Coastguard Worker Stack.insert(SV);
1441*9880d681SAndroid Build Coastguard Worker Blocked.set(V);
1442*9880d681SAndroid Build Coastguard Worker
1443*9880d681SAndroid Build Coastguard Worker for (auto W : AdjK[V]) {
1444*9880d681SAndroid Build Coastguard Worker if (NumPaths > MaxPaths)
1445*9880d681SAndroid Build Coastguard Worker break;
1446*9880d681SAndroid Build Coastguard Worker if (W < S)
1447*9880d681SAndroid Build Coastguard Worker continue;
1448*9880d681SAndroid Build Coastguard Worker if (W == S) {
1449*9880d681SAndroid Build Coastguard Worker if (!HasBackedge)
1450*9880d681SAndroid Build Coastguard Worker NodeSets.push_back(NodeSet(Stack.begin(), Stack.end()));
1451*9880d681SAndroid Build Coastguard Worker F = true;
1452*9880d681SAndroid Build Coastguard Worker ++NumPaths;
1453*9880d681SAndroid Build Coastguard Worker break;
1454*9880d681SAndroid Build Coastguard Worker } else if (!Blocked.test(W)) {
1455*9880d681SAndroid Build Coastguard Worker if (circuit(W, S, NodeSets, W < V ? true : HasBackedge))
1456*9880d681SAndroid Build Coastguard Worker F = true;
1457*9880d681SAndroid Build Coastguard Worker }
1458*9880d681SAndroid Build Coastguard Worker }
1459*9880d681SAndroid Build Coastguard Worker
1460*9880d681SAndroid Build Coastguard Worker if (F)
1461*9880d681SAndroid Build Coastguard Worker unblock(V);
1462*9880d681SAndroid Build Coastguard Worker else {
1463*9880d681SAndroid Build Coastguard Worker for (auto W : AdjK[V]) {
1464*9880d681SAndroid Build Coastguard Worker if (W < S)
1465*9880d681SAndroid Build Coastguard Worker continue;
1466*9880d681SAndroid Build Coastguard Worker if (B[W].count(SV) == 0)
1467*9880d681SAndroid Build Coastguard Worker B[W].insert(SV);
1468*9880d681SAndroid Build Coastguard Worker }
1469*9880d681SAndroid Build Coastguard Worker }
1470*9880d681SAndroid Build Coastguard Worker Stack.pop_back();
1471*9880d681SAndroid Build Coastguard Worker return F;
1472*9880d681SAndroid Build Coastguard Worker }
1473*9880d681SAndroid Build Coastguard Worker
1474*9880d681SAndroid Build Coastguard Worker /// Unblock a node in the circuit finding algorithm.
unblock(int U)1475*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::Circuits::unblock(int U) {
1476*9880d681SAndroid Build Coastguard Worker Blocked.reset(U);
1477*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 4> &BU = B[U];
1478*9880d681SAndroid Build Coastguard Worker while (!BU.empty()) {
1479*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 4>::iterator SI = BU.begin();
1480*9880d681SAndroid Build Coastguard Worker assert(SI != BU.end() && "Invalid B set.");
1481*9880d681SAndroid Build Coastguard Worker SUnit *W = *SI;
1482*9880d681SAndroid Build Coastguard Worker BU.erase(W);
1483*9880d681SAndroid Build Coastguard Worker if (Blocked.test(W->NodeNum))
1484*9880d681SAndroid Build Coastguard Worker unblock(W->NodeNum);
1485*9880d681SAndroid Build Coastguard Worker }
1486*9880d681SAndroid Build Coastguard Worker }
1487*9880d681SAndroid Build Coastguard Worker
1488*9880d681SAndroid Build Coastguard Worker /// Identify all the elementary circuits in the dependence graph using
1489*9880d681SAndroid Build Coastguard Worker /// Johnson's circuit algorithm.
findCircuits(NodeSetType & NodeSets)1490*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::findCircuits(NodeSetType &NodeSets) {
1491*9880d681SAndroid Build Coastguard Worker // Swap all the anti dependences in the DAG. That means it is no longer a DAG,
1492*9880d681SAndroid Build Coastguard Worker // but we do this to find the circuits, and then change them back.
1493*9880d681SAndroid Build Coastguard Worker swapAntiDependences(SUnits);
1494*9880d681SAndroid Build Coastguard Worker
1495*9880d681SAndroid Build Coastguard Worker Circuits Cir(SUnits);
1496*9880d681SAndroid Build Coastguard Worker // Create the adjacency structure.
1497*9880d681SAndroid Build Coastguard Worker Cir.createAdjacencyStructure(this);
1498*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = SUnits.size(); i != e; ++i) {
1499*9880d681SAndroid Build Coastguard Worker Cir.reset();
1500*9880d681SAndroid Build Coastguard Worker Cir.circuit(i, i, NodeSets);
1501*9880d681SAndroid Build Coastguard Worker }
1502*9880d681SAndroid Build Coastguard Worker
1503*9880d681SAndroid Build Coastguard Worker // Change the dependences back so that we've created a DAG again.
1504*9880d681SAndroid Build Coastguard Worker swapAntiDependences(SUnits);
1505*9880d681SAndroid Build Coastguard Worker }
1506*9880d681SAndroid Build Coastguard Worker
1507*9880d681SAndroid Build Coastguard Worker /// Return true for DAG nodes that we ignore when computing the cost functions.
1508*9880d681SAndroid Build Coastguard Worker /// We ignore the back-edge recurrence in order to avoid unbounded recurison
1509*9880d681SAndroid Build Coastguard Worker /// in the calculation of the ASAP, ALAP, etc functions.
ignoreDependence(const SDep & D,bool isPred)1510*9880d681SAndroid Build Coastguard Worker static bool ignoreDependence(const SDep &D, bool isPred) {
1511*9880d681SAndroid Build Coastguard Worker if (D.isArtificial())
1512*9880d681SAndroid Build Coastguard Worker return true;
1513*9880d681SAndroid Build Coastguard Worker return D.getKind() == SDep::Anti && isPred;
1514*9880d681SAndroid Build Coastguard Worker }
1515*9880d681SAndroid Build Coastguard Worker
1516*9880d681SAndroid Build Coastguard Worker /// Compute several functions need to order the nodes for scheduling.
1517*9880d681SAndroid Build Coastguard Worker /// ASAP - Earliest time to schedule a node.
1518*9880d681SAndroid Build Coastguard Worker /// ALAP - Latest time to schedule a node.
1519*9880d681SAndroid Build Coastguard Worker /// MOV - Mobility function, difference between ALAP and ASAP.
1520*9880d681SAndroid Build Coastguard Worker /// D - Depth of each node.
1521*9880d681SAndroid Build Coastguard Worker /// H - Height of each node.
computeNodeFunctions(NodeSetType & NodeSets)1522*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::computeNodeFunctions(NodeSetType &NodeSets) {
1523*9880d681SAndroid Build Coastguard Worker
1524*9880d681SAndroid Build Coastguard Worker ScheduleInfo.resize(SUnits.size());
1525*9880d681SAndroid Build Coastguard Worker
1526*9880d681SAndroid Build Coastguard Worker DEBUG({
1527*9880d681SAndroid Build Coastguard Worker for (ScheduleDAGTopologicalSort::const_iterator I = Topo.begin(),
1528*9880d681SAndroid Build Coastguard Worker E = Topo.end();
1529*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1530*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SUnits[*I];
1531*9880d681SAndroid Build Coastguard Worker SU->dump(this);
1532*9880d681SAndroid Build Coastguard Worker }
1533*9880d681SAndroid Build Coastguard Worker });
1534*9880d681SAndroid Build Coastguard Worker
1535*9880d681SAndroid Build Coastguard Worker int maxASAP = 0;
1536*9880d681SAndroid Build Coastguard Worker // Compute ASAP.
1537*9880d681SAndroid Build Coastguard Worker for (ScheduleDAGTopologicalSort::const_iterator I = Topo.begin(),
1538*9880d681SAndroid Build Coastguard Worker E = Topo.end();
1539*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1540*9880d681SAndroid Build Coastguard Worker int asap = 0;
1541*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SUnits[*I];
1542*9880d681SAndroid Build Coastguard Worker for (SUnit::const_pred_iterator IP = SU->Preds.begin(),
1543*9880d681SAndroid Build Coastguard Worker EP = SU->Preds.end();
1544*9880d681SAndroid Build Coastguard Worker IP != EP; ++IP) {
1545*9880d681SAndroid Build Coastguard Worker if (ignoreDependence(*IP, true))
1546*9880d681SAndroid Build Coastguard Worker continue;
1547*9880d681SAndroid Build Coastguard Worker SUnit *pred = IP->getSUnit();
1548*9880d681SAndroid Build Coastguard Worker asap = std::max(asap, (int)(getASAP(pred) + getLatency(SU, *IP) -
1549*9880d681SAndroid Build Coastguard Worker getDistance(pred, SU, *IP) * MII));
1550*9880d681SAndroid Build Coastguard Worker }
1551*9880d681SAndroid Build Coastguard Worker maxASAP = std::max(maxASAP, asap);
1552*9880d681SAndroid Build Coastguard Worker ScheduleInfo[*I].ASAP = asap;
1553*9880d681SAndroid Build Coastguard Worker }
1554*9880d681SAndroid Build Coastguard Worker
1555*9880d681SAndroid Build Coastguard Worker // Compute ALAP and MOV.
1556*9880d681SAndroid Build Coastguard Worker for (ScheduleDAGTopologicalSort::const_reverse_iterator I = Topo.rbegin(),
1557*9880d681SAndroid Build Coastguard Worker E = Topo.rend();
1558*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1559*9880d681SAndroid Build Coastguard Worker int alap = maxASAP;
1560*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SUnits[*I];
1561*9880d681SAndroid Build Coastguard Worker for (SUnit::const_succ_iterator IS = SU->Succs.begin(),
1562*9880d681SAndroid Build Coastguard Worker ES = SU->Succs.end();
1563*9880d681SAndroid Build Coastguard Worker IS != ES; ++IS) {
1564*9880d681SAndroid Build Coastguard Worker if (ignoreDependence(*IS, true))
1565*9880d681SAndroid Build Coastguard Worker continue;
1566*9880d681SAndroid Build Coastguard Worker SUnit *succ = IS->getSUnit();
1567*9880d681SAndroid Build Coastguard Worker alap = std::min(alap, (int)(getALAP(succ) - getLatency(SU, *IS) +
1568*9880d681SAndroid Build Coastguard Worker getDistance(SU, succ, *IS) * MII));
1569*9880d681SAndroid Build Coastguard Worker }
1570*9880d681SAndroid Build Coastguard Worker
1571*9880d681SAndroid Build Coastguard Worker ScheduleInfo[*I].ALAP = alap;
1572*9880d681SAndroid Build Coastguard Worker }
1573*9880d681SAndroid Build Coastguard Worker
1574*9880d681SAndroid Build Coastguard Worker // After computing the node functions, compute the summary for each node set.
1575*9880d681SAndroid Build Coastguard Worker for (NodeSet &I : NodeSets)
1576*9880d681SAndroid Build Coastguard Worker I.computeNodeSetInfo(this);
1577*9880d681SAndroid Build Coastguard Worker
1578*9880d681SAndroid Build Coastguard Worker DEBUG({
1579*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < SUnits.size(); i++) {
1580*9880d681SAndroid Build Coastguard Worker dbgs() << "\tNode " << i << ":\n";
1581*9880d681SAndroid Build Coastguard Worker dbgs() << "\t ASAP = " << getASAP(&SUnits[i]) << "\n";
1582*9880d681SAndroid Build Coastguard Worker dbgs() << "\t ALAP = " << getALAP(&SUnits[i]) << "\n";
1583*9880d681SAndroid Build Coastguard Worker dbgs() << "\t MOV = " << getMOV(&SUnits[i]) << "\n";
1584*9880d681SAndroid Build Coastguard Worker dbgs() << "\t D = " << getDepth(&SUnits[i]) << "\n";
1585*9880d681SAndroid Build Coastguard Worker dbgs() << "\t H = " << getHeight(&SUnits[i]) << "\n";
1586*9880d681SAndroid Build Coastguard Worker }
1587*9880d681SAndroid Build Coastguard Worker });
1588*9880d681SAndroid Build Coastguard Worker }
1589*9880d681SAndroid Build Coastguard Worker
1590*9880d681SAndroid Build Coastguard Worker /// Compute the Pred_L(O) set, as defined in the paper. The set is defined
1591*9880d681SAndroid Build Coastguard Worker /// as the predecessors of the elements of NodeOrder that are not also in
1592*9880d681SAndroid Build Coastguard Worker /// NodeOrder.
pred_L(SetVector<SUnit * > & NodeOrder,SmallSetVector<SUnit *,8> & Preds,const NodeSet * S=nullptr)1593*9880d681SAndroid Build Coastguard Worker static bool pred_L(SetVector<SUnit *> &NodeOrder,
1594*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> &Preds,
1595*9880d681SAndroid Build Coastguard Worker const NodeSet *S = nullptr) {
1596*9880d681SAndroid Build Coastguard Worker Preds.clear();
1597*9880d681SAndroid Build Coastguard Worker for (SetVector<SUnit *>::iterator I = NodeOrder.begin(), E = NodeOrder.end();
1598*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1599*9880d681SAndroid Build Coastguard Worker for (SUnit::pred_iterator PI = (*I)->Preds.begin(), PE = (*I)->Preds.end();
1600*9880d681SAndroid Build Coastguard Worker PI != PE; ++PI) {
1601*9880d681SAndroid Build Coastguard Worker if (S && S->count(PI->getSUnit()) == 0)
1602*9880d681SAndroid Build Coastguard Worker continue;
1603*9880d681SAndroid Build Coastguard Worker if (ignoreDependence(*PI, true))
1604*9880d681SAndroid Build Coastguard Worker continue;
1605*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(PI->getSUnit()) == 0)
1606*9880d681SAndroid Build Coastguard Worker Preds.insert(PI->getSUnit());
1607*9880d681SAndroid Build Coastguard Worker }
1608*9880d681SAndroid Build Coastguard Worker // Back-edges are predecessors with an anti-dependence.
1609*9880d681SAndroid Build Coastguard Worker for (SUnit::const_succ_iterator IS = (*I)->Succs.begin(),
1610*9880d681SAndroid Build Coastguard Worker ES = (*I)->Succs.end();
1611*9880d681SAndroid Build Coastguard Worker IS != ES; ++IS) {
1612*9880d681SAndroid Build Coastguard Worker if (IS->getKind() != SDep::Anti)
1613*9880d681SAndroid Build Coastguard Worker continue;
1614*9880d681SAndroid Build Coastguard Worker if (S && S->count(IS->getSUnit()) == 0)
1615*9880d681SAndroid Build Coastguard Worker continue;
1616*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(IS->getSUnit()) == 0)
1617*9880d681SAndroid Build Coastguard Worker Preds.insert(IS->getSUnit());
1618*9880d681SAndroid Build Coastguard Worker }
1619*9880d681SAndroid Build Coastguard Worker }
1620*9880d681SAndroid Build Coastguard Worker return Preds.size() > 0;
1621*9880d681SAndroid Build Coastguard Worker }
1622*9880d681SAndroid Build Coastguard Worker
1623*9880d681SAndroid Build Coastguard Worker /// Compute the Succ_L(O) set, as defined in the paper. The set is defined
1624*9880d681SAndroid Build Coastguard Worker /// as the successors of the elements of NodeOrder that are not also in
1625*9880d681SAndroid Build Coastguard Worker /// NodeOrder.
succ_L(SetVector<SUnit * > & NodeOrder,SmallSetVector<SUnit *,8> & Succs,const NodeSet * S=nullptr)1626*9880d681SAndroid Build Coastguard Worker static bool succ_L(SetVector<SUnit *> &NodeOrder,
1627*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> &Succs,
1628*9880d681SAndroid Build Coastguard Worker const NodeSet *S = nullptr) {
1629*9880d681SAndroid Build Coastguard Worker Succs.clear();
1630*9880d681SAndroid Build Coastguard Worker for (SetVector<SUnit *>::iterator I = NodeOrder.begin(), E = NodeOrder.end();
1631*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
1632*9880d681SAndroid Build Coastguard Worker for (SUnit::succ_iterator SI = (*I)->Succs.begin(), SE = (*I)->Succs.end();
1633*9880d681SAndroid Build Coastguard Worker SI != SE; ++SI) {
1634*9880d681SAndroid Build Coastguard Worker if (S && S->count(SI->getSUnit()) == 0)
1635*9880d681SAndroid Build Coastguard Worker continue;
1636*9880d681SAndroid Build Coastguard Worker if (ignoreDependence(*SI, false))
1637*9880d681SAndroid Build Coastguard Worker continue;
1638*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(SI->getSUnit()) == 0)
1639*9880d681SAndroid Build Coastguard Worker Succs.insert(SI->getSUnit());
1640*9880d681SAndroid Build Coastguard Worker }
1641*9880d681SAndroid Build Coastguard Worker for (SUnit::const_pred_iterator PI = (*I)->Preds.begin(),
1642*9880d681SAndroid Build Coastguard Worker PE = (*I)->Preds.end();
1643*9880d681SAndroid Build Coastguard Worker PI != PE; ++PI) {
1644*9880d681SAndroid Build Coastguard Worker if (PI->getKind() != SDep::Anti)
1645*9880d681SAndroid Build Coastguard Worker continue;
1646*9880d681SAndroid Build Coastguard Worker if (S && S->count(PI->getSUnit()) == 0)
1647*9880d681SAndroid Build Coastguard Worker continue;
1648*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(PI->getSUnit()) == 0)
1649*9880d681SAndroid Build Coastguard Worker Succs.insert(PI->getSUnit());
1650*9880d681SAndroid Build Coastguard Worker }
1651*9880d681SAndroid Build Coastguard Worker }
1652*9880d681SAndroid Build Coastguard Worker return Succs.size() > 0;
1653*9880d681SAndroid Build Coastguard Worker }
1654*9880d681SAndroid Build Coastguard Worker
1655*9880d681SAndroid Build Coastguard Worker /// Return true if there is a path from the specified node to any of the nodes
1656*9880d681SAndroid Build Coastguard Worker /// in DestNodes. Keep track and return the nodes in any path.
computePath(SUnit * Cur,SetVector<SUnit * > & Path,SetVector<SUnit * > & DestNodes,SetVector<SUnit * > & Exclude,SmallPtrSet<SUnit *,8> & Visited)1657*9880d681SAndroid Build Coastguard Worker static bool computePath(SUnit *Cur, SetVector<SUnit *> &Path,
1658*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> &DestNodes,
1659*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> &Exclude,
1660*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 8> &Visited) {
1661*9880d681SAndroid Build Coastguard Worker if (Cur->isBoundaryNode())
1662*9880d681SAndroid Build Coastguard Worker return false;
1663*9880d681SAndroid Build Coastguard Worker if (Exclude.count(Cur) != 0)
1664*9880d681SAndroid Build Coastguard Worker return false;
1665*9880d681SAndroid Build Coastguard Worker if (DestNodes.count(Cur) != 0)
1666*9880d681SAndroid Build Coastguard Worker return true;
1667*9880d681SAndroid Build Coastguard Worker if (!Visited.insert(Cur).second)
1668*9880d681SAndroid Build Coastguard Worker return Path.count(Cur) != 0;
1669*9880d681SAndroid Build Coastguard Worker bool FoundPath = false;
1670*9880d681SAndroid Build Coastguard Worker for (auto &SI : Cur->Succs)
1671*9880d681SAndroid Build Coastguard Worker FoundPath |= computePath(SI.getSUnit(), Path, DestNodes, Exclude, Visited);
1672*9880d681SAndroid Build Coastguard Worker for (auto &PI : Cur->Preds)
1673*9880d681SAndroid Build Coastguard Worker if (PI.getKind() == SDep::Anti)
1674*9880d681SAndroid Build Coastguard Worker FoundPath |=
1675*9880d681SAndroid Build Coastguard Worker computePath(PI.getSUnit(), Path, DestNodes, Exclude, Visited);
1676*9880d681SAndroid Build Coastguard Worker if (FoundPath)
1677*9880d681SAndroid Build Coastguard Worker Path.insert(Cur);
1678*9880d681SAndroid Build Coastguard Worker return FoundPath;
1679*9880d681SAndroid Build Coastguard Worker }
1680*9880d681SAndroid Build Coastguard Worker
1681*9880d681SAndroid Build Coastguard Worker /// Return true if Set1 is a subset of Set2.
isSubset(S1Ty & Set1,S2Ty & Set2)1682*9880d681SAndroid Build Coastguard Worker template <class S1Ty, class S2Ty> static bool isSubset(S1Ty &Set1, S2Ty &Set2) {
1683*9880d681SAndroid Build Coastguard Worker for (typename S1Ty::iterator I = Set1.begin(), E = Set1.end(); I != E; ++I)
1684*9880d681SAndroid Build Coastguard Worker if (Set2.count(*I) == 0)
1685*9880d681SAndroid Build Coastguard Worker return false;
1686*9880d681SAndroid Build Coastguard Worker return true;
1687*9880d681SAndroid Build Coastguard Worker }
1688*9880d681SAndroid Build Coastguard Worker
1689*9880d681SAndroid Build Coastguard Worker /// Compute the live-out registers for the instructions in a node-set.
1690*9880d681SAndroid Build Coastguard Worker /// The live-out registers are those that are defined in the node-set,
1691*9880d681SAndroid Build Coastguard Worker /// but not used. Except for use operands of Phis.
computeLiveOuts(MachineFunction & MF,RegPressureTracker & RPTracker,NodeSet & NS)1692*9880d681SAndroid Build Coastguard Worker static void computeLiveOuts(MachineFunction &MF, RegPressureTracker &RPTracker,
1693*9880d681SAndroid Build Coastguard Worker NodeSet &NS) {
1694*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
1695*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF.getRegInfo();
1696*9880d681SAndroid Build Coastguard Worker SmallVector<RegisterMaskPair, 8> LiveOutRegs;
1697*9880d681SAndroid Build Coastguard Worker SmallSet<unsigned, 4> Uses;
1698*9880d681SAndroid Build Coastguard Worker for (SUnit *SU : NS) {
1699*9880d681SAndroid Build Coastguard Worker const MachineInstr *MI = SU->getInstr();
1700*9880d681SAndroid Build Coastguard Worker if (MI->isPHI())
1701*9880d681SAndroid Build Coastguard Worker continue;
1702*9880d681SAndroid Build Coastguard Worker for (ConstMIOperands MO(*MI); MO.isValid(); ++MO)
1703*9880d681SAndroid Build Coastguard Worker if (MO->isReg() && MO->isUse()) {
1704*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO->getReg();
1705*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg))
1706*9880d681SAndroid Build Coastguard Worker Uses.insert(Reg);
1707*9880d681SAndroid Build Coastguard Worker else if (MRI.isAllocatable(Reg))
1708*9880d681SAndroid Build Coastguard Worker for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units)
1709*9880d681SAndroid Build Coastguard Worker Uses.insert(*Units);
1710*9880d681SAndroid Build Coastguard Worker }
1711*9880d681SAndroid Build Coastguard Worker }
1712*9880d681SAndroid Build Coastguard Worker for (SUnit *SU : NS)
1713*9880d681SAndroid Build Coastguard Worker for (ConstMIOperands MO(*SU->getInstr()); MO.isValid(); ++MO)
1714*9880d681SAndroid Build Coastguard Worker if (MO->isReg() && MO->isDef() && !MO->isDead()) {
1715*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO->getReg();
1716*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(Reg)) {
1717*9880d681SAndroid Build Coastguard Worker if (!Uses.count(Reg))
1718*9880d681SAndroid Build Coastguard Worker LiveOutRegs.push_back(RegisterMaskPair(Reg, 0));
1719*9880d681SAndroid Build Coastguard Worker } else if (MRI.isAllocatable(Reg)) {
1720*9880d681SAndroid Build Coastguard Worker for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units)
1721*9880d681SAndroid Build Coastguard Worker if (!Uses.count(*Units))
1722*9880d681SAndroid Build Coastguard Worker LiveOutRegs.push_back(RegisterMaskPair(*Units, 0));
1723*9880d681SAndroid Build Coastguard Worker }
1724*9880d681SAndroid Build Coastguard Worker }
1725*9880d681SAndroid Build Coastguard Worker RPTracker.addLiveRegs(LiveOutRegs);
1726*9880d681SAndroid Build Coastguard Worker }
1727*9880d681SAndroid Build Coastguard Worker
1728*9880d681SAndroid Build Coastguard Worker /// A heuristic to filter nodes in recurrent node-sets if the register
1729*9880d681SAndroid Build Coastguard Worker /// pressure of a set is too high.
registerPressureFilter(NodeSetType & NodeSets)1730*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::registerPressureFilter(NodeSetType &NodeSets) {
1731*9880d681SAndroid Build Coastguard Worker for (auto &NS : NodeSets) {
1732*9880d681SAndroid Build Coastguard Worker // Skip small node-sets since they won't cause register pressure problems.
1733*9880d681SAndroid Build Coastguard Worker if (NS.size() <= 2)
1734*9880d681SAndroid Build Coastguard Worker continue;
1735*9880d681SAndroid Build Coastguard Worker IntervalPressure RecRegPressure;
1736*9880d681SAndroid Build Coastguard Worker RegPressureTracker RecRPTracker(RecRegPressure);
1737*9880d681SAndroid Build Coastguard Worker RecRPTracker.init(&MF, &RegClassInfo, &LIS, BB, BB->end(), false, true);
1738*9880d681SAndroid Build Coastguard Worker computeLiveOuts(MF, RecRPTracker, NS);
1739*9880d681SAndroid Build Coastguard Worker RecRPTracker.closeBottom();
1740*9880d681SAndroid Build Coastguard Worker
1741*9880d681SAndroid Build Coastguard Worker std::vector<SUnit *> SUnits(NS.begin(), NS.end());
1742*9880d681SAndroid Build Coastguard Worker std::sort(SUnits.begin(), SUnits.end(), [](const SUnit *A, const SUnit *B) {
1743*9880d681SAndroid Build Coastguard Worker return A->NodeNum > B->NodeNum;
1744*9880d681SAndroid Build Coastguard Worker });
1745*9880d681SAndroid Build Coastguard Worker
1746*9880d681SAndroid Build Coastguard Worker for (auto &SU : SUnits) {
1747*9880d681SAndroid Build Coastguard Worker // Since we're computing the register pressure for a subset of the
1748*9880d681SAndroid Build Coastguard Worker // instructions in a block, we need to set the tracker for each
1749*9880d681SAndroid Build Coastguard Worker // instruction in the node-set. The tracker is set to the instruction
1750*9880d681SAndroid Build Coastguard Worker // just after the one we're interested in.
1751*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::const_iterator CurInstI = SU->getInstr();
1752*9880d681SAndroid Build Coastguard Worker RecRPTracker.setPos(std::next(CurInstI));
1753*9880d681SAndroid Build Coastguard Worker
1754*9880d681SAndroid Build Coastguard Worker RegPressureDelta RPDelta;
1755*9880d681SAndroid Build Coastguard Worker ArrayRef<PressureChange> CriticalPSets;
1756*9880d681SAndroid Build Coastguard Worker RecRPTracker.getMaxUpwardPressureDelta(SU->getInstr(), nullptr, RPDelta,
1757*9880d681SAndroid Build Coastguard Worker CriticalPSets,
1758*9880d681SAndroid Build Coastguard Worker RecRegPressure.MaxSetPressure);
1759*9880d681SAndroid Build Coastguard Worker if (RPDelta.Excess.isValid()) {
1760*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Excess register pressure: SU(" << SU->NodeNum << ") "
1761*9880d681SAndroid Build Coastguard Worker << TRI->getRegPressureSetName(RPDelta.Excess.getPSet())
1762*9880d681SAndroid Build Coastguard Worker << ":" << RPDelta.Excess.getUnitInc());
1763*9880d681SAndroid Build Coastguard Worker NS.setExceedPressure(SU);
1764*9880d681SAndroid Build Coastguard Worker break;
1765*9880d681SAndroid Build Coastguard Worker }
1766*9880d681SAndroid Build Coastguard Worker RecRPTracker.recede();
1767*9880d681SAndroid Build Coastguard Worker }
1768*9880d681SAndroid Build Coastguard Worker }
1769*9880d681SAndroid Build Coastguard Worker }
1770*9880d681SAndroid Build Coastguard Worker
1771*9880d681SAndroid Build Coastguard Worker /// A heuristic to colocate node sets that have the same set of
1772*9880d681SAndroid Build Coastguard Worker /// successors.
colocateNodeSets(NodeSetType & NodeSets)1773*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::colocateNodeSets(NodeSetType &NodeSets) {
1774*9880d681SAndroid Build Coastguard Worker unsigned Colocate = 0;
1775*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = NodeSets.size(); i < e; ++i) {
1776*9880d681SAndroid Build Coastguard Worker NodeSet &N1 = NodeSets[i];
1777*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> S1;
1778*9880d681SAndroid Build Coastguard Worker if (N1.empty() || !succ_L(N1, S1))
1779*9880d681SAndroid Build Coastguard Worker continue;
1780*9880d681SAndroid Build Coastguard Worker for (int j = i + 1; j < e; ++j) {
1781*9880d681SAndroid Build Coastguard Worker NodeSet &N2 = NodeSets[j];
1782*9880d681SAndroid Build Coastguard Worker if (N1.compareRecMII(N2) != 0)
1783*9880d681SAndroid Build Coastguard Worker continue;
1784*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> S2;
1785*9880d681SAndroid Build Coastguard Worker if (N2.empty() || !succ_L(N2, S2))
1786*9880d681SAndroid Build Coastguard Worker continue;
1787*9880d681SAndroid Build Coastguard Worker if (isSubset(S1, S2) && S1.size() == S2.size()) {
1788*9880d681SAndroid Build Coastguard Worker N1.setColocate(++Colocate);
1789*9880d681SAndroid Build Coastguard Worker N2.setColocate(Colocate);
1790*9880d681SAndroid Build Coastguard Worker break;
1791*9880d681SAndroid Build Coastguard Worker }
1792*9880d681SAndroid Build Coastguard Worker }
1793*9880d681SAndroid Build Coastguard Worker }
1794*9880d681SAndroid Build Coastguard Worker }
1795*9880d681SAndroid Build Coastguard Worker
1796*9880d681SAndroid Build Coastguard Worker /// Check if the existing node-sets are profitable. If not, then ignore the
1797*9880d681SAndroid Build Coastguard Worker /// recurrent node-sets, and attempt to schedule all nodes together. This is
1798*9880d681SAndroid Build Coastguard Worker /// a heuristic. If the MII is large and there is a non-recurrent node with
1799*9880d681SAndroid Build Coastguard Worker /// a large depth compared to the MII, then it's best to try and schedule
1800*9880d681SAndroid Build Coastguard Worker /// all instruction together instead of starting with the recurrent node-sets.
checkNodeSets(NodeSetType & NodeSets)1801*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::checkNodeSets(NodeSetType &NodeSets) {
1802*9880d681SAndroid Build Coastguard Worker // Look for loops with a large MII.
1803*9880d681SAndroid Build Coastguard Worker if (MII <= 20)
1804*9880d681SAndroid Build Coastguard Worker return;
1805*9880d681SAndroid Build Coastguard Worker // Check if the node-set contains only a simple add recurrence.
1806*9880d681SAndroid Build Coastguard Worker for (auto &NS : NodeSets)
1807*9880d681SAndroid Build Coastguard Worker if (NS.size() > 2)
1808*9880d681SAndroid Build Coastguard Worker return;
1809*9880d681SAndroid Build Coastguard Worker // If the depth of any instruction is significantly larger than the MII, then
1810*9880d681SAndroid Build Coastguard Worker // ignore the recurrent node-sets and treat all instructions equally.
1811*9880d681SAndroid Build Coastguard Worker for (auto &SU : SUnits)
1812*9880d681SAndroid Build Coastguard Worker if (SU.getDepth() > MII * 1.5) {
1813*9880d681SAndroid Build Coastguard Worker NodeSets.clear();
1814*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Clear recurrence node-sets\n");
1815*9880d681SAndroid Build Coastguard Worker return;
1816*9880d681SAndroid Build Coastguard Worker }
1817*9880d681SAndroid Build Coastguard Worker }
1818*9880d681SAndroid Build Coastguard Worker
1819*9880d681SAndroid Build Coastguard Worker /// Add the nodes that do not belong to a recurrence set into groups
1820*9880d681SAndroid Build Coastguard Worker /// based upon connected componenets.
groupRemainingNodes(NodeSetType & NodeSets)1821*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::groupRemainingNodes(NodeSetType &NodeSets) {
1822*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> NodesAdded;
1823*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 8> Visited;
1824*9880d681SAndroid Build Coastguard Worker // Add the nodes that are on a path between the previous node sets and
1825*9880d681SAndroid Build Coastguard Worker // the current node set.
1826*9880d681SAndroid Build Coastguard Worker for (NodeSet &I : NodeSets) {
1827*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> N;
1828*9880d681SAndroid Build Coastguard Worker // Add the nodes from the current node set to the previous node set.
1829*9880d681SAndroid Build Coastguard Worker if (succ_L(I, N)) {
1830*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> Path;
1831*9880d681SAndroid Build Coastguard Worker for (SUnit *NI : N) {
1832*9880d681SAndroid Build Coastguard Worker Visited.clear();
1833*9880d681SAndroid Build Coastguard Worker computePath(NI, Path, NodesAdded, I, Visited);
1834*9880d681SAndroid Build Coastguard Worker }
1835*9880d681SAndroid Build Coastguard Worker if (Path.size() > 0)
1836*9880d681SAndroid Build Coastguard Worker I.insert(Path.begin(), Path.end());
1837*9880d681SAndroid Build Coastguard Worker }
1838*9880d681SAndroid Build Coastguard Worker // Add the nodes from the previous node set to the current node set.
1839*9880d681SAndroid Build Coastguard Worker N.clear();
1840*9880d681SAndroid Build Coastguard Worker if (succ_L(NodesAdded, N)) {
1841*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> Path;
1842*9880d681SAndroid Build Coastguard Worker for (SUnit *NI : N) {
1843*9880d681SAndroid Build Coastguard Worker Visited.clear();
1844*9880d681SAndroid Build Coastguard Worker computePath(NI, Path, I, NodesAdded, Visited);
1845*9880d681SAndroid Build Coastguard Worker }
1846*9880d681SAndroid Build Coastguard Worker if (Path.size() > 0)
1847*9880d681SAndroid Build Coastguard Worker I.insert(Path.begin(), Path.end());
1848*9880d681SAndroid Build Coastguard Worker }
1849*9880d681SAndroid Build Coastguard Worker NodesAdded.insert(I.begin(), I.end());
1850*9880d681SAndroid Build Coastguard Worker }
1851*9880d681SAndroid Build Coastguard Worker
1852*9880d681SAndroid Build Coastguard Worker // Create a new node set with the connected nodes of any successor of a node
1853*9880d681SAndroid Build Coastguard Worker // in a recurrent set.
1854*9880d681SAndroid Build Coastguard Worker NodeSet NewSet;
1855*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> N;
1856*9880d681SAndroid Build Coastguard Worker if (succ_L(NodesAdded, N))
1857*9880d681SAndroid Build Coastguard Worker for (SUnit *I : N)
1858*9880d681SAndroid Build Coastguard Worker addConnectedNodes(I, NewSet, NodesAdded);
1859*9880d681SAndroid Build Coastguard Worker if (NewSet.size() > 0)
1860*9880d681SAndroid Build Coastguard Worker NodeSets.push_back(NewSet);
1861*9880d681SAndroid Build Coastguard Worker
1862*9880d681SAndroid Build Coastguard Worker // Create a new node set with the connected nodes of any predecessor of a node
1863*9880d681SAndroid Build Coastguard Worker // in a recurrent set.
1864*9880d681SAndroid Build Coastguard Worker NewSet.clear();
1865*9880d681SAndroid Build Coastguard Worker if (pred_L(NodesAdded, N))
1866*9880d681SAndroid Build Coastguard Worker for (SUnit *I : N)
1867*9880d681SAndroid Build Coastguard Worker addConnectedNodes(I, NewSet, NodesAdded);
1868*9880d681SAndroid Build Coastguard Worker if (NewSet.size() > 0)
1869*9880d681SAndroid Build Coastguard Worker NodeSets.push_back(NewSet);
1870*9880d681SAndroid Build Coastguard Worker
1871*9880d681SAndroid Build Coastguard Worker // Create new nodes sets with the connected nodes any any remaining node that
1872*9880d681SAndroid Build Coastguard Worker // has no predecessor.
1873*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < SUnits.size(); ++i) {
1874*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SUnits[i];
1875*9880d681SAndroid Build Coastguard Worker if (NodesAdded.count(SU) == 0) {
1876*9880d681SAndroid Build Coastguard Worker NewSet.clear();
1877*9880d681SAndroid Build Coastguard Worker addConnectedNodes(SU, NewSet, NodesAdded);
1878*9880d681SAndroid Build Coastguard Worker if (NewSet.size() > 0)
1879*9880d681SAndroid Build Coastguard Worker NodeSets.push_back(NewSet);
1880*9880d681SAndroid Build Coastguard Worker }
1881*9880d681SAndroid Build Coastguard Worker }
1882*9880d681SAndroid Build Coastguard Worker }
1883*9880d681SAndroid Build Coastguard Worker
1884*9880d681SAndroid Build Coastguard Worker /// Add the node to the set, and add all is its connected nodes to the set.
addConnectedNodes(SUnit * SU,NodeSet & NewSet,SetVector<SUnit * > & NodesAdded)1885*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::addConnectedNodes(SUnit *SU, NodeSet &NewSet,
1886*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *> &NodesAdded) {
1887*9880d681SAndroid Build Coastguard Worker NewSet.insert(SU);
1888*9880d681SAndroid Build Coastguard Worker NodesAdded.insert(SU);
1889*9880d681SAndroid Build Coastguard Worker for (auto &SI : SU->Succs) {
1890*9880d681SAndroid Build Coastguard Worker SUnit *Successor = SI.getSUnit();
1891*9880d681SAndroid Build Coastguard Worker if (!SI.isArtificial() && NodesAdded.count(Successor) == 0)
1892*9880d681SAndroid Build Coastguard Worker addConnectedNodes(Successor, NewSet, NodesAdded);
1893*9880d681SAndroid Build Coastguard Worker }
1894*9880d681SAndroid Build Coastguard Worker for (auto &PI : SU->Preds) {
1895*9880d681SAndroid Build Coastguard Worker SUnit *Predecessor = PI.getSUnit();
1896*9880d681SAndroid Build Coastguard Worker if (!PI.isArtificial() && NodesAdded.count(Predecessor) == 0)
1897*9880d681SAndroid Build Coastguard Worker addConnectedNodes(Predecessor, NewSet, NodesAdded);
1898*9880d681SAndroid Build Coastguard Worker }
1899*9880d681SAndroid Build Coastguard Worker }
1900*9880d681SAndroid Build Coastguard Worker
1901*9880d681SAndroid Build Coastguard Worker /// Return true if Set1 contains elements in Set2. The elements in common
1902*9880d681SAndroid Build Coastguard Worker /// are returned in a different container.
isIntersect(SmallSetVector<SUnit *,8> & Set1,const NodeSet & Set2,SmallSetVector<SUnit *,8> & Result)1903*9880d681SAndroid Build Coastguard Worker static bool isIntersect(SmallSetVector<SUnit *, 8> &Set1, const NodeSet &Set2,
1904*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> &Result) {
1905*9880d681SAndroid Build Coastguard Worker Result.clear();
1906*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Set1.size(); i != e; ++i) {
1907*9880d681SAndroid Build Coastguard Worker SUnit *SU = Set1[i];
1908*9880d681SAndroid Build Coastguard Worker if (Set2.count(SU) != 0)
1909*9880d681SAndroid Build Coastguard Worker Result.insert(SU);
1910*9880d681SAndroid Build Coastguard Worker }
1911*9880d681SAndroid Build Coastguard Worker return !Result.empty();
1912*9880d681SAndroid Build Coastguard Worker }
1913*9880d681SAndroid Build Coastguard Worker
1914*9880d681SAndroid Build Coastguard Worker /// Merge the recurrence node sets that have the same initial node.
fuseRecs(NodeSetType & NodeSets)1915*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::fuseRecs(NodeSetType &NodeSets) {
1916*9880d681SAndroid Build Coastguard Worker for (NodeSetType::iterator I = NodeSets.begin(), E = NodeSets.end(); I != E;
1917*9880d681SAndroid Build Coastguard Worker ++I) {
1918*9880d681SAndroid Build Coastguard Worker NodeSet &NI = *I;
1919*9880d681SAndroid Build Coastguard Worker for (NodeSetType::iterator J = I + 1; J != E;) {
1920*9880d681SAndroid Build Coastguard Worker NodeSet &NJ = *J;
1921*9880d681SAndroid Build Coastguard Worker if (NI.getNode(0)->NodeNum == NJ.getNode(0)->NodeNum) {
1922*9880d681SAndroid Build Coastguard Worker if (NJ.compareRecMII(NI) > 0)
1923*9880d681SAndroid Build Coastguard Worker NI.setRecMII(NJ.getRecMII());
1924*9880d681SAndroid Build Coastguard Worker for (NodeSet::iterator NII = J->begin(), ENI = J->end(); NII != ENI;
1925*9880d681SAndroid Build Coastguard Worker ++NII)
1926*9880d681SAndroid Build Coastguard Worker I->insert(*NII);
1927*9880d681SAndroid Build Coastguard Worker NodeSets.erase(J);
1928*9880d681SAndroid Build Coastguard Worker E = NodeSets.end();
1929*9880d681SAndroid Build Coastguard Worker } else {
1930*9880d681SAndroid Build Coastguard Worker ++J;
1931*9880d681SAndroid Build Coastguard Worker }
1932*9880d681SAndroid Build Coastguard Worker }
1933*9880d681SAndroid Build Coastguard Worker }
1934*9880d681SAndroid Build Coastguard Worker }
1935*9880d681SAndroid Build Coastguard Worker
1936*9880d681SAndroid Build Coastguard Worker /// Remove nodes that have been scheduled in previous NodeSets.
removeDuplicateNodes(NodeSetType & NodeSets)1937*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::removeDuplicateNodes(NodeSetType &NodeSets) {
1938*9880d681SAndroid Build Coastguard Worker for (NodeSetType::iterator I = NodeSets.begin(), E = NodeSets.end(); I != E;
1939*9880d681SAndroid Build Coastguard Worker ++I)
1940*9880d681SAndroid Build Coastguard Worker for (NodeSetType::iterator J = I + 1; J != E;) {
1941*9880d681SAndroid Build Coastguard Worker J->remove_if([&](SUnit *SUJ) { return I->count(SUJ); });
1942*9880d681SAndroid Build Coastguard Worker
1943*9880d681SAndroid Build Coastguard Worker if (J->size() == 0) {
1944*9880d681SAndroid Build Coastguard Worker NodeSets.erase(J);
1945*9880d681SAndroid Build Coastguard Worker E = NodeSets.end();
1946*9880d681SAndroid Build Coastguard Worker } else {
1947*9880d681SAndroid Build Coastguard Worker ++J;
1948*9880d681SAndroid Build Coastguard Worker }
1949*9880d681SAndroid Build Coastguard Worker }
1950*9880d681SAndroid Build Coastguard Worker }
1951*9880d681SAndroid Build Coastguard Worker
1952*9880d681SAndroid Build Coastguard Worker /// Return true if Inst1 defines a value that is used in Inst2.
hasDataDependence(SUnit * Inst1,SUnit * Inst2)1953*9880d681SAndroid Build Coastguard Worker static bool hasDataDependence(SUnit *Inst1, SUnit *Inst2) {
1954*9880d681SAndroid Build Coastguard Worker for (auto &SI : Inst1->Succs)
1955*9880d681SAndroid Build Coastguard Worker if (SI.getSUnit() == Inst2 && SI.getKind() == SDep::Data)
1956*9880d681SAndroid Build Coastguard Worker return true;
1957*9880d681SAndroid Build Coastguard Worker return false;
1958*9880d681SAndroid Build Coastguard Worker }
1959*9880d681SAndroid Build Coastguard Worker
1960*9880d681SAndroid Build Coastguard Worker /// Compute an ordered list of the dependence graph nodes, which
1961*9880d681SAndroid Build Coastguard Worker /// indicates the order that the nodes will be scheduled. This is a
1962*9880d681SAndroid Build Coastguard Worker /// two-level algorithm. First, a partial order is created, which
1963*9880d681SAndroid Build Coastguard Worker /// consists of a list of sets ordered from highest to lowest priority.
computeNodeOrder(NodeSetType & NodeSets)1964*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::computeNodeOrder(NodeSetType &NodeSets) {
1965*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> R;
1966*9880d681SAndroid Build Coastguard Worker NodeOrder.clear();
1967*9880d681SAndroid Build Coastguard Worker
1968*9880d681SAndroid Build Coastguard Worker for (auto &Nodes : NodeSets) {
1969*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "NodeSet size " << Nodes.size() << "\n");
1970*9880d681SAndroid Build Coastguard Worker OrderKind Order;
1971*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> N;
1972*9880d681SAndroid Build Coastguard Worker if (pred_L(NodeOrder, N) && isSubset(N, Nodes)) {
1973*9880d681SAndroid Build Coastguard Worker R.insert(N.begin(), N.end());
1974*9880d681SAndroid Build Coastguard Worker Order = BottomUp;
1975*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Bottom up (preds) ");
1976*9880d681SAndroid Build Coastguard Worker } else if (succ_L(NodeOrder, N) && isSubset(N, Nodes)) {
1977*9880d681SAndroid Build Coastguard Worker R.insert(N.begin(), N.end());
1978*9880d681SAndroid Build Coastguard Worker Order = TopDown;
1979*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Top down (succs) ");
1980*9880d681SAndroid Build Coastguard Worker } else if (isIntersect(N, Nodes, R)) {
1981*9880d681SAndroid Build Coastguard Worker // If some of the successors are in the existing node-set, then use the
1982*9880d681SAndroid Build Coastguard Worker // top-down ordering.
1983*9880d681SAndroid Build Coastguard Worker Order = TopDown;
1984*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Top down (intersect) ");
1985*9880d681SAndroid Build Coastguard Worker } else if (NodeSets.size() == 1) {
1986*9880d681SAndroid Build Coastguard Worker for (auto &N : Nodes)
1987*9880d681SAndroid Build Coastguard Worker if (N->Succs.size() == 0)
1988*9880d681SAndroid Build Coastguard Worker R.insert(N);
1989*9880d681SAndroid Build Coastguard Worker Order = BottomUp;
1990*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Bottom up (all) ");
1991*9880d681SAndroid Build Coastguard Worker } else {
1992*9880d681SAndroid Build Coastguard Worker // Find the node with the highest ASAP.
1993*9880d681SAndroid Build Coastguard Worker SUnit *maxASAP = nullptr;
1994*9880d681SAndroid Build Coastguard Worker for (SUnit *SU : Nodes) {
1995*9880d681SAndroid Build Coastguard Worker if (maxASAP == nullptr || getASAP(SU) >= getASAP(maxASAP))
1996*9880d681SAndroid Build Coastguard Worker maxASAP = SU;
1997*9880d681SAndroid Build Coastguard Worker }
1998*9880d681SAndroid Build Coastguard Worker R.insert(maxASAP);
1999*9880d681SAndroid Build Coastguard Worker Order = BottomUp;
2000*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << " Bottom up (default) ");
2001*9880d681SAndroid Build Coastguard Worker }
2002*9880d681SAndroid Build Coastguard Worker
2003*9880d681SAndroid Build Coastguard Worker while (!R.empty()) {
2004*9880d681SAndroid Build Coastguard Worker if (Order == TopDown) {
2005*9880d681SAndroid Build Coastguard Worker // Choose the node with the maximum height. If more than one, choose
2006*9880d681SAndroid Build Coastguard Worker // the node with the lowest MOV. If still more than one, check if there
2007*9880d681SAndroid Build Coastguard Worker // is a dependence between the instructions.
2008*9880d681SAndroid Build Coastguard Worker while (!R.empty()) {
2009*9880d681SAndroid Build Coastguard Worker SUnit *maxHeight = nullptr;
2010*9880d681SAndroid Build Coastguard Worker for (SUnit *I : R) {
2011*9880d681SAndroid Build Coastguard Worker if (maxHeight == 0 || getHeight(I) > getHeight(maxHeight))
2012*9880d681SAndroid Build Coastguard Worker maxHeight = I;
2013*9880d681SAndroid Build Coastguard Worker else if (getHeight(I) == getHeight(maxHeight) &&
2014*9880d681SAndroid Build Coastguard Worker getMOV(I) < getMOV(maxHeight) &&
2015*9880d681SAndroid Build Coastguard Worker !hasDataDependence(maxHeight, I))
2016*9880d681SAndroid Build Coastguard Worker maxHeight = I;
2017*9880d681SAndroid Build Coastguard Worker else if (hasDataDependence(I, maxHeight))
2018*9880d681SAndroid Build Coastguard Worker maxHeight = I;
2019*9880d681SAndroid Build Coastguard Worker }
2020*9880d681SAndroid Build Coastguard Worker NodeOrder.insert(maxHeight);
2021*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << maxHeight->NodeNum << " ");
2022*9880d681SAndroid Build Coastguard Worker R.remove(maxHeight);
2023*9880d681SAndroid Build Coastguard Worker for (const auto &I : maxHeight->Succs) {
2024*9880d681SAndroid Build Coastguard Worker if (Nodes.count(I.getSUnit()) == 0)
2025*9880d681SAndroid Build Coastguard Worker continue;
2026*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(I.getSUnit()) != 0)
2027*9880d681SAndroid Build Coastguard Worker continue;
2028*9880d681SAndroid Build Coastguard Worker if (ignoreDependence(I, false))
2029*9880d681SAndroid Build Coastguard Worker continue;
2030*9880d681SAndroid Build Coastguard Worker R.insert(I.getSUnit());
2031*9880d681SAndroid Build Coastguard Worker }
2032*9880d681SAndroid Build Coastguard Worker // Back-edges are predecessors with an anti-dependence.
2033*9880d681SAndroid Build Coastguard Worker for (const auto &I : maxHeight->Preds) {
2034*9880d681SAndroid Build Coastguard Worker if (I.getKind() != SDep::Anti)
2035*9880d681SAndroid Build Coastguard Worker continue;
2036*9880d681SAndroid Build Coastguard Worker if (Nodes.count(I.getSUnit()) == 0)
2037*9880d681SAndroid Build Coastguard Worker continue;
2038*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(I.getSUnit()) != 0)
2039*9880d681SAndroid Build Coastguard Worker continue;
2040*9880d681SAndroid Build Coastguard Worker R.insert(I.getSUnit());
2041*9880d681SAndroid Build Coastguard Worker }
2042*9880d681SAndroid Build Coastguard Worker }
2043*9880d681SAndroid Build Coastguard Worker Order = BottomUp;
2044*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n Switching order to bottom up ");
2045*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> N;
2046*9880d681SAndroid Build Coastguard Worker if (pred_L(NodeOrder, N, &Nodes))
2047*9880d681SAndroid Build Coastguard Worker R.insert(N.begin(), N.end());
2048*9880d681SAndroid Build Coastguard Worker } else {
2049*9880d681SAndroid Build Coastguard Worker // Choose the node with the maximum depth. If more than one, choose
2050*9880d681SAndroid Build Coastguard Worker // the node with the lowest MOV. If there is still more than one, check
2051*9880d681SAndroid Build Coastguard Worker // for a dependence between the instructions.
2052*9880d681SAndroid Build Coastguard Worker while (!R.empty()) {
2053*9880d681SAndroid Build Coastguard Worker SUnit *maxDepth = nullptr;
2054*9880d681SAndroid Build Coastguard Worker for (SUnit *I : R) {
2055*9880d681SAndroid Build Coastguard Worker if (maxDepth == 0 || getDepth(I) > getDepth(maxDepth))
2056*9880d681SAndroid Build Coastguard Worker maxDepth = I;
2057*9880d681SAndroid Build Coastguard Worker else if (getDepth(I) == getDepth(maxDepth) &&
2058*9880d681SAndroid Build Coastguard Worker getMOV(I) < getMOV(maxDepth) &&
2059*9880d681SAndroid Build Coastguard Worker !hasDataDependence(I, maxDepth))
2060*9880d681SAndroid Build Coastguard Worker maxDepth = I;
2061*9880d681SAndroid Build Coastguard Worker else if (hasDataDependence(maxDepth, I))
2062*9880d681SAndroid Build Coastguard Worker maxDepth = I;
2063*9880d681SAndroid Build Coastguard Worker }
2064*9880d681SAndroid Build Coastguard Worker NodeOrder.insert(maxDepth);
2065*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << maxDepth->NodeNum << " ");
2066*9880d681SAndroid Build Coastguard Worker R.remove(maxDepth);
2067*9880d681SAndroid Build Coastguard Worker if (Nodes.isExceedSU(maxDepth)) {
2068*9880d681SAndroid Build Coastguard Worker Order = TopDown;
2069*9880d681SAndroid Build Coastguard Worker R.clear();
2070*9880d681SAndroid Build Coastguard Worker R.insert(Nodes.getNode(0));
2071*9880d681SAndroid Build Coastguard Worker break;
2072*9880d681SAndroid Build Coastguard Worker }
2073*9880d681SAndroid Build Coastguard Worker for (const auto &I : maxDepth->Preds) {
2074*9880d681SAndroid Build Coastguard Worker if (Nodes.count(I.getSUnit()) == 0)
2075*9880d681SAndroid Build Coastguard Worker continue;
2076*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(I.getSUnit()) != 0)
2077*9880d681SAndroid Build Coastguard Worker continue;
2078*9880d681SAndroid Build Coastguard Worker if (I.getKind() == SDep::Anti)
2079*9880d681SAndroid Build Coastguard Worker continue;
2080*9880d681SAndroid Build Coastguard Worker R.insert(I.getSUnit());
2081*9880d681SAndroid Build Coastguard Worker }
2082*9880d681SAndroid Build Coastguard Worker // Back-edges are predecessors with an anti-dependence.
2083*9880d681SAndroid Build Coastguard Worker for (const auto &I : maxDepth->Succs) {
2084*9880d681SAndroid Build Coastguard Worker if (I.getKind() != SDep::Anti)
2085*9880d681SAndroid Build Coastguard Worker continue;
2086*9880d681SAndroid Build Coastguard Worker if (Nodes.count(I.getSUnit()) == 0)
2087*9880d681SAndroid Build Coastguard Worker continue;
2088*9880d681SAndroid Build Coastguard Worker if (NodeOrder.count(I.getSUnit()) != 0)
2089*9880d681SAndroid Build Coastguard Worker continue;
2090*9880d681SAndroid Build Coastguard Worker R.insert(I.getSUnit());
2091*9880d681SAndroid Build Coastguard Worker }
2092*9880d681SAndroid Build Coastguard Worker }
2093*9880d681SAndroid Build Coastguard Worker Order = TopDown;
2094*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\n Switching order to top down ");
2095*9880d681SAndroid Build Coastguard Worker SmallSetVector<SUnit *, 8> N;
2096*9880d681SAndroid Build Coastguard Worker if (succ_L(NodeOrder, N, &Nodes))
2097*9880d681SAndroid Build Coastguard Worker R.insert(N.begin(), N.end());
2098*9880d681SAndroid Build Coastguard Worker }
2099*9880d681SAndroid Build Coastguard Worker }
2100*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "\nDone with Nodeset\n");
2101*9880d681SAndroid Build Coastguard Worker }
2102*9880d681SAndroid Build Coastguard Worker
2103*9880d681SAndroid Build Coastguard Worker DEBUG({
2104*9880d681SAndroid Build Coastguard Worker dbgs() << "Node order: ";
2105*9880d681SAndroid Build Coastguard Worker for (SUnit *I : NodeOrder)
2106*9880d681SAndroid Build Coastguard Worker dbgs() << " " << I->NodeNum << " ";
2107*9880d681SAndroid Build Coastguard Worker dbgs() << "\n";
2108*9880d681SAndroid Build Coastguard Worker });
2109*9880d681SAndroid Build Coastguard Worker }
2110*9880d681SAndroid Build Coastguard Worker
2111*9880d681SAndroid Build Coastguard Worker /// Process the nodes in the computed order and create the pipelined schedule
2112*9880d681SAndroid Build Coastguard Worker /// of the instructions, if possible. Return true if a schedule is found.
schedulePipeline(SMSchedule & Schedule)2113*9880d681SAndroid Build Coastguard Worker bool SwingSchedulerDAG::schedulePipeline(SMSchedule &Schedule) {
2114*9880d681SAndroid Build Coastguard Worker
2115*9880d681SAndroid Build Coastguard Worker if (NodeOrder.size() == 0)
2116*9880d681SAndroid Build Coastguard Worker return false;
2117*9880d681SAndroid Build Coastguard Worker
2118*9880d681SAndroid Build Coastguard Worker bool scheduleFound = false;
2119*9880d681SAndroid Build Coastguard Worker // Keep increasing II until a valid schedule is found.
2120*9880d681SAndroid Build Coastguard Worker for (unsigned II = MII; II < MII + 10 && !scheduleFound; ++II) {
2121*9880d681SAndroid Build Coastguard Worker Schedule.reset();
2122*9880d681SAndroid Build Coastguard Worker Schedule.setInitiationInterval(II);
2123*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Try to schedule with " << II << "\n");
2124*9880d681SAndroid Build Coastguard Worker
2125*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *>::iterator NI = NodeOrder.begin();
2126*9880d681SAndroid Build Coastguard Worker SetVector<SUnit *>::iterator NE = NodeOrder.end();
2127*9880d681SAndroid Build Coastguard Worker do {
2128*9880d681SAndroid Build Coastguard Worker SUnit *SU = *NI;
2129*9880d681SAndroid Build Coastguard Worker
2130*9880d681SAndroid Build Coastguard Worker // Compute the schedule time for the instruction, which is based
2131*9880d681SAndroid Build Coastguard Worker // upon the scheduled time for any predecessors/successors.
2132*9880d681SAndroid Build Coastguard Worker int EarlyStart = INT_MIN;
2133*9880d681SAndroid Build Coastguard Worker int LateStart = INT_MAX;
2134*9880d681SAndroid Build Coastguard Worker // These values are set when the size of the schedule window is limited
2135*9880d681SAndroid Build Coastguard Worker // due to chain dependences.
2136*9880d681SAndroid Build Coastguard Worker int SchedEnd = INT_MAX;
2137*9880d681SAndroid Build Coastguard Worker int SchedStart = INT_MIN;
2138*9880d681SAndroid Build Coastguard Worker Schedule.computeStart(SU, &EarlyStart, &LateStart, &SchedEnd, &SchedStart,
2139*9880d681SAndroid Build Coastguard Worker II, this);
2140*9880d681SAndroid Build Coastguard Worker DEBUG({
2141*9880d681SAndroid Build Coastguard Worker dbgs() << "Inst (" << SU->NodeNum << ") ";
2142*9880d681SAndroid Build Coastguard Worker SU->getInstr()->dump();
2143*9880d681SAndroid Build Coastguard Worker dbgs() << "\n";
2144*9880d681SAndroid Build Coastguard Worker });
2145*9880d681SAndroid Build Coastguard Worker DEBUG({
2146*9880d681SAndroid Build Coastguard Worker dbgs() << "\tes: " << EarlyStart << " ls: " << LateStart
2147*9880d681SAndroid Build Coastguard Worker << " me: " << SchedEnd << " ms: " << SchedStart << "\n";
2148*9880d681SAndroid Build Coastguard Worker });
2149*9880d681SAndroid Build Coastguard Worker
2150*9880d681SAndroid Build Coastguard Worker if (EarlyStart > LateStart || SchedEnd < EarlyStart ||
2151*9880d681SAndroid Build Coastguard Worker SchedStart > LateStart)
2152*9880d681SAndroid Build Coastguard Worker scheduleFound = false;
2153*9880d681SAndroid Build Coastguard Worker else if (EarlyStart != INT_MIN && LateStart == INT_MAX) {
2154*9880d681SAndroid Build Coastguard Worker SchedEnd = std::min(SchedEnd, EarlyStart + (int)II - 1);
2155*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.insert(SU, EarlyStart, SchedEnd, II);
2156*9880d681SAndroid Build Coastguard Worker } else if (EarlyStart == INT_MIN && LateStart != INT_MAX) {
2157*9880d681SAndroid Build Coastguard Worker SchedStart = std::max(SchedStart, LateStart - (int)II + 1);
2158*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.insert(SU, LateStart, SchedStart, II);
2159*9880d681SAndroid Build Coastguard Worker } else if (EarlyStart != INT_MIN && LateStart != INT_MAX) {
2160*9880d681SAndroid Build Coastguard Worker SchedEnd =
2161*9880d681SAndroid Build Coastguard Worker std::min(SchedEnd, std::min(LateStart, EarlyStart + (int)II - 1));
2162*9880d681SAndroid Build Coastguard Worker // When scheduling a Phi it is better to start at the late cycle and go
2163*9880d681SAndroid Build Coastguard Worker // backwards. The default order may insert the Phi too far away from
2164*9880d681SAndroid Build Coastguard Worker // its first dependence.
2165*9880d681SAndroid Build Coastguard Worker if (SU->getInstr()->isPHI())
2166*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.insert(SU, SchedEnd, EarlyStart, II);
2167*9880d681SAndroid Build Coastguard Worker else
2168*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.insert(SU, EarlyStart, SchedEnd, II);
2169*9880d681SAndroid Build Coastguard Worker } else {
2170*9880d681SAndroid Build Coastguard Worker int FirstCycle = Schedule.getFirstCycle();
2171*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.insert(SU, FirstCycle + getASAP(SU),
2172*9880d681SAndroid Build Coastguard Worker FirstCycle + getASAP(SU) + II - 1, II);
2173*9880d681SAndroid Build Coastguard Worker }
2174*9880d681SAndroid Build Coastguard Worker // Even if we find a schedule, make sure the schedule doesn't exceed the
2175*9880d681SAndroid Build Coastguard Worker // allowable number of stages. We keep trying if this happens.
2176*9880d681SAndroid Build Coastguard Worker if (scheduleFound)
2177*9880d681SAndroid Build Coastguard Worker if (SwpMaxStages > -1 &&
2178*9880d681SAndroid Build Coastguard Worker Schedule.getMaxStageCount() > (unsigned)SwpMaxStages)
2179*9880d681SAndroid Build Coastguard Worker scheduleFound = false;
2180*9880d681SAndroid Build Coastguard Worker
2181*9880d681SAndroid Build Coastguard Worker DEBUG({
2182*9880d681SAndroid Build Coastguard Worker if (!scheduleFound)
2183*9880d681SAndroid Build Coastguard Worker dbgs() << "\tCan't schedule\n";
2184*9880d681SAndroid Build Coastguard Worker });
2185*9880d681SAndroid Build Coastguard Worker } while (++NI != NE && scheduleFound);
2186*9880d681SAndroid Build Coastguard Worker
2187*9880d681SAndroid Build Coastguard Worker // If a schedule is found, check if it is a valid schedule too.
2188*9880d681SAndroid Build Coastguard Worker if (scheduleFound)
2189*9880d681SAndroid Build Coastguard Worker scheduleFound = Schedule.isValidSchedule(this);
2190*9880d681SAndroid Build Coastguard Worker }
2191*9880d681SAndroid Build Coastguard Worker
2192*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Schedule Found? " << scheduleFound << "\n");
2193*9880d681SAndroid Build Coastguard Worker
2194*9880d681SAndroid Build Coastguard Worker if (scheduleFound)
2195*9880d681SAndroid Build Coastguard Worker Schedule.finalizeSchedule(this);
2196*9880d681SAndroid Build Coastguard Worker else
2197*9880d681SAndroid Build Coastguard Worker Schedule.reset();
2198*9880d681SAndroid Build Coastguard Worker
2199*9880d681SAndroid Build Coastguard Worker return scheduleFound && Schedule.getMaxStageCount() > 0;
2200*9880d681SAndroid Build Coastguard Worker }
2201*9880d681SAndroid Build Coastguard Worker
2202*9880d681SAndroid Build Coastguard Worker /// Given a schedule for the loop, generate a new version of the loop,
2203*9880d681SAndroid Build Coastguard Worker /// and replace the old version. This function generates a prolog
2204*9880d681SAndroid Build Coastguard Worker /// that contains the initial iterations in the pipeline, and kernel
2205*9880d681SAndroid Build Coastguard Worker /// loop, and the epilogue that contains the code for the final
2206*9880d681SAndroid Build Coastguard Worker /// iterations.
generatePipelinedLoop(SMSchedule & Schedule)2207*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::generatePipelinedLoop(SMSchedule &Schedule) {
2208*9880d681SAndroid Build Coastguard Worker // Create a new basic block for the kernel and add it to the CFG.
2209*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB = MF.CreateMachineBasicBlock(BB->getBasicBlock());
2210*9880d681SAndroid Build Coastguard Worker
2211*9880d681SAndroid Build Coastguard Worker unsigned MaxStageCount = Schedule.getMaxStageCount();
2212*9880d681SAndroid Build Coastguard Worker
2213*9880d681SAndroid Build Coastguard Worker // Remember the registers that are used in different stages. The index is
2214*9880d681SAndroid Build Coastguard Worker // the iteration, or stage, that the instruction is scheduled in. This is
2215*9880d681SAndroid Build Coastguard Worker // a map between register names in the orignal block and the names created
2216*9880d681SAndroid Build Coastguard Worker // in each stage of the pipelined loop.
2217*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap = new ValueMapTy[(MaxStageCount + 1) * 2];
2218*9880d681SAndroid Build Coastguard Worker InstrMapTy InstrMap;
2219*9880d681SAndroid Build Coastguard Worker
2220*9880d681SAndroid Build Coastguard Worker SmallVector<MachineBasicBlock *, 4> PrologBBs;
2221*9880d681SAndroid Build Coastguard Worker // Generate the prolog instructions that set up the pipeline.
2222*9880d681SAndroid Build Coastguard Worker generateProlog(Schedule, MaxStageCount, KernelBB, VRMap, PrologBBs);
2223*9880d681SAndroid Build Coastguard Worker MF.insert(BB->getIterator(), KernelBB);
2224*9880d681SAndroid Build Coastguard Worker
2225*9880d681SAndroid Build Coastguard Worker // Rearrange the instructions to generate the new, pipelined loop,
2226*9880d681SAndroid Build Coastguard Worker // and update register names as needed.
2227*9880d681SAndroid Build Coastguard Worker for (int Cycle = Schedule.getFirstCycle(),
2228*9880d681SAndroid Build Coastguard Worker LastCycle = Schedule.getFinalCycle();
2229*9880d681SAndroid Build Coastguard Worker Cycle <= LastCycle; ++Cycle) {
2230*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &CycleInstrs = Schedule.getInstructions(Cycle);
2231*9880d681SAndroid Build Coastguard Worker // This inner loop schedules each instruction in the cycle.
2232*9880d681SAndroid Build Coastguard Worker for (SUnit *CI : CycleInstrs) {
2233*9880d681SAndroid Build Coastguard Worker if (CI->getInstr()->isPHI())
2234*9880d681SAndroid Build Coastguard Worker continue;
2235*9880d681SAndroid Build Coastguard Worker unsigned StageNum = Schedule.stageScheduled(getSUnit(CI->getInstr()));
2236*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = cloneInstr(CI->getInstr(), MaxStageCount, StageNum);
2237*9880d681SAndroid Build Coastguard Worker updateInstruction(NewMI, false, MaxStageCount, StageNum, Schedule, VRMap);
2238*9880d681SAndroid Build Coastguard Worker KernelBB->push_back(NewMI);
2239*9880d681SAndroid Build Coastguard Worker InstrMap[NewMI] = CI->getInstr();
2240*9880d681SAndroid Build Coastguard Worker }
2241*9880d681SAndroid Build Coastguard Worker }
2242*9880d681SAndroid Build Coastguard Worker
2243*9880d681SAndroid Build Coastguard Worker // Copy any terminator instructions to the new kernel, and update
2244*9880d681SAndroid Build Coastguard Worker // names as needed.
2245*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator I = BB->getFirstTerminator(),
2246*9880d681SAndroid Build Coastguard Worker E = BB->instr_end();
2247*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
2248*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = MF.CloneMachineInstr(&*I);
2249*9880d681SAndroid Build Coastguard Worker updateInstruction(NewMI, false, MaxStageCount, 0, Schedule, VRMap);
2250*9880d681SAndroid Build Coastguard Worker KernelBB->push_back(NewMI);
2251*9880d681SAndroid Build Coastguard Worker InstrMap[NewMI] = &*I;
2252*9880d681SAndroid Build Coastguard Worker }
2253*9880d681SAndroid Build Coastguard Worker
2254*9880d681SAndroid Build Coastguard Worker KernelBB->transferSuccessors(BB);
2255*9880d681SAndroid Build Coastguard Worker KernelBB->replaceSuccessor(BB, KernelBB);
2256*9880d681SAndroid Build Coastguard Worker
2257*9880d681SAndroid Build Coastguard Worker generateExistingPhis(KernelBB, PrologBBs.back(), KernelBB, KernelBB, Schedule,
2258*9880d681SAndroid Build Coastguard Worker VRMap, InstrMap, MaxStageCount, MaxStageCount, false);
2259*9880d681SAndroid Build Coastguard Worker generatePhis(KernelBB, PrologBBs.back(), KernelBB, KernelBB, Schedule, VRMap,
2260*9880d681SAndroid Build Coastguard Worker InstrMap, MaxStageCount, MaxStageCount, false);
2261*9880d681SAndroid Build Coastguard Worker
2262*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "New block\n"; KernelBB->dump(););
2263*9880d681SAndroid Build Coastguard Worker
2264*9880d681SAndroid Build Coastguard Worker SmallVector<MachineBasicBlock *, 4> EpilogBBs;
2265*9880d681SAndroid Build Coastguard Worker // Generate the epilog instructions to complete the pipeline.
2266*9880d681SAndroid Build Coastguard Worker generateEpilog(Schedule, MaxStageCount, KernelBB, VRMap, EpilogBBs,
2267*9880d681SAndroid Build Coastguard Worker PrologBBs);
2268*9880d681SAndroid Build Coastguard Worker
2269*9880d681SAndroid Build Coastguard Worker // We need this step because the register allocation doesn't handle some
2270*9880d681SAndroid Build Coastguard Worker // situations well, so we insert copies to help out.
2271*9880d681SAndroid Build Coastguard Worker splitLifetimes(KernelBB, EpilogBBs, Schedule);
2272*9880d681SAndroid Build Coastguard Worker
2273*9880d681SAndroid Build Coastguard Worker // Remove dead instructions due to loop induction variables.
2274*9880d681SAndroid Build Coastguard Worker removeDeadInstructions(KernelBB, EpilogBBs);
2275*9880d681SAndroid Build Coastguard Worker
2276*9880d681SAndroid Build Coastguard Worker // Add branches between prolog and epilog blocks.
2277*9880d681SAndroid Build Coastguard Worker addBranches(PrologBBs, KernelBB, EpilogBBs, Schedule, VRMap);
2278*9880d681SAndroid Build Coastguard Worker
2279*9880d681SAndroid Build Coastguard Worker // Remove the original loop since it's no longer referenced.
2280*9880d681SAndroid Build Coastguard Worker BB->clear();
2281*9880d681SAndroid Build Coastguard Worker BB->eraseFromParent();
2282*9880d681SAndroid Build Coastguard Worker
2283*9880d681SAndroid Build Coastguard Worker delete[] VRMap;
2284*9880d681SAndroid Build Coastguard Worker }
2285*9880d681SAndroid Build Coastguard Worker
2286*9880d681SAndroid Build Coastguard Worker /// Generate the pipeline prolog code.
generateProlog(SMSchedule & Schedule,unsigned LastStage,MachineBasicBlock * KernelBB,ValueMapTy * VRMap,MBBVectorTy & PrologBBs)2287*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::generateProlog(SMSchedule &Schedule, unsigned LastStage,
2288*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB,
2289*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap,
2290*9880d681SAndroid Build Coastguard Worker MBBVectorTy &PrologBBs) {
2291*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *PreheaderBB = MLI->getLoopFor(BB)->getLoopPreheader();
2292*9880d681SAndroid Build Coastguard Worker assert(PreheaderBB != NULL &&
2293*9880d681SAndroid Build Coastguard Worker "Need to add code to handle loops w/o preheader");
2294*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *PredBB = PreheaderBB;
2295*9880d681SAndroid Build Coastguard Worker InstrMapTy InstrMap;
2296*9880d681SAndroid Build Coastguard Worker
2297*9880d681SAndroid Build Coastguard Worker // Generate a basic block for each stage, not including the last stage,
2298*9880d681SAndroid Build Coastguard Worker // which will be generated in the kernel. Each basic block may contain
2299*9880d681SAndroid Build Coastguard Worker // instructions from multiple stages/iterations.
2300*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0; i < LastStage; ++i) {
2301*9880d681SAndroid Build Coastguard Worker // Create and insert the prolog basic block prior to the original loop
2302*9880d681SAndroid Build Coastguard Worker // basic block. The original loop is removed later.
2303*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock(BB->getBasicBlock());
2304*9880d681SAndroid Build Coastguard Worker PrologBBs.push_back(NewBB);
2305*9880d681SAndroid Build Coastguard Worker MF.insert(BB->getIterator(), NewBB);
2306*9880d681SAndroid Build Coastguard Worker NewBB->transferSuccessors(PredBB);
2307*9880d681SAndroid Build Coastguard Worker PredBB->addSuccessor(NewBB);
2308*9880d681SAndroid Build Coastguard Worker PredBB = NewBB;
2309*9880d681SAndroid Build Coastguard Worker
2310*9880d681SAndroid Build Coastguard Worker // Generate instructions for each appropriate stage. Process instructions
2311*9880d681SAndroid Build Coastguard Worker // in original program order.
2312*9880d681SAndroid Build Coastguard Worker for (int StageNum = i; StageNum >= 0; --StageNum) {
2313*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = BB->instr_begin(),
2314*9880d681SAndroid Build Coastguard Worker BBE = BB->getFirstTerminator();
2315*9880d681SAndroid Build Coastguard Worker BBI != BBE; ++BBI) {
2316*9880d681SAndroid Build Coastguard Worker if (Schedule.isScheduledAtStage(getSUnit(&*BBI), (unsigned)StageNum)) {
2317*9880d681SAndroid Build Coastguard Worker if (BBI->isPHI())
2318*9880d681SAndroid Build Coastguard Worker continue;
2319*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI =
2320*9880d681SAndroid Build Coastguard Worker cloneAndChangeInstr(&*BBI, i, (unsigned)StageNum, Schedule);
2321*9880d681SAndroid Build Coastguard Worker updateInstruction(NewMI, false, i, (unsigned)StageNum, Schedule,
2322*9880d681SAndroid Build Coastguard Worker VRMap);
2323*9880d681SAndroid Build Coastguard Worker NewBB->push_back(NewMI);
2324*9880d681SAndroid Build Coastguard Worker InstrMap[NewMI] = &*BBI;
2325*9880d681SAndroid Build Coastguard Worker }
2326*9880d681SAndroid Build Coastguard Worker }
2327*9880d681SAndroid Build Coastguard Worker }
2328*9880d681SAndroid Build Coastguard Worker rewritePhiValues(NewBB, i, Schedule, VRMap, InstrMap);
2329*9880d681SAndroid Build Coastguard Worker DEBUG({
2330*9880d681SAndroid Build Coastguard Worker dbgs() << "prolog:\n";
2331*9880d681SAndroid Build Coastguard Worker NewBB->dump();
2332*9880d681SAndroid Build Coastguard Worker });
2333*9880d681SAndroid Build Coastguard Worker }
2334*9880d681SAndroid Build Coastguard Worker
2335*9880d681SAndroid Build Coastguard Worker PredBB->replaceSuccessor(BB, KernelBB);
2336*9880d681SAndroid Build Coastguard Worker
2337*9880d681SAndroid Build Coastguard Worker // Check if we need to remove the branch from the preheader to the original
2338*9880d681SAndroid Build Coastguard Worker // loop, and replace it with a branch to the new loop.
2339*9880d681SAndroid Build Coastguard Worker unsigned numBranches = TII->RemoveBranch(*PreheaderBB);
2340*9880d681SAndroid Build Coastguard Worker if (numBranches) {
2341*9880d681SAndroid Build Coastguard Worker SmallVector<MachineOperand, 0> Cond;
2342*9880d681SAndroid Build Coastguard Worker TII->InsertBranch(*PreheaderBB, PrologBBs[0], 0, Cond, DebugLoc());
2343*9880d681SAndroid Build Coastguard Worker }
2344*9880d681SAndroid Build Coastguard Worker }
2345*9880d681SAndroid Build Coastguard Worker
2346*9880d681SAndroid Build Coastguard Worker /// Generate the pipeline epilog code. The epilog code finishes the iterations
2347*9880d681SAndroid Build Coastguard Worker /// that were started in either the prolog or the kernel. We create a basic
2348*9880d681SAndroid Build Coastguard Worker /// block for each stage that needs to complete.
generateEpilog(SMSchedule & Schedule,unsigned LastStage,MachineBasicBlock * KernelBB,ValueMapTy * VRMap,MBBVectorTy & EpilogBBs,MBBVectorTy & PrologBBs)2349*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::generateEpilog(SMSchedule &Schedule, unsigned LastStage,
2350*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB,
2351*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap,
2352*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs,
2353*9880d681SAndroid Build Coastguard Worker MBBVectorTy &PrologBBs) {
2354*9880d681SAndroid Build Coastguard Worker // We need to change the branch from the kernel to the first epilog block, so
2355*9880d681SAndroid Build Coastguard Worker // this call to analyze branch uses the kernel rather than the original BB.
2356*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
2357*9880d681SAndroid Build Coastguard Worker SmallVector<MachineOperand, 4> Cond;
2358*9880d681SAndroid Build Coastguard Worker bool checkBranch = TII->analyzeBranch(*KernelBB, TBB, FBB, Cond);
2359*9880d681SAndroid Build Coastguard Worker assert(!checkBranch && "generateEpilog must be able to analyze the branch");
2360*9880d681SAndroid Build Coastguard Worker if (checkBranch)
2361*9880d681SAndroid Build Coastguard Worker return;
2362*9880d681SAndroid Build Coastguard Worker
2363*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::succ_iterator LoopExitI = KernelBB->succ_begin();
2364*9880d681SAndroid Build Coastguard Worker if (*LoopExitI == KernelBB)
2365*9880d681SAndroid Build Coastguard Worker ++LoopExitI;
2366*9880d681SAndroid Build Coastguard Worker assert(LoopExitI != KernelBB->succ_end() && "Expecting a successor");
2367*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *LoopExitBB = *LoopExitI;
2368*9880d681SAndroid Build Coastguard Worker
2369*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *PredBB = KernelBB;
2370*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *EpilogStart = LoopExitBB;
2371*9880d681SAndroid Build Coastguard Worker InstrMapTy InstrMap;
2372*9880d681SAndroid Build Coastguard Worker
2373*9880d681SAndroid Build Coastguard Worker // Generate a basic block for each stage, not including the last stage,
2374*9880d681SAndroid Build Coastguard Worker // which was generated for the kernel. Each basic block may contain
2375*9880d681SAndroid Build Coastguard Worker // instructions from multiple stages/iterations.
2376*9880d681SAndroid Build Coastguard Worker int EpilogStage = LastStage + 1;
2377*9880d681SAndroid Build Coastguard Worker for (unsigned i = LastStage; i >= 1; --i, ++EpilogStage) {
2378*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *NewBB = MF.CreateMachineBasicBlock();
2379*9880d681SAndroid Build Coastguard Worker EpilogBBs.push_back(NewBB);
2380*9880d681SAndroid Build Coastguard Worker MF.insert(BB->getIterator(), NewBB);
2381*9880d681SAndroid Build Coastguard Worker
2382*9880d681SAndroid Build Coastguard Worker PredBB->replaceSuccessor(LoopExitBB, NewBB);
2383*9880d681SAndroid Build Coastguard Worker NewBB->addSuccessor(LoopExitBB);
2384*9880d681SAndroid Build Coastguard Worker
2385*9880d681SAndroid Build Coastguard Worker if (EpilogStart == LoopExitBB)
2386*9880d681SAndroid Build Coastguard Worker EpilogStart = NewBB;
2387*9880d681SAndroid Build Coastguard Worker
2388*9880d681SAndroid Build Coastguard Worker // Add instructions to the epilog depending on the current block.
2389*9880d681SAndroid Build Coastguard Worker // Process instructions in original program order.
2390*9880d681SAndroid Build Coastguard Worker for (unsigned StageNum = i; StageNum <= LastStage; ++StageNum) {
2391*9880d681SAndroid Build Coastguard Worker for (auto &BBI : *BB) {
2392*9880d681SAndroid Build Coastguard Worker if (BBI.isPHI())
2393*9880d681SAndroid Build Coastguard Worker continue;
2394*9880d681SAndroid Build Coastguard Worker MachineInstr *In = &BBI;
2395*9880d681SAndroid Build Coastguard Worker if (Schedule.isScheduledAtStage(getSUnit(In), StageNum)) {
2396*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = cloneInstr(In, EpilogStage - LastStage, 0);
2397*9880d681SAndroid Build Coastguard Worker updateInstruction(NewMI, i == 1, EpilogStage, 0, Schedule, VRMap);
2398*9880d681SAndroid Build Coastguard Worker NewBB->push_back(NewMI);
2399*9880d681SAndroid Build Coastguard Worker InstrMap[NewMI] = In;
2400*9880d681SAndroid Build Coastguard Worker }
2401*9880d681SAndroid Build Coastguard Worker }
2402*9880d681SAndroid Build Coastguard Worker }
2403*9880d681SAndroid Build Coastguard Worker generateExistingPhis(NewBB, PrologBBs[i - 1], PredBB, KernelBB, Schedule,
2404*9880d681SAndroid Build Coastguard Worker VRMap, InstrMap, LastStage, EpilogStage, i == 1);
2405*9880d681SAndroid Build Coastguard Worker generatePhis(NewBB, PrologBBs[i - 1], PredBB, KernelBB, Schedule, VRMap,
2406*9880d681SAndroid Build Coastguard Worker InstrMap, LastStage, EpilogStage, i == 1);
2407*9880d681SAndroid Build Coastguard Worker PredBB = NewBB;
2408*9880d681SAndroid Build Coastguard Worker
2409*9880d681SAndroid Build Coastguard Worker DEBUG({
2410*9880d681SAndroid Build Coastguard Worker dbgs() << "epilog:\n";
2411*9880d681SAndroid Build Coastguard Worker NewBB->dump();
2412*9880d681SAndroid Build Coastguard Worker });
2413*9880d681SAndroid Build Coastguard Worker }
2414*9880d681SAndroid Build Coastguard Worker
2415*9880d681SAndroid Build Coastguard Worker // Fix any Phi nodes in the loop exit block.
2416*9880d681SAndroid Build Coastguard Worker for (MachineInstr &MI : *LoopExitBB) {
2417*9880d681SAndroid Build Coastguard Worker if (!MI.isPHI())
2418*9880d681SAndroid Build Coastguard Worker break;
2419*9880d681SAndroid Build Coastguard Worker for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
2420*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = MI.getOperand(i);
2421*9880d681SAndroid Build Coastguard Worker if (MO.getMBB() == BB)
2422*9880d681SAndroid Build Coastguard Worker MO.setMBB(PredBB);
2423*9880d681SAndroid Build Coastguard Worker }
2424*9880d681SAndroid Build Coastguard Worker }
2425*9880d681SAndroid Build Coastguard Worker
2426*9880d681SAndroid Build Coastguard Worker // Create a branch to the new epilog from the kernel.
2427*9880d681SAndroid Build Coastguard Worker // Remove the original branch and add a new branch to the epilog.
2428*9880d681SAndroid Build Coastguard Worker TII->RemoveBranch(*KernelBB);
2429*9880d681SAndroid Build Coastguard Worker TII->InsertBranch(*KernelBB, KernelBB, EpilogStart, Cond, DebugLoc());
2430*9880d681SAndroid Build Coastguard Worker // Add a branch to the loop exit.
2431*9880d681SAndroid Build Coastguard Worker if (EpilogBBs.size() > 0) {
2432*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *LastEpilogBB = EpilogBBs.back();
2433*9880d681SAndroid Build Coastguard Worker SmallVector<MachineOperand, 4> Cond1;
2434*9880d681SAndroid Build Coastguard Worker TII->InsertBranch(*LastEpilogBB, LoopExitBB, 0, Cond1, DebugLoc());
2435*9880d681SAndroid Build Coastguard Worker }
2436*9880d681SAndroid Build Coastguard Worker }
2437*9880d681SAndroid Build Coastguard Worker
2438*9880d681SAndroid Build Coastguard Worker /// Replace all uses of FromReg that appear outside the specified
2439*9880d681SAndroid Build Coastguard Worker /// basic block with ToReg.
replaceRegUsesAfterLoop(unsigned FromReg,unsigned ToReg,MachineBasicBlock * MBB,MachineRegisterInfo & MRI,LiveIntervals & LIS)2440*9880d681SAndroid Build Coastguard Worker static void replaceRegUsesAfterLoop(unsigned FromReg, unsigned ToReg,
2441*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB,
2442*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI,
2443*9880d681SAndroid Build Coastguard Worker LiveIntervals &LIS) {
2444*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_iterator I = MRI.use_begin(FromReg),
2445*9880d681SAndroid Build Coastguard Worker E = MRI.use_end();
2446*9880d681SAndroid Build Coastguard Worker I != E;) {
2447*9880d681SAndroid Build Coastguard Worker MachineOperand &O = *I;
2448*9880d681SAndroid Build Coastguard Worker ++I;
2449*9880d681SAndroid Build Coastguard Worker if (O.getParent()->getParent() != MBB)
2450*9880d681SAndroid Build Coastguard Worker O.setReg(ToReg);
2451*9880d681SAndroid Build Coastguard Worker }
2452*9880d681SAndroid Build Coastguard Worker if (!LIS.hasInterval(ToReg))
2453*9880d681SAndroid Build Coastguard Worker LIS.createEmptyInterval(ToReg);
2454*9880d681SAndroid Build Coastguard Worker }
2455*9880d681SAndroid Build Coastguard Worker
2456*9880d681SAndroid Build Coastguard Worker /// Return true if the register has a use that occurs outside the
2457*9880d681SAndroid Build Coastguard Worker /// specified loop.
hasUseAfterLoop(unsigned Reg,MachineBasicBlock * BB,MachineRegisterInfo & MRI)2458*9880d681SAndroid Build Coastguard Worker static bool hasUseAfterLoop(unsigned Reg, MachineBasicBlock *BB,
2459*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI) {
2460*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_iterator I = MRI.use_begin(Reg),
2461*9880d681SAndroid Build Coastguard Worker E = MRI.use_end();
2462*9880d681SAndroid Build Coastguard Worker I != E; ++I)
2463*9880d681SAndroid Build Coastguard Worker if (I->getParent()->getParent() != BB)
2464*9880d681SAndroid Build Coastguard Worker return true;
2465*9880d681SAndroid Build Coastguard Worker return false;
2466*9880d681SAndroid Build Coastguard Worker }
2467*9880d681SAndroid Build Coastguard Worker
2468*9880d681SAndroid Build Coastguard Worker /// Generate Phis for the specific block in the generated pipelined code.
2469*9880d681SAndroid Build Coastguard Worker /// This function looks at the Phis from the original code to guide the
2470*9880d681SAndroid Build Coastguard Worker /// creation of new Phis.
generateExistingPhis(MachineBasicBlock * NewBB,MachineBasicBlock * BB1,MachineBasicBlock * BB2,MachineBasicBlock * KernelBB,SMSchedule & Schedule,ValueMapTy * VRMap,InstrMapTy & InstrMap,unsigned LastStageNum,unsigned CurStageNum,bool IsLast)2471*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::generateExistingPhis(
2472*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *NewBB, MachineBasicBlock *BB1, MachineBasicBlock *BB2,
2473*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB, SMSchedule &Schedule, ValueMapTy *VRMap,
2474*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap, unsigned LastStageNum, unsigned CurStageNum,
2475*9880d681SAndroid Build Coastguard Worker bool IsLast) {
2476*9880d681SAndroid Build Coastguard Worker // Compute the stage number for the inital value of the Phi, which
2477*9880d681SAndroid Build Coastguard Worker // comes from the prolog. The prolog to use depends on to which kernel/
2478*9880d681SAndroid Build Coastguard Worker // epilog that we're adding the Phi.
2479*9880d681SAndroid Build Coastguard Worker unsigned PrologStage = 0;
2480*9880d681SAndroid Build Coastguard Worker unsigned PrevStage = 0;
2481*9880d681SAndroid Build Coastguard Worker bool InKernel = (LastStageNum == CurStageNum);
2482*9880d681SAndroid Build Coastguard Worker if (InKernel) {
2483*9880d681SAndroid Build Coastguard Worker PrologStage = LastStageNum - 1;
2484*9880d681SAndroid Build Coastguard Worker PrevStage = CurStageNum;
2485*9880d681SAndroid Build Coastguard Worker } else {
2486*9880d681SAndroid Build Coastguard Worker PrologStage = LastStageNum - (CurStageNum - LastStageNum);
2487*9880d681SAndroid Build Coastguard Worker PrevStage = LastStageNum + (CurStageNum - LastStageNum) - 1;
2488*9880d681SAndroid Build Coastguard Worker }
2489*9880d681SAndroid Build Coastguard Worker
2490*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = BB->instr_begin(),
2491*9880d681SAndroid Build Coastguard Worker BBE = BB->getFirstNonPHI();
2492*9880d681SAndroid Build Coastguard Worker BBI != BBE; ++BBI) {
2493*9880d681SAndroid Build Coastguard Worker unsigned Def = BBI->getOperand(0).getReg();
2494*9880d681SAndroid Build Coastguard Worker
2495*9880d681SAndroid Build Coastguard Worker unsigned InitVal = 0;
2496*9880d681SAndroid Build Coastguard Worker unsigned LoopVal = 0;
2497*9880d681SAndroid Build Coastguard Worker getPhiRegs(*BBI, BB, InitVal, LoopVal);
2498*9880d681SAndroid Build Coastguard Worker
2499*9880d681SAndroid Build Coastguard Worker unsigned PhiOp1 = 0;
2500*9880d681SAndroid Build Coastguard Worker // The Phi value from the loop body typically is defined in the loop, but
2501*9880d681SAndroid Build Coastguard Worker // not always. So, we need to check if the value is defined in the loop.
2502*9880d681SAndroid Build Coastguard Worker unsigned PhiOp2 = LoopVal;
2503*9880d681SAndroid Build Coastguard Worker if (VRMap[LastStageNum].count(LoopVal))
2504*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[LastStageNum][LoopVal];
2505*9880d681SAndroid Build Coastguard Worker
2506*9880d681SAndroid Build Coastguard Worker int StageScheduled = Schedule.stageScheduled(getSUnit(&*BBI));
2507*9880d681SAndroid Build Coastguard Worker int LoopValStage =
2508*9880d681SAndroid Build Coastguard Worker Schedule.stageScheduled(getSUnit(MRI.getVRegDef(LoopVal)));
2509*9880d681SAndroid Build Coastguard Worker unsigned NumStages = Schedule.getStagesForReg(Def, CurStageNum);
2510*9880d681SAndroid Build Coastguard Worker if (NumStages == 0) {
2511*9880d681SAndroid Build Coastguard Worker // We don't need to generate a Phi anymore, but we need to rename any uses
2512*9880d681SAndroid Build Coastguard Worker // of the Phi value.
2513*9880d681SAndroid Build Coastguard Worker unsigned NewReg = VRMap[PrevStage][LoopVal];
2514*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, 0, &*BBI,
2515*9880d681SAndroid Build Coastguard Worker Def, NewReg);
2516*9880d681SAndroid Build Coastguard Worker if (VRMap[CurStageNum].count(LoopVal))
2517*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum][Def] = VRMap[CurStageNum][LoopVal];
2518*9880d681SAndroid Build Coastguard Worker }
2519*9880d681SAndroid Build Coastguard Worker // Adjust the number of Phis needed depending on the number of prologs left,
2520*9880d681SAndroid Build Coastguard Worker // and the distance from where the Phi is first scheduled.
2521*9880d681SAndroid Build Coastguard Worker unsigned NumPhis = NumStages;
2522*9880d681SAndroid Build Coastguard Worker if (!InKernel && (int)PrologStage < LoopValStage)
2523*9880d681SAndroid Build Coastguard Worker // The NumPhis is the maximum number of new Phis needed during the steady
2524*9880d681SAndroid Build Coastguard Worker // state. If the Phi has not been scheduled in current prolog, then we
2525*9880d681SAndroid Build Coastguard Worker // need to generate less Phis.
2526*9880d681SAndroid Build Coastguard Worker NumPhis = std::max((int)NumPhis - (int)(LoopValStage - PrologStage), 1);
2527*9880d681SAndroid Build Coastguard Worker // The number of Phis cannot exceed the number of prolog stages. Each
2528*9880d681SAndroid Build Coastguard Worker // stage can potentially define two values.
2529*9880d681SAndroid Build Coastguard Worker NumPhis = std::min(NumPhis, PrologStage + 2);
2530*9880d681SAndroid Build Coastguard Worker
2531*9880d681SAndroid Build Coastguard Worker unsigned NewReg = 0;
2532*9880d681SAndroid Build Coastguard Worker
2533*9880d681SAndroid Build Coastguard Worker unsigned AccessStage = (LoopValStage != -1) ? LoopValStage : StageScheduled;
2534*9880d681SAndroid Build Coastguard Worker // In the epilog, we may need to look back one stage to get the correct
2535*9880d681SAndroid Build Coastguard Worker // Phi name because the epilog and prolog blocks execute the same stage.
2536*9880d681SAndroid Build Coastguard Worker // The correct name is from the previous block only when the Phi has
2537*9880d681SAndroid Build Coastguard Worker // been completely scheduled prior to the epilog, and Phi value is not
2538*9880d681SAndroid Build Coastguard Worker // needed in multiple stages.
2539*9880d681SAndroid Build Coastguard Worker int StageDiff = 0;
2540*9880d681SAndroid Build Coastguard Worker if (!InKernel && StageScheduled >= LoopValStage && AccessStage == 0 &&
2541*9880d681SAndroid Build Coastguard Worker NumPhis == 1)
2542*9880d681SAndroid Build Coastguard Worker StageDiff = 1;
2543*9880d681SAndroid Build Coastguard Worker // Adjust the computations below when the phi and the loop definition
2544*9880d681SAndroid Build Coastguard Worker // are scheduled in different stages.
2545*9880d681SAndroid Build Coastguard Worker if (InKernel && LoopValStage != -1 && StageScheduled > LoopValStage)
2546*9880d681SAndroid Build Coastguard Worker StageDiff = StageScheduled - LoopValStage;
2547*9880d681SAndroid Build Coastguard Worker for (unsigned np = 0; np < NumPhis; ++np) {
2548*9880d681SAndroid Build Coastguard Worker // If the Phi hasn't been scheduled, then use the initial Phi operand
2549*9880d681SAndroid Build Coastguard Worker // value. Otherwise, use the scheduled version of the instruction. This
2550*9880d681SAndroid Build Coastguard Worker // is a little complicated when a Phi references another Phi.
2551*9880d681SAndroid Build Coastguard Worker if (np > PrologStage || StageScheduled >= (int)LastStageNum)
2552*9880d681SAndroid Build Coastguard Worker PhiOp1 = InitVal;
2553*9880d681SAndroid Build Coastguard Worker // Check if the Phi has already been scheduled in a prolog stage.
2554*9880d681SAndroid Build Coastguard Worker else if (PrologStage >= AccessStage + StageDiff + np &&
2555*9880d681SAndroid Build Coastguard Worker VRMap[PrologStage - StageDiff - np].count(LoopVal) != 0)
2556*9880d681SAndroid Build Coastguard Worker PhiOp1 = VRMap[PrologStage - StageDiff - np][LoopVal];
2557*9880d681SAndroid Build Coastguard Worker // Check if the Phi has already been scheduled, but the loop intruction
2558*9880d681SAndroid Build Coastguard Worker // is either another Phi, or doesn't occur in the loop.
2559*9880d681SAndroid Build Coastguard Worker else if (PrologStage >= AccessStage + StageDiff + np) {
2560*9880d681SAndroid Build Coastguard Worker // If the Phi references another Phi, we need to examine the other
2561*9880d681SAndroid Build Coastguard Worker // Phi to get the correct value.
2562*9880d681SAndroid Build Coastguard Worker PhiOp1 = LoopVal;
2563*9880d681SAndroid Build Coastguard Worker MachineInstr *InstOp1 = MRI.getVRegDef(PhiOp1);
2564*9880d681SAndroid Build Coastguard Worker int Indirects = 1;
2565*9880d681SAndroid Build Coastguard Worker while (InstOp1 && InstOp1->isPHI() && InstOp1->getParent() == BB) {
2566*9880d681SAndroid Build Coastguard Worker int PhiStage = Schedule.stageScheduled(getSUnit(InstOp1));
2567*9880d681SAndroid Build Coastguard Worker if ((int)(PrologStage - StageDiff - np) < PhiStage + Indirects)
2568*9880d681SAndroid Build Coastguard Worker PhiOp1 = getInitPhiReg(*InstOp1, BB);
2569*9880d681SAndroid Build Coastguard Worker else
2570*9880d681SAndroid Build Coastguard Worker PhiOp1 = getLoopPhiReg(*InstOp1, BB);
2571*9880d681SAndroid Build Coastguard Worker InstOp1 = MRI.getVRegDef(PhiOp1);
2572*9880d681SAndroid Build Coastguard Worker int PhiOpStage = Schedule.stageScheduled(getSUnit(InstOp1));
2573*9880d681SAndroid Build Coastguard Worker int StageAdj = (PhiOpStage != -1 ? PhiStage - PhiOpStage : 0);
2574*9880d681SAndroid Build Coastguard Worker if (PhiOpStage != -1 && PrologStage - StageAdj >= Indirects + np &&
2575*9880d681SAndroid Build Coastguard Worker VRMap[PrologStage - StageAdj - Indirects - np].count(PhiOp1)) {
2576*9880d681SAndroid Build Coastguard Worker PhiOp1 = VRMap[PrologStage - StageAdj - Indirects - np][PhiOp1];
2577*9880d681SAndroid Build Coastguard Worker break;
2578*9880d681SAndroid Build Coastguard Worker }
2579*9880d681SAndroid Build Coastguard Worker ++Indirects;
2580*9880d681SAndroid Build Coastguard Worker }
2581*9880d681SAndroid Build Coastguard Worker } else
2582*9880d681SAndroid Build Coastguard Worker PhiOp1 = InitVal;
2583*9880d681SAndroid Build Coastguard Worker // If this references a generated Phi in the kernel, get the Phi operand
2584*9880d681SAndroid Build Coastguard Worker // from the incoming block.
2585*9880d681SAndroid Build Coastguard Worker if (MachineInstr *InstOp1 = MRI.getVRegDef(PhiOp1))
2586*9880d681SAndroid Build Coastguard Worker if (InstOp1->isPHI() && InstOp1->getParent() == KernelBB)
2587*9880d681SAndroid Build Coastguard Worker PhiOp1 = getInitPhiReg(*InstOp1, KernelBB);
2588*9880d681SAndroid Build Coastguard Worker
2589*9880d681SAndroid Build Coastguard Worker MachineInstr *PhiInst = MRI.getVRegDef(LoopVal);
2590*9880d681SAndroid Build Coastguard Worker bool LoopDefIsPhi = PhiInst && PhiInst->isPHI();
2591*9880d681SAndroid Build Coastguard Worker // In the epilog, a map lookup is needed to get the value from the kernel,
2592*9880d681SAndroid Build Coastguard Worker // or previous epilog block. How is does this depends on if the
2593*9880d681SAndroid Build Coastguard Worker // instruction is scheduled in the previous block.
2594*9880d681SAndroid Build Coastguard Worker if (!InKernel) {
2595*9880d681SAndroid Build Coastguard Worker int StageDiffAdj = 0;
2596*9880d681SAndroid Build Coastguard Worker if (LoopValStage != -1 && StageScheduled > LoopValStage)
2597*9880d681SAndroid Build Coastguard Worker StageDiffAdj = StageScheduled - LoopValStage;
2598*9880d681SAndroid Build Coastguard Worker // Use the loop value defined in the kernel, unless the kernel
2599*9880d681SAndroid Build Coastguard Worker // contains the last definition of the Phi.
2600*9880d681SAndroid Build Coastguard Worker if (np == 0 && PrevStage == LastStageNum &&
2601*9880d681SAndroid Build Coastguard Worker (StageScheduled != 0 || LoopValStage != 0) &&
2602*9880d681SAndroid Build Coastguard Worker VRMap[PrevStage - StageDiffAdj].count(LoopVal))
2603*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[PrevStage - StageDiffAdj][LoopVal];
2604*9880d681SAndroid Build Coastguard Worker // Use the value defined by the Phi. We add one because we switch
2605*9880d681SAndroid Build Coastguard Worker // from looking at the loop value to the Phi definition.
2606*9880d681SAndroid Build Coastguard Worker else if (np > 0 && PrevStage == LastStageNum &&
2607*9880d681SAndroid Build Coastguard Worker VRMap[PrevStage - np + 1].count(Def))
2608*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[PrevStage - np + 1][Def];
2609*9880d681SAndroid Build Coastguard Worker // Use the loop value defined in the kernel.
2610*9880d681SAndroid Build Coastguard Worker else if ((unsigned)LoopValStage + StageDiffAdj > PrologStage + 1 &&
2611*9880d681SAndroid Build Coastguard Worker VRMap[PrevStage - StageDiffAdj - np].count(LoopVal))
2612*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[PrevStage - StageDiffAdj - np][LoopVal];
2613*9880d681SAndroid Build Coastguard Worker // Use the value defined by the Phi, unless we're generating the first
2614*9880d681SAndroid Build Coastguard Worker // epilog and the Phi refers to a Phi in a different stage.
2615*9880d681SAndroid Build Coastguard Worker else if (VRMap[PrevStage - np].count(Def) &&
2616*9880d681SAndroid Build Coastguard Worker (!LoopDefIsPhi || PrevStage != LastStageNum))
2617*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[PrevStage - np][Def];
2618*9880d681SAndroid Build Coastguard Worker }
2619*9880d681SAndroid Build Coastguard Worker
2620*9880d681SAndroid Build Coastguard Worker // Check if we can reuse an existing Phi. This occurs when a Phi
2621*9880d681SAndroid Build Coastguard Worker // references another Phi, and the other Phi is scheduled in an
2622*9880d681SAndroid Build Coastguard Worker // earlier stage. We can try to reuse an existing Phi up until the last
2623*9880d681SAndroid Build Coastguard Worker // stage of the current Phi.
2624*9880d681SAndroid Build Coastguard Worker if (LoopDefIsPhi && VRMap[CurStageNum].count(LoopVal) &&
2625*9880d681SAndroid Build Coastguard Worker LoopValStage >= (int)(CurStageNum - LastStageNum)) {
2626*9880d681SAndroid Build Coastguard Worker int LVNumStages = Schedule.getStagesForPhi(LoopVal);
2627*9880d681SAndroid Build Coastguard Worker int StageDiff = (StageScheduled - LoopValStage);
2628*9880d681SAndroid Build Coastguard Worker LVNumStages -= StageDiff;
2629*9880d681SAndroid Build Coastguard Worker if (LVNumStages > (int)np) {
2630*9880d681SAndroid Build Coastguard Worker NewReg = PhiOp2;
2631*9880d681SAndroid Build Coastguard Worker unsigned ReuseStage = CurStageNum;
2632*9880d681SAndroid Build Coastguard Worker if (Schedule.isLoopCarried(this, *PhiInst))
2633*9880d681SAndroid Build Coastguard Worker ReuseStage -= LVNumStages;
2634*9880d681SAndroid Build Coastguard Worker // Check if the Phi to reuse has been generated yet. If not, then
2635*9880d681SAndroid Build Coastguard Worker // there is nothing to reuse.
2636*9880d681SAndroid Build Coastguard Worker if (VRMap[ReuseStage].count(LoopVal)) {
2637*9880d681SAndroid Build Coastguard Worker NewReg = VRMap[ReuseStage][LoopVal];
2638*9880d681SAndroid Build Coastguard Worker
2639*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np,
2640*9880d681SAndroid Build Coastguard Worker &*BBI, Def, NewReg);
2641*9880d681SAndroid Build Coastguard Worker // Update the map with the new Phi name.
2642*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum - np][Def] = NewReg;
2643*9880d681SAndroid Build Coastguard Worker PhiOp2 = NewReg;
2644*9880d681SAndroid Build Coastguard Worker if (VRMap[LastStageNum - np - 1].count(LoopVal))
2645*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[LastStageNum - np - 1][LoopVal];
2646*9880d681SAndroid Build Coastguard Worker
2647*9880d681SAndroid Build Coastguard Worker if (IsLast && np == NumPhis - 1)
2648*9880d681SAndroid Build Coastguard Worker replaceRegUsesAfterLoop(Def, NewReg, BB, MRI, LIS);
2649*9880d681SAndroid Build Coastguard Worker continue;
2650*9880d681SAndroid Build Coastguard Worker }
2651*9880d681SAndroid Build Coastguard Worker } else if (StageDiff > 0 &&
2652*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum - StageDiff - np].count(LoopVal))
2653*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[CurStageNum - StageDiff - np][LoopVal];
2654*9880d681SAndroid Build Coastguard Worker }
2655*9880d681SAndroid Build Coastguard Worker
2656*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI.getRegClass(Def);
2657*9880d681SAndroid Build Coastguard Worker NewReg = MRI.createVirtualRegister(RC);
2658*9880d681SAndroid Build Coastguard Worker
2659*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder NewPhi =
2660*9880d681SAndroid Build Coastguard Worker BuildMI(*NewBB, NewBB->getFirstNonPHI(), DebugLoc(),
2661*9880d681SAndroid Build Coastguard Worker TII->get(TargetOpcode::PHI), NewReg);
2662*9880d681SAndroid Build Coastguard Worker NewPhi.addReg(PhiOp1).addMBB(BB1);
2663*9880d681SAndroid Build Coastguard Worker NewPhi.addReg(PhiOp2).addMBB(BB2);
2664*9880d681SAndroid Build Coastguard Worker if (np == 0)
2665*9880d681SAndroid Build Coastguard Worker InstrMap[NewPhi] = &*BBI;
2666*9880d681SAndroid Build Coastguard Worker
2667*9880d681SAndroid Build Coastguard Worker // We define the Phis after creating the new pipelined code, so
2668*9880d681SAndroid Build Coastguard Worker // we need to rename the Phi values in scheduled instructions.
2669*9880d681SAndroid Build Coastguard Worker
2670*9880d681SAndroid Build Coastguard Worker unsigned PrevReg = 0;
2671*9880d681SAndroid Build Coastguard Worker if (InKernel && VRMap[PrevStage - np].count(LoopVal))
2672*9880d681SAndroid Build Coastguard Worker PrevReg = VRMap[PrevStage - np][LoopVal];
2673*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np, &*BBI,
2674*9880d681SAndroid Build Coastguard Worker Def, NewReg, PrevReg);
2675*9880d681SAndroid Build Coastguard Worker // If the Phi has been scheduled, use the new name for rewriting.
2676*9880d681SAndroid Build Coastguard Worker if (VRMap[CurStageNum - np].count(Def)) {
2677*9880d681SAndroid Build Coastguard Worker unsigned R = VRMap[CurStageNum - np][Def];
2678*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np, &*BBI,
2679*9880d681SAndroid Build Coastguard Worker R, NewReg);
2680*9880d681SAndroid Build Coastguard Worker }
2681*9880d681SAndroid Build Coastguard Worker
2682*9880d681SAndroid Build Coastguard Worker // Check if we need to rename any uses that occurs after the loop. The
2683*9880d681SAndroid Build Coastguard Worker // register to replace depends on whether the Phi is scheduled in the
2684*9880d681SAndroid Build Coastguard Worker // epilog.
2685*9880d681SAndroid Build Coastguard Worker if (IsLast && np == NumPhis - 1)
2686*9880d681SAndroid Build Coastguard Worker replaceRegUsesAfterLoop(Def, NewReg, BB, MRI, LIS);
2687*9880d681SAndroid Build Coastguard Worker
2688*9880d681SAndroid Build Coastguard Worker // In the kernel, a dependent Phi uses the value from this Phi.
2689*9880d681SAndroid Build Coastguard Worker if (InKernel)
2690*9880d681SAndroid Build Coastguard Worker PhiOp2 = NewReg;
2691*9880d681SAndroid Build Coastguard Worker
2692*9880d681SAndroid Build Coastguard Worker // Update the map with the new Phi name.
2693*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum - np][Def] = NewReg;
2694*9880d681SAndroid Build Coastguard Worker }
2695*9880d681SAndroid Build Coastguard Worker
2696*9880d681SAndroid Build Coastguard Worker while (NumPhis++ < NumStages) {
2697*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, NumPhis,
2698*9880d681SAndroid Build Coastguard Worker &*BBI, Def, NewReg, 0);
2699*9880d681SAndroid Build Coastguard Worker }
2700*9880d681SAndroid Build Coastguard Worker
2701*9880d681SAndroid Build Coastguard Worker // Check if we need to rename a Phi that has been eliminated due to
2702*9880d681SAndroid Build Coastguard Worker // scheduling.
2703*9880d681SAndroid Build Coastguard Worker if (NumStages == 0 && IsLast && VRMap[CurStageNum].count(LoopVal))
2704*9880d681SAndroid Build Coastguard Worker replaceRegUsesAfterLoop(Def, VRMap[CurStageNum][LoopVal], BB, MRI, LIS);
2705*9880d681SAndroid Build Coastguard Worker }
2706*9880d681SAndroid Build Coastguard Worker }
2707*9880d681SAndroid Build Coastguard Worker
2708*9880d681SAndroid Build Coastguard Worker /// Generate Phis for the specified block in the generated pipelined code.
2709*9880d681SAndroid Build Coastguard Worker /// These are new Phis needed because the definition is scheduled after the
2710*9880d681SAndroid Build Coastguard Worker /// use in the pipelened sequence.
generatePhis(MachineBasicBlock * NewBB,MachineBasicBlock * BB1,MachineBasicBlock * BB2,MachineBasicBlock * KernelBB,SMSchedule & Schedule,ValueMapTy * VRMap,InstrMapTy & InstrMap,unsigned LastStageNum,unsigned CurStageNum,bool IsLast)2711*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::generatePhis(
2712*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *NewBB, MachineBasicBlock *BB1, MachineBasicBlock *BB2,
2713*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB, SMSchedule &Schedule, ValueMapTy *VRMap,
2714*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap, unsigned LastStageNum, unsigned CurStageNum,
2715*9880d681SAndroid Build Coastguard Worker bool IsLast) {
2716*9880d681SAndroid Build Coastguard Worker // Compute the stage number that contains the initial Phi value, and
2717*9880d681SAndroid Build Coastguard Worker // the Phi from the previous stage.
2718*9880d681SAndroid Build Coastguard Worker unsigned PrologStage = 0;
2719*9880d681SAndroid Build Coastguard Worker unsigned PrevStage = 0;
2720*9880d681SAndroid Build Coastguard Worker unsigned StageDiff = CurStageNum - LastStageNum;
2721*9880d681SAndroid Build Coastguard Worker bool InKernel = (StageDiff == 0);
2722*9880d681SAndroid Build Coastguard Worker if (InKernel) {
2723*9880d681SAndroid Build Coastguard Worker PrologStage = LastStageNum - 1;
2724*9880d681SAndroid Build Coastguard Worker PrevStage = CurStageNum;
2725*9880d681SAndroid Build Coastguard Worker } else {
2726*9880d681SAndroid Build Coastguard Worker PrologStage = LastStageNum - StageDiff;
2727*9880d681SAndroid Build Coastguard Worker PrevStage = LastStageNum + StageDiff - 1;
2728*9880d681SAndroid Build Coastguard Worker }
2729*9880d681SAndroid Build Coastguard Worker
2730*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = BB->getFirstNonPHI(),
2731*9880d681SAndroid Build Coastguard Worker BBE = BB->instr_end();
2732*9880d681SAndroid Build Coastguard Worker BBI != BBE; ++BBI) {
2733*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = BBI->getNumOperands(); i != e; ++i) {
2734*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = BBI->getOperand(i);
2735*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !MO.isDef() ||
2736*9880d681SAndroid Build Coastguard Worker !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
2737*9880d681SAndroid Build Coastguard Worker continue;
2738*9880d681SAndroid Build Coastguard Worker
2739*9880d681SAndroid Build Coastguard Worker int StageScheduled = Schedule.stageScheduled(getSUnit(&*BBI));
2740*9880d681SAndroid Build Coastguard Worker assert(StageScheduled != -1 && "Expecting scheduled instruction.");
2741*9880d681SAndroid Build Coastguard Worker unsigned Def = MO.getReg();
2742*9880d681SAndroid Build Coastguard Worker unsigned NumPhis = Schedule.getStagesForReg(Def, CurStageNum);
2743*9880d681SAndroid Build Coastguard Worker // An instruction scheduled in stage 0 and is used after the loop
2744*9880d681SAndroid Build Coastguard Worker // requires a phi in the epilog for the last definition from either
2745*9880d681SAndroid Build Coastguard Worker // the kernel or prolog.
2746*9880d681SAndroid Build Coastguard Worker if (!InKernel && NumPhis == 0 && StageScheduled == 0 &&
2747*9880d681SAndroid Build Coastguard Worker hasUseAfterLoop(Def, BB, MRI))
2748*9880d681SAndroid Build Coastguard Worker NumPhis = 1;
2749*9880d681SAndroid Build Coastguard Worker if (!InKernel && (unsigned)StageScheduled > PrologStage)
2750*9880d681SAndroid Build Coastguard Worker continue;
2751*9880d681SAndroid Build Coastguard Worker
2752*9880d681SAndroid Build Coastguard Worker unsigned PhiOp2 = VRMap[PrevStage][Def];
2753*9880d681SAndroid Build Coastguard Worker if (MachineInstr *InstOp2 = MRI.getVRegDef(PhiOp2))
2754*9880d681SAndroid Build Coastguard Worker if (InstOp2->isPHI() && InstOp2->getParent() == NewBB)
2755*9880d681SAndroid Build Coastguard Worker PhiOp2 = getLoopPhiReg(*InstOp2, BB2);
2756*9880d681SAndroid Build Coastguard Worker // The number of Phis can't exceed the number of prolog stages. The
2757*9880d681SAndroid Build Coastguard Worker // prolog stage number is zero based.
2758*9880d681SAndroid Build Coastguard Worker if (NumPhis > PrologStage + 1 - StageScheduled)
2759*9880d681SAndroid Build Coastguard Worker NumPhis = PrologStage + 1 - StageScheduled;
2760*9880d681SAndroid Build Coastguard Worker for (unsigned np = 0; np < NumPhis; ++np) {
2761*9880d681SAndroid Build Coastguard Worker unsigned PhiOp1 = VRMap[PrologStage][Def];
2762*9880d681SAndroid Build Coastguard Worker if (np <= PrologStage)
2763*9880d681SAndroid Build Coastguard Worker PhiOp1 = VRMap[PrologStage - np][Def];
2764*9880d681SAndroid Build Coastguard Worker if (MachineInstr *InstOp1 = MRI.getVRegDef(PhiOp1)) {
2765*9880d681SAndroid Build Coastguard Worker if (InstOp1->isPHI() && InstOp1->getParent() == KernelBB)
2766*9880d681SAndroid Build Coastguard Worker PhiOp1 = getInitPhiReg(*InstOp1, KernelBB);
2767*9880d681SAndroid Build Coastguard Worker if (InstOp1->isPHI() && InstOp1->getParent() == NewBB)
2768*9880d681SAndroid Build Coastguard Worker PhiOp1 = getInitPhiReg(*InstOp1, NewBB);
2769*9880d681SAndroid Build Coastguard Worker }
2770*9880d681SAndroid Build Coastguard Worker if (!InKernel)
2771*9880d681SAndroid Build Coastguard Worker PhiOp2 = VRMap[PrevStage - np][Def];
2772*9880d681SAndroid Build Coastguard Worker
2773*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI.getRegClass(Def);
2774*9880d681SAndroid Build Coastguard Worker unsigned NewReg = MRI.createVirtualRegister(RC);
2775*9880d681SAndroid Build Coastguard Worker
2776*9880d681SAndroid Build Coastguard Worker MachineInstrBuilder NewPhi =
2777*9880d681SAndroid Build Coastguard Worker BuildMI(*NewBB, NewBB->getFirstNonPHI(), DebugLoc(),
2778*9880d681SAndroid Build Coastguard Worker TII->get(TargetOpcode::PHI), NewReg);
2779*9880d681SAndroid Build Coastguard Worker NewPhi.addReg(PhiOp1).addMBB(BB1);
2780*9880d681SAndroid Build Coastguard Worker NewPhi.addReg(PhiOp2).addMBB(BB2);
2781*9880d681SAndroid Build Coastguard Worker if (np == 0)
2782*9880d681SAndroid Build Coastguard Worker InstrMap[NewPhi] = &*BBI;
2783*9880d681SAndroid Build Coastguard Worker
2784*9880d681SAndroid Build Coastguard Worker // Rewrite uses and update the map. The actions depend upon whether
2785*9880d681SAndroid Build Coastguard Worker // we generating code for the kernel or epilog blocks.
2786*9880d681SAndroid Build Coastguard Worker if (InKernel) {
2787*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np,
2788*9880d681SAndroid Build Coastguard Worker &*BBI, PhiOp1, NewReg);
2789*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np,
2790*9880d681SAndroid Build Coastguard Worker &*BBI, PhiOp2, NewReg);
2791*9880d681SAndroid Build Coastguard Worker
2792*9880d681SAndroid Build Coastguard Worker PhiOp2 = NewReg;
2793*9880d681SAndroid Build Coastguard Worker VRMap[PrevStage - np - 1][Def] = NewReg;
2794*9880d681SAndroid Build Coastguard Worker } else {
2795*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum - np][Def] = NewReg;
2796*9880d681SAndroid Build Coastguard Worker if (np == NumPhis - 1)
2797*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, CurStageNum, np,
2798*9880d681SAndroid Build Coastguard Worker &*BBI, Def, NewReg);
2799*9880d681SAndroid Build Coastguard Worker }
2800*9880d681SAndroid Build Coastguard Worker if (IsLast && np == NumPhis - 1)
2801*9880d681SAndroid Build Coastguard Worker replaceRegUsesAfterLoop(Def, NewReg, BB, MRI, LIS);
2802*9880d681SAndroid Build Coastguard Worker }
2803*9880d681SAndroid Build Coastguard Worker }
2804*9880d681SAndroid Build Coastguard Worker }
2805*9880d681SAndroid Build Coastguard Worker }
2806*9880d681SAndroid Build Coastguard Worker
2807*9880d681SAndroid Build Coastguard Worker /// Remove instructions that generate values with no uses.
2808*9880d681SAndroid Build Coastguard Worker /// Typically, these are induction variable operations that generate values
2809*9880d681SAndroid Build Coastguard Worker /// used in the loop itself. A dead instruction has a definition with
2810*9880d681SAndroid Build Coastguard Worker /// no uses, or uses that occur in the original loop only.
removeDeadInstructions(MachineBasicBlock * KernelBB,MBBVectorTy & EpilogBBs)2811*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::removeDeadInstructions(MachineBasicBlock *KernelBB,
2812*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs) {
2813*9880d681SAndroid Build Coastguard Worker // For each epilog block, check that the value defined by each instruction
2814*9880d681SAndroid Build Coastguard Worker // is used. If not, delete it.
2815*9880d681SAndroid Build Coastguard Worker for (MBBVectorTy::reverse_iterator MBB = EpilogBBs.rbegin(),
2816*9880d681SAndroid Build Coastguard Worker MBE = EpilogBBs.rend();
2817*9880d681SAndroid Build Coastguard Worker MBB != MBE; ++MBB)
2818*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::reverse_instr_iterator MI = (*MBB)->instr_rbegin(),
2819*9880d681SAndroid Build Coastguard Worker ME = (*MBB)->instr_rend();
2820*9880d681SAndroid Build Coastguard Worker MI != ME;) {
2821*9880d681SAndroid Build Coastguard Worker // From DeadMachineInstructionElem. Don't delete inline assembly.
2822*9880d681SAndroid Build Coastguard Worker if (MI->isInlineAsm()) {
2823*9880d681SAndroid Build Coastguard Worker ++MI;
2824*9880d681SAndroid Build Coastguard Worker continue;
2825*9880d681SAndroid Build Coastguard Worker }
2826*9880d681SAndroid Build Coastguard Worker bool SawStore = false;
2827*9880d681SAndroid Build Coastguard Worker // Check if it's safe to remove the instruction due to side effects.
2828*9880d681SAndroid Build Coastguard Worker // We can, and want to, remove Phis here.
2829*9880d681SAndroid Build Coastguard Worker if (!MI->isSafeToMove(nullptr, SawStore) && !MI->isPHI()) {
2830*9880d681SAndroid Build Coastguard Worker ++MI;
2831*9880d681SAndroid Build Coastguard Worker continue;
2832*9880d681SAndroid Build Coastguard Worker }
2833*9880d681SAndroid Build Coastguard Worker bool used = true;
2834*9880d681SAndroid Build Coastguard Worker for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
2835*9880d681SAndroid Build Coastguard Worker MOE = MI->operands_end();
2836*9880d681SAndroid Build Coastguard Worker MOI != MOE; ++MOI) {
2837*9880d681SAndroid Build Coastguard Worker if (!MOI->isReg() || !MOI->isDef())
2838*9880d681SAndroid Build Coastguard Worker continue;
2839*9880d681SAndroid Build Coastguard Worker unsigned reg = MOI->getReg();
2840*9880d681SAndroid Build Coastguard Worker unsigned realUses = 0;
2841*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_iterator UI = MRI.use_begin(reg),
2842*9880d681SAndroid Build Coastguard Worker EI = MRI.use_end();
2843*9880d681SAndroid Build Coastguard Worker UI != EI; ++UI) {
2844*9880d681SAndroid Build Coastguard Worker // Check if there are any uses that occur only in the original
2845*9880d681SAndroid Build Coastguard Worker // loop. If so, that's not a real use.
2846*9880d681SAndroid Build Coastguard Worker if (UI->getParent()->getParent() != BB) {
2847*9880d681SAndroid Build Coastguard Worker realUses++;
2848*9880d681SAndroid Build Coastguard Worker used = true;
2849*9880d681SAndroid Build Coastguard Worker break;
2850*9880d681SAndroid Build Coastguard Worker }
2851*9880d681SAndroid Build Coastguard Worker }
2852*9880d681SAndroid Build Coastguard Worker if (realUses > 0)
2853*9880d681SAndroid Build Coastguard Worker break;
2854*9880d681SAndroid Build Coastguard Worker used = false;
2855*9880d681SAndroid Build Coastguard Worker }
2856*9880d681SAndroid Build Coastguard Worker if (!used) {
2857*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
2858*9880d681SAndroid Build Coastguard Worker ME = (*MBB)->instr_rend();
2859*9880d681SAndroid Build Coastguard Worker continue;
2860*9880d681SAndroid Build Coastguard Worker }
2861*9880d681SAndroid Build Coastguard Worker ++MI;
2862*9880d681SAndroid Build Coastguard Worker }
2863*9880d681SAndroid Build Coastguard Worker // In the kernel block, check if we can remove a Phi that generates a value
2864*9880d681SAndroid Build Coastguard Worker // used in an instruction removed in the epilog block.
2865*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = KernelBB->instr_begin(),
2866*9880d681SAndroid Build Coastguard Worker BBE = KernelBB->getFirstNonPHI();
2867*9880d681SAndroid Build Coastguard Worker BBI != BBE;) {
2868*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = &*BBI;
2869*9880d681SAndroid Build Coastguard Worker ++BBI;
2870*9880d681SAndroid Build Coastguard Worker unsigned reg = MI->getOperand(0).getReg();
2871*9880d681SAndroid Build Coastguard Worker if (MRI.use_begin(reg) == MRI.use_end()) {
2872*9880d681SAndroid Build Coastguard Worker MI->eraseFromParent();
2873*9880d681SAndroid Build Coastguard Worker }
2874*9880d681SAndroid Build Coastguard Worker }
2875*9880d681SAndroid Build Coastguard Worker }
2876*9880d681SAndroid Build Coastguard Worker
2877*9880d681SAndroid Build Coastguard Worker /// For loop carried definitions, we split the lifetime of a virtual register
2878*9880d681SAndroid Build Coastguard Worker /// that has uses past the definition in the next iteration. A copy with a new
2879*9880d681SAndroid Build Coastguard Worker /// virtual register is inserted before the definition, which helps with
2880*9880d681SAndroid Build Coastguard Worker /// generating a better register assignment.
2881*9880d681SAndroid Build Coastguard Worker ///
2882*9880d681SAndroid Build Coastguard Worker /// v1 = phi(a, v2) v1 = phi(a, v2)
2883*9880d681SAndroid Build Coastguard Worker /// v2 = phi(b, v3) v2 = phi(b, v3)
2884*9880d681SAndroid Build Coastguard Worker /// v3 = .. v4 = copy v1
2885*9880d681SAndroid Build Coastguard Worker /// .. = V1 v3 = ..
2886*9880d681SAndroid Build Coastguard Worker /// .. = v4
splitLifetimes(MachineBasicBlock * KernelBB,MBBVectorTy & EpilogBBs,SMSchedule & Schedule)2887*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::splitLifetimes(MachineBasicBlock *KernelBB,
2888*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs,
2889*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule) {
2890*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2891*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = KernelBB->instr_begin(),
2892*9880d681SAndroid Build Coastguard Worker BBF = KernelBB->getFirstNonPHI();
2893*9880d681SAndroid Build Coastguard Worker BBI != BBF; ++BBI) {
2894*9880d681SAndroid Build Coastguard Worker unsigned Def = BBI->getOperand(0).getReg();
2895*9880d681SAndroid Build Coastguard Worker // Check for any Phi definition that used as an operand of another Phi
2896*9880d681SAndroid Build Coastguard Worker // in the same block.
2897*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_instr_iterator I = MRI.use_instr_begin(Def),
2898*9880d681SAndroid Build Coastguard Worker E = MRI.use_instr_end();
2899*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
2900*9880d681SAndroid Build Coastguard Worker if (I->isPHI() && I->getParent() == KernelBB) {
2901*9880d681SAndroid Build Coastguard Worker // Get the loop carried definition.
2902*9880d681SAndroid Build Coastguard Worker unsigned LCDef = getLoopPhiReg(*BBI, KernelBB);
2903*9880d681SAndroid Build Coastguard Worker if (!LCDef)
2904*9880d681SAndroid Build Coastguard Worker continue;
2905*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = MRI.getVRegDef(LCDef);
2906*9880d681SAndroid Build Coastguard Worker if (!MI || MI->getParent() != KernelBB || MI->isPHI())
2907*9880d681SAndroid Build Coastguard Worker continue;
2908*9880d681SAndroid Build Coastguard Worker // Search through the rest of the block looking for uses of the Phi
2909*9880d681SAndroid Build Coastguard Worker // definition. If one occurs, then split the lifetime.
2910*9880d681SAndroid Build Coastguard Worker unsigned SplitReg = 0;
2911*9880d681SAndroid Build Coastguard Worker for (auto &BBJ : make_range(MachineBasicBlock::instr_iterator(MI),
2912*9880d681SAndroid Build Coastguard Worker KernelBB->instr_end()))
2913*9880d681SAndroid Build Coastguard Worker if (BBJ.readsRegister(Def)) {
2914*9880d681SAndroid Build Coastguard Worker // We split the lifetime when we find the first use.
2915*9880d681SAndroid Build Coastguard Worker if (SplitReg == 0) {
2916*9880d681SAndroid Build Coastguard Worker SplitReg = MRI.createVirtualRegister(MRI.getRegClass(Def));
2917*9880d681SAndroid Build Coastguard Worker BuildMI(*KernelBB, MI, MI->getDebugLoc(),
2918*9880d681SAndroid Build Coastguard Worker TII->get(TargetOpcode::COPY), SplitReg)
2919*9880d681SAndroid Build Coastguard Worker .addReg(Def);
2920*9880d681SAndroid Build Coastguard Worker }
2921*9880d681SAndroid Build Coastguard Worker BBJ.substituteRegister(Def, SplitReg, 0, *TRI);
2922*9880d681SAndroid Build Coastguard Worker }
2923*9880d681SAndroid Build Coastguard Worker if (!SplitReg)
2924*9880d681SAndroid Build Coastguard Worker continue;
2925*9880d681SAndroid Build Coastguard Worker // Search through each of the epilog blocks for any uses to be renamed.
2926*9880d681SAndroid Build Coastguard Worker for (auto &Epilog : EpilogBBs)
2927*9880d681SAndroid Build Coastguard Worker for (auto &I : *Epilog)
2928*9880d681SAndroid Build Coastguard Worker if (I.readsRegister(Def))
2929*9880d681SAndroid Build Coastguard Worker I.substituteRegister(Def, SplitReg, 0, *TRI);
2930*9880d681SAndroid Build Coastguard Worker break;
2931*9880d681SAndroid Build Coastguard Worker }
2932*9880d681SAndroid Build Coastguard Worker }
2933*9880d681SAndroid Build Coastguard Worker }
2934*9880d681SAndroid Build Coastguard Worker }
2935*9880d681SAndroid Build Coastguard Worker
2936*9880d681SAndroid Build Coastguard Worker /// Remove the incoming block from the Phis in a basic block.
removePhis(MachineBasicBlock * BB,MachineBasicBlock * Incoming)2937*9880d681SAndroid Build Coastguard Worker static void removePhis(MachineBasicBlock *BB, MachineBasicBlock *Incoming) {
2938*9880d681SAndroid Build Coastguard Worker for (MachineInstr &MI : *BB) {
2939*9880d681SAndroid Build Coastguard Worker if (!MI.isPHI())
2940*9880d681SAndroid Build Coastguard Worker break;
2941*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2)
2942*9880d681SAndroid Build Coastguard Worker if (MI.getOperand(i + 1).getMBB() == Incoming) {
2943*9880d681SAndroid Build Coastguard Worker MI.RemoveOperand(i + 1);
2944*9880d681SAndroid Build Coastguard Worker MI.RemoveOperand(i);
2945*9880d681SAndroid Build Coastguard Worker break;
2946*9880d681SAndroid Build Coastguard Worker }
2947*9880d681SAndroid Build Coastguard Worker }
2948*9880d681SAndroid Build Coastguard Worker }
2949*9880d681SAndroid Build Coastguard Worker
2950*9880d681SAndroid Build Coastguard Worker /// Create branches from each prolog basic block to the appropriate epilog
2951*9880d681SAndroid Build Coastguard Worker /// block. These edges are needed if the loop ends before reaching the
2952*9880d681SAndroid Build Coastguard Worker /// kernel.
addBranches(MBBVectorTy & PrologBBs,MachineBasicBlock * KernelBB,MBBVectorTy & EpilogBBs,SMSchedule & Schedule,ValueMapTy * VRMap)2953*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::addBranches(MBBVectorTy &PrologBBs,
2954*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *KernelBB,
2955*9880d681SAndroid Build Coastguard Worker MBBVectorTy &EpilogBBs,
2956*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule, ValueMapTy *VRMap) {
2957*9880d681SAndroid Build Coastguard Worker assert(PrologBBs.size() == EpilogBBs.size() && "Prolog/Epilog mismatch");
2958*9880d681SAndroid Build Coastguard Worker MachineInstr *IndVar = Pass.LI.LoopInductionVar;
2959*9880d681SAndroid Build Coastguard Worker MachineInstr *Cmp = Pass.LI.LoopCompare;
2960*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *LastPro = KernelBB;
2961*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *LastEpi = KernelBB;
2962*9880d681SAndroid Build Coastguard Worker
2963*9880d681SAndroid Build Coastguard Worker // Start from the blocks connected to the kernel and work "out"
2964*9880d681SAndroid Build Coastguard Worker // to the first prolog and the last epilog blocks.
2965*9880d681SAndroid Build Coastguard Worker SmallVector<MachineInstr *, 4> PrevInsts;
2966*9880d681SAndroid Build Coastguard Worker unsigned MaxIter = PrologBBs.size() - 1;
2967*9880d681SAndroid Build Coastguard Worker unsigned LC = UINT_MAX;
2968*9880d681SAndroid Build Coastguard Worker unsigned LCMin = UINT_MAX;
2969*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, j = MaxIter; i <= MaxIter; ++i, --j) {
2970*9880d681SAndroid Build Coastguard Worker // Add branches to the prolog that go to the corresponding
2971*9880d681SAndroid Build Coastguard Worker // epilog, and the fall-thru prolog/kernel block.
2972*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *Prolog = PrologBBs[j];
2973*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *Epilog = EpilogBBs[i];
2974*9880d681SAndroid Build Coastguard Worker // We've executed one iteration, so decrement the loop count and check for
2975*9880d681SAndroid Build Coastguard Worker // the loop end.
2976*9880d681SAndroid Build Coastguard Worker SmallVector<MachineOperand, 4> Cond;
2977*9880d681SAndroid Build Coastguard Worker // Check if the LOOP0 has already been removed. If so, then there is no need
2978*9880d681SAndroid Build Coastguard Worker // to reduce the trip count.
2979*9880d681SAndroid Build Coastguard Worker if (LC != 0)
2980*9880d681SAndroid Build Coastguard Worker LC = TII->reduceLoopCount(*Prolog, IndVar, Cmp, Cond, PrevInsts, j,
2981*9880d681SAndroid Build Coastguard Worker MaxIter);
2982*9880d681SAndroid Build Coastguard Worker
2983*9880d681SAndroid Build Coastguard Worker // Record the value of the first trip count, which is used to determine if
2984*9880d681SAndroid Build Coastguard Worker // branches and blocks can be removed for constant trip counts.
2985*9880d681SAndroid Build Coastguard Worker if (LCMin == UINT_MAX)
2986*9880d681SAndroid Build Coastguard Worker LCMin = LC;
2987*9880d681SAndroid Build Coastguard Worker
2988*9880d681SAndroid Build Coastguard Worker unsigned numAdded = 0;
2989*9880d681SAndroid Build Coastguard Worker if (TargetRegisterInfo::isVirtualRegister(LC)) {
2990*9880d681SAndroid Build Coastguard Worker Prolog->addSuccessor(Epilog);
2991*9880d681SAndroid Build Coastguard Worker numAdded = TII->InsertBranch(*Prolog, Epilog, LastPro, Cond, DebugLoc());
2992*9880d681SAndroid Build Coastguard Worker } else if (j >= LCMin) {
2993*9880d681SAndroid Build Coastguard Worker Prolog->addSuccessor(Epilog);
2994*9880d681SAndroid Build Coastguard Worker Prolog->removeSuccessor(LastPro);
2995*9880d681SAndroid Build Coastguard Worker LastEpi->removeSuccessor(Epilog);
2996*9880d681SAndroid Build Coastguard Worker numAdded = TII->InsertBranch(*Prolog, Epilog, 0, Cond, DebugLoc());
2997*9880d681SAndroid Build Coastguard Worker removePhis(Epilog, LastEpi);
2998*9880d681SAndroid Build Coastguard Worker // Remove the blocks that are no longer referenced.
2999*9880d681SAndroid Build Coastguard Worker if (LastPro != LastEpi) {
3000*9880d681SAndroid Build Coastguard Worker LastEpi->clear();
3001*9880d681SAndroid Build Coastguard Worker LastEpi->eraseFromParent();
3002*9880d681SAndroid Build Coastguard Worker }
3003*9880d681SAndroid Build Coastguard Worker LastPro->clear();
3004*9880d681SAndroid Build Coastguard Worker LastPro->eraseFromParent();
3005*9880d681SAndroid Build Coastguard Worker } else {
3006*9880d681SAndroid Build Coastguard Worker numAdded = TII->InsertBranch(*Prolog, LastPro, 0, Cond, DebugLoc());
3007*9880d681SAndroid Build Coastguard Worker removePhis(Epilog, Prolog);
3008*9880d681SAndroid Build Coastguard Worker }
3009*9880d681SAndroid Build Coastguard Worker LastPro = Prolog;
3010*9880d681SAndroid Build Coastguard Worker LastEpi = Epilog;
3011*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::reverse_instr_iterator I = Prolog->instr_rbegin(),
3012*9880d681SAndroid Build Coastguard Worker E = Prolog->instr_rend();
3013*9880d681SAndroid Build Coastguard Worker I != E && numAdded > 0; ++I, --numAdded)
3014*9880d681SAndroid Build Coastguard Worker updateInstruction(&*I, false, j, 0, Schedule, VRMap);
3015*9880d681SAndroid Build Coastguard Worker }
3016*9880d681SAndroid Build Coastguard Worker }
3017*9880d681SAndroid Build Coastguard Worker
3018*9880d681SAndroid Build Coastguard Worker /// Return true if we can compute the amount the instruction changes
3019*9880d681SAndroid Build Coastguard Worker /// during each iteration. Set Delta to the amount of the change.
computeDelta(MachineInstr & MI,unsigned & Delta)3020*9880d681SAndroid Build Coastguard Worker bool SwingSchedulerDAG::computeDelta(MachineInstr &MI, unsigned &Delta) {
3021*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
3022*9880d681SAndroid Build Coastguard Worker unsigned BaseReg;
3023*9880d681SAndroid Build Coastguard Worker int64_t Offset;
3024*9880d681SAndroid Build Coastguard Worker if (!TII->getMemOpBaseRegImmOfs(MI, BaseReg, Offset, TRI))
3025*9880d681SAndroid Build Coastguard Worker return false;
3026*9880d681SAndroid Build Coastguard Worker
3027*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MF.getRegInfo();
3028*9880d681SAndroid Build Coastguard Worker // Check if there is a Phi. If so, get the definition in the loop.
3029*9880d681SAndroid Build Coastguard Worker MachineInstr *BaseDef = MRI.getVRegDef(BaseReg);
3030*9880d681SAndroid Build Coastguard Worker if (BaseDef && BaseDef->isPHI()) {
3031*9880d681SAndroid Build Coastguard Worker BaseReg = getLoopPhiReg(*BaseDef, MI.getParent());
3032*9880d681SAndroid Build Coastguard Worker BaseDef = MRI.getVRegDef(BaseReg);
3033*9880d681SAndroid Build Coastguard Worker }
3034*9880d681SAndroid Build Coastguard Worker if (!BaseDef)
3035*9880d681SAndroid Build Coastguard Worker return false;
3036*9880d681SAndroid Build Coastguard Worker
3037*9880d681SAndroid Build Coastguard Worker int D = 0;
3038*9880d681SAndroid Build Coastguard Worker if (!TII->getIncrementValue(BaseDef, D) && D >= 0)
3039*9880d681SAndroid Build Coastguard Worker return false;
3040*9880d681SAndroid Build Coastguard Worker
3041*9880d681SAndroid Build Coastguard Worker Delta = D;
3042*9880d681SAndroid Build Coastguard Worker return true;
3043*9880d681SAndroid Build Coastguard Worker }
3044*9880d681SAndroid Build Coastguard Worker
3045*9880d681SAndroid Build Coastguard Worker /// Update the memory operand with a new offset when the pipeliner
3046*9880d681SAndroid Build Coastguard Worker /// generate a new copy of the instruction that refers to a
3047*9880d681SAndroid Build Coastguard Worker /// different memory location.
updateMemOperands(MachineInstr & NewMI,MachineInstr & OldMI,unsigned Num)3048*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::updateMemOperands(MachineInstr &NewMI,
3049*9880d681SAndroid Build Coastguard Worker MachineInstr &OldMI, unsigned Num) {
3050*9880d681SAndroid Build Coastguard Worker if (Num == 0)
3051*9880d681SAndroid Build Coastguard Worker return;
3052*9880d681SAndroid Build Coastguard Worker // If the instruction has memory operands, then adjust the offset
3053*9880d681SAndroid Build Coastguard Worker // when the instruction appears in different stages.
3054*9880d681SAndroid Build Coastguard Worker unsigned NumRefs = NewMI.memoperands_end() - NewMI.memoperands_begin();
3055*9880d681SAndroid Build Coastguard Worker if (NumRefs == 0)
3056*9880d681SAndroid Build Coastguard Worker return;
3057*9880d681SAndroid Build Coastguard Worker MachineInstr::mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NumRefs);
3058*9880d681SAndroid Build Coastguard Worker unsigned Refs = 0;
3059*9880d681SAndroid Build Coastguard Worker for (MachineInstr::mmo_iterator I = NewMI.memoperands_begin(),
3060*9880d681SAndroid Build Coastguard Worker E = NewMI.memoperands_end();
3061*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
3062*9880d681SAndroid Build Coastguard Worker if ((*I)->isVolatile() || (*I)->isInvariant() || (!(*I)->getValue())) {
3063*9880d681SAndroid Build Coastguard Worker NewMemRefs[Refs++] = *I;
3064*9880d681SAndroid Build Coastguard Worker continue;
3065*9880d681SAndroid Build Coastguard Worker }
3066*9880d681SAndroid Build Coastguard Worker unsigned Delta;
3067*9880d681SAndroid Build Coastguard Worker if (computeDelta(OldMI, Delta)) {
3068*9880d681SAndroid Build Coastguard Worker int64_t AdjOffset = Delta * Num;
3069*9880d681SAndroid Build Coastguard Worker NewMemRefs[Refs++] =
3070*9880d681SAndroid Build Coastguard Worker MF.getMachineMemOperand(*I, AdjOffset, (*I)->getSize());
3071*9880d681SAndroid Build Coastguard Worker } else
3072*9880d681SAndroid Build Coastguard Worker NewMemRefs[Refs++] = MF.getMachineMemOperand(*I, 0, UINT64_MAX);
3073*9880d681SAndroid Build Coastguard Worker }
3074*9880d681SAndroid Build Coastguard Worker NewMI.setMemRefs(NewMemRefs, NewMemRefs + NumRefs);
3075*9880d681SAndroid Build Coastguard Worker }
3076*9880d681SAndroid Build Coastguard Worker
3077*9880d681SAndroid Build Coastguard Worker /// Clone the instruction for the new pipelined loop and update the
3078*9880d681SAndroid Build Coastguard Worker /// memory operands, if needed.
cloneInstr(MachineInstr * OldMI,unsigned CurStageNum,unsigned InstStageNum)3079*9880d681SAndroid Build Coastguard Worker MachineInstr *SwingSchedulerDAG::cloneInstr(MachineInstr *OldMI,
3080*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum,
3081*9880d681SAndroid Build Coastguard Worker unsigned InstStageNum) {
3082*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = MF.CloneMachineInstr(OldMI);
3083*9880d681SAndroid Build Coastguard Worker // Check for tied operands in inline asm instructions. This should be handled
3084*9880d681SAndroid Build Coastguard Worker // elsewhere, but I'm not sure of the best solution.
3085*9880d681SAndroid Build Coastguard Worker if (OldMI->isInlineAsm())
3086*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = OldMI->getNumOperands(); i != e; ++i) {
3087*9880d681SAndroid Build Coastguard Worker const auto &MO = OldMI->getOperand(i);
3088*9880d681SAndroid Build Coastguard Worker if (MO.isReg() && MO.isUse())
3089*9880d681SAndroid Build Coastguard Worker break;
3090*9880d681SAndroid Build Coastguard Worker unsigned UseIdx;
3091*9880d681SAndroid Build Coastguard Worker if (OldMI->isRegTiedToUseOperand(i, &UseIdx))
3092*9880d681SAndroid Build Coastguard Worker NewMI->tieOperands(i, UseIdx);
3093*9880d681SAndroid Build Coastguard Worker }
3094*9880d681SAndroid Build Coastguard Worker updateMemOperands(*NewMI, *OldMI, CurStageNum - InstStageNum);
3095*9880d681SAndroid Build Coastguard Worker return NewMI;
3096*9880d681SAndroid Build Coastguard Worker }
3097*9880d681SAndroid Build Coastguard Worker
3098*9880d681SAndroid Build Coastguard Worker /// Clone the instruction for the new pipelined loop. If needed, this
3099*9880d681SAndroid Build Coastguard Worker /// function updates the instruction using the values saved in the
3100*9880d681SAndroid Build Coastguard Worker /// InstrChanges structure.
cloneAndChangeInstr(MachineInstr * OldMI,unsigned CurStageNum,unsigned InstStageNum,SMSchedule & Schedule)3101*9880d681SAndroid Build Coastguard Worker MachineInstr *SwingSchedulerDAG::cloneAndChangeInstr(MachineInstr *OldMI,
3102*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum,
3103*9880d681SAndroid Build Coastguard Worker unsigned InstStageNum,
3104*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule) {
3105*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = MF.CloneMachineInstr(OldMI);
3106*9880d681SAndroid Build Coastguard Worker DenseMap<SUnit *, std::pair<unsigned, int64_t>>::iterator It =
3107*9880d681SAndroid Build Coastguard Worker InstrChanges.find(getSUnit(OldMI));
3108*9880d681SAndroid Build Coastguard Worker if (It != InstrChanges.end()) {
3109*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, int64_t> RegAndOffset = It->second;
3110*9880d681SAndroid Build Coastguard Worker unsigned BasePos, OffsetPos;
3111*9880d681SAndroid Build Coastguard Worker if (!TII->getBaseAndOffsetPosition(OldMI, BasePos, OffsetPos))
3112*9880d681SAndroid Build Coastguard Worker return nullptr;
3113*9880d681SAndroid Build Coastguard Worker int64_t NewOffset = OldMI->getOperand(OffsetPos).getImm();
3114*9880d681SAndroid Build Coastguard Worker MachineInstr *LoopDef = findDefInLoop(RegAndOffset.first);
3115*9880d681SAndroid Build Coastguard Worker if (Schedule.stageScheduled(getSUnit(LoopDef)) > (signed)InstStageNum)
3116*9880d681SAndroid Build Coastguard Worker NewOffset += RegAndOffset.second * (CurStageNum - InstStageNum);
3117*9880d681SAndroid Build Coastguard Worker NewMI->getOperand(OffsetPos).setImm(NewOffset);
3118*9880d681SAndroid Build Coastguard Worker }
3119*9880d681SAndroid Build Coastguard Worker updateMemOperands(*NewMI, *OldMI, CurStageNum - InstStageNum);
3120*9880d681SAndroid Build Coastguard Worker return NewMI;
3121*9880d681SAndroid Build Coastguard Worker }
3122*9880d681SAndroid Build Coastguard Worker
3123*9880d681SAndroid Build Coastguard Worker /// Update the machine instruction with new virtual registers. This
3124*9880d681SAndroid Build Coastguard Worker /// function may change the defintions and/or uses.
updateInstruction(MachineInstr * NewMI,bool LastDef,unsigned CurStageNum,unsigned InstrStageNum,SMSchedule & Schedule,ValueMapTy * VRMap)3125*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::updateInstruction(MachineInstr *NewMI, bool LastDef,
3126*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum,
3127*9880d681SAndroid Build Coastguard Worker unsigned InstrStageNum,
3128*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule,
3129*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap) {
3130*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
3131*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = NewMI->getOperand(i);
3132*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
3133*9880d681SAndroid Build Coastguard Worker continue;
3134*9880d681SAndroid Build Coastguard Worker unsigned reg = MO.getReg();
3135*9880d681SAndroid Build Coastguard Worker if (MO.isDef()) {
3136*9880d681SAndroid Build Coastguard Worker // Create a new virtual register for the definition.
3137*9880d681SAndroid Build Coastguard Worker const TargetRegisterClass *RC = MRI.getRegClass(reg);
3138*9880d681SAndroid Build Coastguard Worker unsigned NewReg = MRI.createVirtualRegister(RC);
3139*9880d681SAndroid Build Coastguard Worker MO.setReg(NewReg);
3140*9880d681SAndroid Build Coastguard Worker VRMap[CurStageNum][reg] = NewReg;
3141*9880d681SAndroid Build Coastguard Worker if (LastDef)
3142*9880d681SAndroid Build Coastguard Worker replaceRegUsesAfterLoop(reg, NewReg, BB, MRI, LIS);
3143*9880d681SAndroid Build Coastguard Worker } else if (MO.isUse()) {
3144*9880d681SAndroid Build Coastguard Worker MachineInstr *Def = MRI.getVRegDef(reg);
3145*9880d681SAndroid Build Coastguard Worker // Compute the stage that contains the last definition for instruction.
3146*9880d681SAndroid Build Coastguard Worker int DefStageNum = Schedule.stageScheduled(getSUnit(Def));
3147*9880d681SAndroid Build Coastguard Worker unsigned StageNum = CurStageNum;
3148*9880d681SAndroid Build Coastguard Worker if (DefStageNum != -1 && (int)InstrStageNum > DefStageNum) {
3149*9880d681SAndroid Build Coastguard Worker // Compute the difference in stages between the defintion and the use.
3150*9880d681SAndroid Build Coastguard Worker unsigned StageDiff = (InstrStageNum - DefStageNum);
3151*9880d681SAndroid Build Coastguard Worker // Make an adjustment to get the last definition.
3152*9880d681SAndroid Build Coastguard Worker StageNum -= StageDiff;
3153*9880d681SAndroid Build Coastguard Worker }
3154*9880d681SAndroid Build Coastguard Worker if (VRMap[StageNum].count(reg))
3155*9880d681SAndroid Build Coastguard Worker MO.setReg(VRMap[StageNum][reg]);
3156*9880d681SAndroid Build Coastguard Worker }
3157*9880d681SAndroid Build Coastguard Worker }
3158*9880d681SAndroid Build Coastguard Worker }
3159*9880d681SAndroid Build Coastguard Worker
3160*9880d681SAndroid Build Coastguard Worker /// Return the instruction in the loop that defines the register.
3161*9880d681SAndroid Build Coastguard Worker /// If the definition is a Phi, then follow the Phi operand to
3162*9880d681SAndroid Build Coastguard Worker /// the instruction in the loop.
findDefInLoop(unsigned Reg)3163*9880d681SAndroid Build Coastguard Worker MachineInstr *SwingSchedulerDAG::findDefInLoop(unsigned Reg) {
3164*9880d681SAndroid Build Coastguard Worker SmallPtrSet<MachineInstr *, 8> Visited;
3165*9880d681SAndroid Build Coastguard Worker MachineInstr *Def = MRI.getVRegDef(Reg);
3166*9880d681SAndroid Build Coastguard Worker while (Def->isPHI()) {
3167*9880d681SAndroid Build Coastguard Worker if (!Visited.insert(Def).second)
3168*9880d681SAndroid Build Coastguard Worker break;
3169*9880d681SAndroid Build Coastguard Worker for (unsigned i = 1, e = Def->getNumOperands(); i < e; i += 2)
3170*9880d681SAndroid Build Coastguard Worker if (Def->getOperand(i + 1).getMBB() == BB) {
3171*9880d681SAndroid Build Coastguard Worker Def = MRI.getVRegDef(Def->getOperand(i).getReg());
3172*9880d681SAndroid Build Coastguard Worker break;
3173*9880d681SAndroid Build Coastguard Worker }
3174*9880d681SAndroid Build Coastguard Worker }
3175*9880d681SAndroid Build Coastguard Worker return Def;
3176*9880d681SAndroid Build Coastguard Worker }
3177*9880d681SAndroid Build Coastguard Worker
3178*9880d681SAndroid Build Coastguard Worker /// Return the new name for the value from the previous stage.
getPrevMapVal(unsigned StageNum,unsigned PhiStage,unsigned LoopVal,unsigned LoopStage,ValueMapTy * VRMap,MachineBasicBlock * BB)3179*9880d681SAndroid Build Coastguard Worker unsigned SwingSchedulerDAG::getPrevMapVal(unsigned StageNum, unsigned PhiStage,
3180*9880d681SAndroid Build Coastguard Worker unsigned LoopVal, unsigned LoopStage,
3181*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap,
3182*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB) {
3183*9880d681SAndroid Build Coastguard Worker unsigned PrevVal = 0;
3184*9880d681SAndroid Build Coastguard Worker if (StageNum > PhiStage) {
3185*9880d681SAndroid Build Coastguard Worker MachineInstr *LoopInst = MRI.getVRegDef(LoopVal);
3186*9880d681SAndroid Build Coastguard Worker if (PhiStage == LoopStage && VRMap[StageNum - 1].count(LoopVal))
3187*9880d681SAndroid Build Coastguard Worker // The name is defined in the previous stage.
3188*9880d681SAndroid Build Coastguard Worker PrevVal = VRMap[StageNum - 1][LoopVal];
3189*9880d681SAndroid Build Coastguard Worker else if (VRMap[StageNum].count(LoopVal))
3190*9880d681SAndroid Build Coastguard Worker // The previous name is defined in the current stage when the instruction
3191*9880d681SAndroid Build Coastguard Worker // order is swapped.
3192*9880d681SAndroid Build Coastguard Worker PrevVal = VRMap[StageNum][LoopVal];
3193*9880d681SAndroid Build Coastguard Worker else if (!LoopInst->isPHI())
3194*9880d681SAndroid Build Coastguard Worker // The loop value hasn't yet been scheduled.
3195*9880d681SAndroid Build Coastguard Worker PrevVal = LoopVal;
3196*9880d681SAndroid Build Coastguard Worker else if (StageNum == PhiStage + 1)
3197*9880d681SAndroid Build Coastguard Worker // The loop value is another phi, which has not been scheduled.
3198*9880d681SAndroid Build Coastguard Worker PrevVal = getInitPhiReg(*LoopInst, BB);
3199*9880d681SAndroid Build Coastguard Worker else if (StageNum > PhiStage + 1 && LoopInst->getParent() == BB)
3200*9880d681SAndroid Build Coastguard Worker // The loop value is another phi, which has been scheduled.
3201*9880d681SAndroid Build Coastguard Worker PrevVal =
3202*9880d681SAndroid Build Coastguard Worker getPrevMapVal(StageNum - 1, PhiStage, getLoopPhiReg(*LoopInst, BB),
3203*9880d681SAndroid Build Coastguard Worker LoopStage, VRMap, BB);
3204*9880d681SAndroid Build Coastguard Worker }
3205*9880d681SAndroid Build Coastguard Worker return PrevVal;
3206*9880d681SAndroid Build Coastguard Worker }
3207*9880d681SAndroid Build Coastguard Worker
3208*9880d681SAndroid Build Coastguard Worker /// Rewrite the Phi values in the specified block to use the mappings
3209*9880d681SAndroid Build Coastguard Worker /// from the initial operand. Once the Phi is scheduled, we switch
3210*9880d681SAndroid Build Coastguard Worker /// to using the loop value instead of the Phi value, so those names
3211*9880d681SAndroid Build Coastguard Worker /// do not need to be rewritten.
rewritePhiValues(MachineBasicBlock * NewBB,unsigned StageNum,SMSchedule & Schedule,ValueMapTy * VRMap,InstrMapTy & InstrMap)3212*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::rewritePhiValues(MachineBasicBlock *NewBB,
3213*9880d681SAndroid Build Coastguard Worker unsigned StageNum,
3214*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule,
3215*9880d681SAndroid Build Coastguard Worker ValueMapTy *VRMap,
3216*9880d681SAndroid Build Coastguard Worker InstrMapTy &InstrMap) {
3217*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator BBI = BB->instr_begin(),
3218*9880d681SAndroid Build Coastguard Worker BBE = BB->getFirstNonPHI();
3219*9880d681SAndroid Build Coastguard Worker BBI != BBE; ++BBI) {
3220*9880d681SAndroid Build Coastguard Worker unsigned InitVal = 0;
3221*9880d681SAndroid Build Coastguard Worker unsigned LoopVal = 0;
3222*9880d681SAndroid Build Coastguard Worker getPhiRegs(*BBI, BB, InitVal, LoopVal);
3223*9880d681SAndroid Build Coastguard Worker unsigned PhiDef = BBI->getOperand(0).getReg();
3224*9880d681SAndroid Build Coastguard Worker
3225*9880d681SAndroid Build Coastguard Worker unsigned PhiStage =
3226*9880d681SAndroid Build Coastguard Worker (unsigned)Schedule.stageScheduled(getSUnit(MRI.getVRegDef(PhiDef)));
3227*9880d681SAndroid Build Coastguard Worker unsigned LoopStage =
3228*9880d681SAndroid Build Coastguard Worker (unsigned)Schedule.stageScheduled(getSUnit(MRI.getVRegDef(LoopVal)));
3229*9880d681SAndroid Build Coastguard Worker unsigned NumPhis = Schedule.getStagesForPhi(PhiDef);
3230*9880d681SAndroid Build Coastguard Worker if (NumPhis > StageNum)
3231*9880d681SAndroid Build Coastguard Worker NumPhis = StageNum;
3232*9880d681SAndroid Build Coastguard Worker for (unsigned np = 0; np <= NumPhis; ++np) {
3233*9880d681SAndroid Build Coastguard Worker unsigned NewVal =
3234*9880d681SAndroid Build Coastguard Worker getPrevMapVal(StageNum - np, PhiStage, LoopVal, LoopStage, VRMap, BB);
3235*9880d681SAndroid Build Coastguard Worker if (!NewVal)
3236*9880d681SAndroid Build Coastguard Worker NewVal = InitVal;
3237*9880d681SAndroid Build Coastguard Worker rewriteScheduledInstr(NewBB, Schedule, InstrMap, StageNum - np, np, &*BBI,
3238*9880d681SAndroid Build Coastguard Worker PhiDef, NewVal);
3239*9880d681SAndroid Build Coastguard Worker }
3240*9880d681SAndroid Build Coastguard Worker }
3241*9880d681SAndroid Build Coastguard Worker }
3242*9880d681SAndroid Build Coastguard Worker
3243*9880d681SAndroid Build Coastguard Worker /// Rewrite a previously scheduled instruction to use the register value
3244*9880d681SAndroid Build Coastguard Worker /// from the new instruction. Make sure the instruction occurs in the
3245*9880d681SAndroid Build Coastguard Worker /// basic block, and we don't change the uses in the new instruction.
rewriteScheduledInstr(MachineBasicBlock * BB,SMSchedule & Schedule,InstrMapTy & InstrMap,unsigned CurStageNum,unsigned PhiNum,MachineInstr * Phi,unsigned OldReg,unsigned NewReg,unsigned PrevReg)3246*9880d681SAndroid Build Coastguard Worker void SwingSchedulerDAG::rewriteScheduledInstr(
3247*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *BB, SMSchedule &Schedule, InstrMapTy &InstrMap,
3248*9880d681SAndroid Build Coastguard Worker unsigned CurStageNum, unsigned PhiNum, MachineInstr *Phi, unsigned OldReg,
3249*9880d681SAndroid Build Coastguard Worker unsigned NewReg, unsigned PrevReg) {
3250*9880d681SAndroid Build Coastguard Worker bool InProlog = (CurStageNum < Schedule.getMaxStageCount());
3251*9880d681SAndroid Build Coastguard Worker int StagePhi = Schedule.stageScheduled(getSUnit(Phi)) + PhiNum;
3252*9880d681SAndroid Build Coastguard Worker // Rewrite uses that have been scheduled already to use the new
3253*9880d681SAndroid Build Coastguard Worker // Phi register.
3254*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_iterator UI = MRI.use_begin(OldReg),
3255*9880d681SAndroid Build Coastguard Worker EI = MRI.use_end();
3256*9880d681SAndroid Build Coastguard Worker UI != EI;) {
3257*9880d681SAndroid Build Coastguard Worker MachineOperand &UseOp = *UI;
3258*9880d681SAndroid Build Coastguard Worker MachineInstr *UseMI = UseOp.getParent();
3259*9880d681SAndroid Build Coastguard Worker ++UI;
3260*9880d681SAndroid Build Coastguard Worker if (UseMI->getParent() != BB)
3261*9880d681SAndroid Build Coastguard Worker continue;
3262*9880d681SAndroid Build Coastguard Worker if (UseMI->isPHI()) {
3263*9880d681SAndroid Build Coastguard Worker if (!Phi->isPHI() && UseMI->getOperand(0).getReg() == NewReg)
3264*9880d681SAndroid Build Coastguard Worker continue;
3265*9880d681SAndroid Build Coastguard Worker if (getLoopPhiReg(*UseMI, BB) != OldReg)
3266*9880d681SAndroid Build Coastguard Worker continue;
3267*9880d681SAndroid Build Coastguard Worker }
3268*9880d681SAndroid Build Coastguard Worker InstrMapTy::iterator OrigInstr = InstrMap.find(UseMI);
3269*9880d681SAndroid Build Coastguard Worker assert(OrigInstr != InstrMap.end() && "Instruction not scheduled.");
3270*9880d681SAndroid Build Coastguard Worker SUnit *OrigMISU = getSUnit(OrigInstr->second);
3271*9880d681SAndroid Build Coastguard Worker int StageSched = Schedule.stageScheduled(OrigMISU);
3272*9880d681SAndroid Build Coastguard Worker int CycleSched = Schedule.cycleScheduled(OrigMISU);
3273*9880d681SAndroid Build Coastguard Worker unsigned ReplaceReg = 0;
3274*9880d681SAndroid Build Coastguard Worker // This is the stage for the scheduled instruction.
3275*9880d681SAndroid Build Coastguard Worker if (StagePhi == StageSched && Phi->isPHI()) {
3276*9880d681SAndroid Build Coastguard Worker int CyclePhi = Schedule.cycleScheduled(getSUnit(Phi));
3277*9880d681SAndroid Build Coastguard Worker if (PrevReg && InProlog)
3278*9880d681SAndroid Build Coastguard Worker ReplaceReg = PrevReg;
3279*9880d681SAndroid Build Coastguard Worker else if (PrevReg && !Schedule.isLoopCarried(this, *Phi) &&
3280*9880d681SAndroid Build Coastguard Worker (CyclePhi <= CycleSched || OrigMISU->getInstr()->isPHI()))
3281*9880d681SAndroid Build Coastguard Worker ReplaceReg = PrevReg;
3282*9880d681SAndroid Build Coastguard Worker else
3283*9880d681SAndroid Build Coastguard Worker ReplaceReg = NewReg;
3284*9880d681SAndroid Build Coastguard Worker }
3285*9880d681SAndroid Build Coastguard Worker // The scheduled instruction occurs before the scheduled Phi, and the
3286*9880d681SAndroid Build Coastguard Worker // Phi is not loop carried.
3287*9880d681SAndroid Build Coastguard Worker if (!InProlog && StagePhi + 1 == StageSched &&
3288*9880d681SAndroid Build Coastguard Worker !Schedule.isLoopCarried(this, *Phi))
3289*9880d681SAndroid Build Coastguard Worker ReplaceReg = NewReg;
3290*9880d681SAndroid Build Coastguard Worker if (StagePhi > StageSched && Phi->isPHI())
3291*9880d681SAndroid Build Coastguard Worker ReplaceReg = NewReg;
3292*9880d681SAndroid Build Coastguard Worker if (!InProlog && !Phi->isPHI() && StagePhi < StageSched)
3293*9880d681SAndroid Build Coastguard Worker ReplaceReg = NewReg;
3294*9880d681SAndroid Build Coastguard Worker if (ReplaceReg) {
3295*9880d681SAndroid Build Coastguard Worker MRI.constrainRegClass(ReplaceReg, MRI.getRegClass(OldReg));
3296*9880d681SAndroid Build Coastguard Worker UseOp.setReg(ReplaceReg);
3297*9880d681SAndroid Build Coastguard Worker }
3298*9880d681SAndroid Build Coastguard Worker }
3299*9880d681SAndroid Build Coastguard Worker }
3300*9880d681SAndroid Build Coastguard Worker
3301*9880d681SAndroid Build Coastguard Worker /// Check if we can change the instruction to use an offset value from the
3302*9880d681SAndroid Build Coastguard Worker /// previous iteration. If so, return true and set the base and offset values
3303*9880d681SAndroid Build Coastguard Worker /// so that we can rewrite the load, if necessary.
3304*9880d681SAndroid Build Coastguard Worker /// v1 = Phi(v0, v3)
3305*9880d681SAndroid Build Coastguard Worker /// v2 = load v1, 0
3306*9880d681SAndroid Build Coastguard Worker /// v3 = post_store v1, 4, x
3307*9880d681SAndroid Build Coastguard Worker /// This function enables the load to be rewritten as v2 = load v3, 4.
canUseLastOffsetValue(MachineInstr * MI,unsigned & BasePos,unsigned & OffsetPos,unsigned & NewBase,int64_t & Offset)3308*9880d681SAndroid Build Coastguard Worker bool SwingSchedulerDAG::canUseLastOffsetValue(MachineInstr *MI,
3309*9880d681SAndroid Build Coastguard Worker unsigned &BasePos,
3310*9880d681SAndroid Build Coastguard Worker unsigned &OffsetPos,
3311*9880d681SAndroid Build Coastguard Worker unsigned &NewBase,
3312*9880d681SAndroid Build Coastguard Worker int64_t &Offset) {
3313*9880d681SAndroid Build Coastguard Worker // Get the load instruction.
3314*9880d681SAndroid Build Coastguard Worker if (TII->isPostIncrement(MI))
3315*9880d681SAndroid Build Coastguard Worker return false;
3316*9880d681SAndroid Build Coastguard Worker unsigned BasePosLd, OffsetPosLd;
3317*9880d681SAndroid Build Coastguard Worker if (!TII->getBaseAndOffsetPosition(MI, BasePosLd, OffsetPosLd))
3318*9880d681SAndroid Build Coastguard Worker return false;
3319*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = MI->getOperand(BasePosLd).getReg();
3320*9880d681SAndroid Build Coastguard Worker
3321*9880d681SAndroid Build Coastguard Worker // Look for the Phi instruction.
3322*9880d681SAndroid Build Coastguard Worker MachineRegisterInfo &MRI = MI->getParent()->getParent()->getRegInfo();
3323*9880d681SAndroid Build Coastguard Worker MachineInstr *Phi = MRI.getVRegDef(BaseReg);
3324*9880d681SAndroid Build Coastguard Worker if (!Phi || !Phi->isPHI())
3325*9880d681SAndroid Build Coastguard Worker return false;
3326*9880d681SAndroid Build Coastguard Worker // Get the register defined in the loop block.
3327*9880d681SAndroid Build Coastguard Worker unsigned PrevReg = getLoopPhiReg(*Phi, MI->getParent());
3328*9880d681SAndroid Build Coastguard Worker if (!PrevReg)
3329*9880d681SAndroid Build Coastguard Worker return false;
3330*9880d681SAndroid Build Coastguard Worker
3331*9880d681SAndroid Build Coastguard Worker // Check for the post-increment load/store instruction.
3332*9880d681SAndroid Build Coastguard Worker MachineInstr *PrevDef = MRI.getVRegDef(PrevReg);
3333*9880d681SAndroid Build Coastguard Worker if (!PrevDef || PrevDef == MI)
3334*9880d681SAndroid Build Coastguard Worker return false;
3335*9880d681SAndroid Build Coastguard Worker
3336*9880d681SAndroid Build Coastguard Worker if (!TII->isPostIncrement(PrevDef))
3337*9880d681SAndroid Build Coastguard Worker return false;
3338*9880d681SAndroid Build Coastguard Worker
3339*9880d681SAndroid Build Coastguard Worker unsigned BasePos1 = 0, OffsetPos1 = 0;
3340*9880d681SAndroid Build Coastguard Worker if (!TII->getBaseAndOffsetPosition(PrevDef, BasePos1, OffsetPos1))
3341*9880d681SAndroid Build Coastguard Worker return false;
3342*9880d681SAndroid Build Coastguard Worker
3343*9880d681SAndroid Build Coastguard Worker // Make sure offset values are both positive or both negative.
3344*9880d681SAndroid Build Coastguard Worker int64_t LoadOffset = MI->getOperand(OffsetPosLd).getImm();
3345*9880d681SAndroid Build Coastguard Worker int64_t StoreOffset = PrevDef->getOperand(OffsetPos1).getImm();
3346*9880d681SAndroid Build Coastguard Worker if ((LoadOffset >= 0) != (StoreOffset >= 0))
3347*9880d681SAndroid Build Coastguard Worker return false;
3348*9880d681SAndroid Build Coastguard Worker
3349*9880d681SAndroid Build Coastguard Worker // Set the return value once we determine that we return true.
3350*9880d681SAndroid Build Coastguard Worker BasePos = BasePosLd;
3351*9880d681SAndroid Build Coastguard Worker OffsetPos = OffsetPosLd;
3352*9880d681SAndroid Build Coastguard Worker NewBase = PrevReg;
3353*9880d681SAndroid Build Coastguard Worker Offset = StoreOffset;
3354*9880d681SAndroid Build Coastguard Worker return true;
3355*9880d681SAndroid Build Coastguard Worker }
3356*9880d681SAndroid Build Coastguard Worker
3357*9880d681SAndroid Build Coastguard Worker /// Apply changes to the instruction if needed. The changes are need
3358*9880d681SAndroid Build Coastguard Worker /// to improve the scheduling and depend up on the final schedule.
applyInstrChange(MachineInstr * MI,SMSchedule & Schedule,bool UpdateDAG)3359*9880d681SAndroid Build Coastguard Worker MachineInstr *SwingSchedulerDAG::applyInstrChange(MachineInstr *MI,
3360*9880d681SAndroid Build Coastguard Worker SMSchedule &Schedule,
3361*9880d681SAndroid Build Coastguard Worker bool UpdateDAG) {
3362*9880d681SAndroid Build Coastguard Worker SUnit *SU = getSUnit(MI);
3363*9880d681SAndroid Build Coastguard Worker DenseMap<SUnit *, std::pair<unsigned, int64_t>>::iterator It =
3364*9880d681SAndroid Build Coastguard Worker InstrChanges.find(SU);
3365*9880d681SAndroid Build Coastguard Worker if (It != InstrChanges.end()) {
3366*9880d681SAndroid Build Coastguard Worker std::pair<unsigned, int64_t> RegAndOffset = It->second;
3367*9880d681SAndroid Build Coastguard Worker unsigned BasePos, OffsetPos;
3368*9880d681SAndroid Build Coastguard Worker if (!TII->getBaseAndOffsetPosition(MI, BasePos, OffsetPos))
3369*9880d681SAndroid Build Coastguard Worker return nullptr;
3370*9880d681SAndroid Build Coastguard Worker unsigned BaseReg = MI->getOperand(BasePos).getReg();
3371*9880d681SAndroid Build Coastguard Worker MachineInstr *LoopDef = findDefInLoop(BaseReg);
3372*9880d681SAndroid Build Coastguard Worker int DefStageNum = Schedule.stageScheduled(getSUnit(LoopDef));
3373*9880d681SAndroid Build Coastguard Worker int DefCycleNum = Schedule.cycleScheduled(getSUnit(LoopDef));
3374*9880d681SAndroid Build Coastguard Worker int BaseStageNum = Schedule.stageScheduled(SU);
3375*9880d681SAndroid Build Coastguard Worker int BaseCycleNum = Schedule.cycleScheduled(SU);
3376*9880d681SAndroid Build Coastguard Worker if (BaseStageNum < DefStageNum) {
3377*9880d681SAndroid Build Coastguard Worker MachineInstr *NewMI = MF.CloneMachineInstr(MI);
3378*9880d681SAndroid Build Coastguard Worker int OffsetDiff = DefStageNum - BaseStageNum;
3379*9880d681SAndroid Build Coastguard Worker if (DefCycleNum < BaseCycleNum) {
3380*9880d681SAndroid Build Coastguard Worker NewMI->getOperand(BasePos).setReg(RegAndOffset.first);
3381*9880d681SAndroid Build Coastguard Worker if (OffsetDiff > 0)
3382*9880d681SAndroid Build Coastguard Worker --OffsetDiff;
3383*9880d681SAndroid Build Coastguard Worker }
3384*9880d681SAndroid Build Coastguard Worker int64_t NewOffset =
3385*9880d681SAndroid Build Coastguard Worker MI->getOperand(OffsetPos).getImm() + RegAndOffset.second * OffsetDiff;
3386*9880d681SAndroid Build Coastguard Worker NewMI->getOperand(OffsetPos).setImm(NewOffset);
3387*9880d681SAndroid Build Coastguard Worker if (UpdateDAG) {
3388*9880d681SAndroid Build Coastguard Worker SU->setInstr(NewMI);
3389*9880d681SAndroid Build Coastguard Worker MISUnitMap[NewMI] = SU;
3390*9880d681SAndroid Build Coastguard Worker }
3391*9880d681SAndroid Build Coastguard Worker NewMIs.insert(NewMI);
3392*9880d681SAndroid Build Coastguard Worker return NewMI;
3393*9880d681SAndroid Build Coastguard Worker }
3394*9880d681SAndroid Build Coastguard Worker }
3395*9880d681SAndroid Build Coastguard Worker return nullptr;
3396*9880d681SAndroid Build Coastguard Worker }
3397*9880d681SAndroid Build Coastguard Worker
3398*9880d681SAndroid Build Coastguard Worker /// Return true for an order dependence that is loop carried potentially.
3399*9880d681SAndroid Build Coastguard Worker /// An order dependence is loop carried if the destination defines a value
3400*9880d681SAndroid Build Coastguard Worker /// that may be used by the source in a subsequent iteration.
isLoopCarriedOrder(SUnit * Source,const SDep & Dep,bool isSucc)3401*9880d681SAndroid Build Coastguard Worker bool SwingSchedulerDAG::isLoopCarriedOrder(SUnit *Source, const SDep &Dep,
3402*9880d681SAndroid Build Coastguard Worker bool isSucc) {
3403*9880d681SAndroid Build Coastguard Worker if (!isOrder(Source, Dep) || Dep.isArtificial())
3404*9880d681SAndroid Build Coastguard Worker return false;
3405*9880d681SAndroid Build Coastguard Worker
3406*9880d681SAndroid Build Coastguard Worker if (!SwpPruneLoopCarried)
3407*9880d681SAndroid Build Coastguard Worker return true;
3408*9880d681SAndroid Build Coastguard Worker
3409*9880d681SAndroid Build Coastguard Worker MachineInstr *SI = Source->getInstr();
3410*9880d681SAndroid Build Coastguard Worker MachineInstr *DI = Dep.getSUnit()->getInstr();
3411*9880d681SAndroid Build Coastguard Worker if (!isSucc)
3412*9880d681SAndroid Build Coastguard Worker std::swap(SI, DI);
3413*9880d681SAndroid Build Coastguard Worker assert(SI != nullptr && DI != nullptr && "Expecting SUnit with an MI.");
3414*9880d681SAndroid Build Coastguard Worker
3415*9880d681SAndroid Build Coastguard Worker // Assume ordered loads and stores may have a loop carried dependence.
3416*9880d681SAndroid Build Coastguard Worker if (SI->hasUnmodeledSideEffects() || DI->hasUnmodeledSideEffects() ||
3417*9880d681SAndroid Build Coastguard Worker SI->hasOrderedMemoryRef() || DI->hasOrderedMemoryRef())
3418*9880d681SAndroid Build Coastguard Worker return true;
3419*9880d681SAndroid Build Coastguard Worker
3420*9880d681SAndroid Build Coastguard Worker // Only chain dependences between a load and store can be loop carried.
3421*9880d681SAndroid Build Coastguard Worker if (!DI->mayStore() || !SI->mayLoad())
3422*9880d681SAndroid Build Coastguard Worker return false;
3423*9880d681SAndroid Build Coastguard Worker
3424*9880d681SAndroid Build Coastguard Worker unsigned DeltaS, DeltaD;
3425*9880d681SAndroid Build Coastguard Worker if (!computeDelta(*SI, DeltaS) || !computeDelta(*DI, DeltaD))
3426*9880d681SAndroid Build Coastguard Worker return true;
3427*9880d681SAndroid Build Coastguard Worker
3428*9880d681SAndroid Build Coastguard Worker unsigned BaseRegS, BaseRegD;
3429*9880d681SAndroid Build Coastguard Worker int64_t OffsetS, OffsetD;
3430*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
3431*9880d681SAndroid Build Coastguard Worker if (!TII->getMemOpBaseRegImmOfs(*SI, BaseRegS, OffsetS, TRI) ||
3432*9880d681SAndroid Build Coastguard Worker !TII->getMemOpBaseRegImmOfs(*DI, BaseRegD, OffsetD, TRI))
3433*9880d681SAndroid Build Coastguard Worker return true;
3434*9880d681SAndroid Build Coastguard Worker
3435*9880d681SAndroid Build Coastguard Worker if (BaseRegS != BaseRegD)
3436*9880d681SAndroid Build Coastguard Worker return true;
3437*9880d681SAndroid Build Coastguard Worker
3438*9880d681SAndroid Build Coastguard Worker uint64_t AccessSizeS = (*SI->memoperands_begin())->getSize();
3439*9880d681SAndroid Build Coastguard Worker uint64_t AccessSizeD = (*DI->memoperands_begin())->getSize();
3440*9880d681SAndroid Build Coastguard Worker
3441*9880d681SAndroid Build Coastguard Worker // This is the main test, which checks the offset values and the loop
3442*9880d681SAndroid Build Coastguard Worker // increment value to determine if the accesses may be loop carried.
3443*9880d681SAndroid Build Coastguard Worker if (OffsetS >= OffsetD)
3444*9880d681SAndroid Build Coastguard Worker return OffsetS + AccessSizeS > DeltaS;
3445*9880d681SAndroid Build Coastguard Worker else if (OffsetS < OffsetD)
3446*9880d681SAndroid Build Coastguard Worker return OffsetD + AccessSizeD > DeltaD;
3447*9880d681SAndroid Build Coastguard Worker
3448*9880d681SAndroid Build Coastguard Worker return true;
3449*9880d681SAndroid Build Coastguard Worker }
3450*9880d681SAndroid Build Coastguard Worker
3451*9880d681SAndroid Build Coastguard Worker /// Try to schedule the node at the specified StartCycle and continue
3452*9880d681SAndroid Build Coastguard Worker /// until the node is schedule or the EndCycle is reached. This function
3453*9880d681SAndroid Build Coastguard Worker /// returns true if the node is scheduled. This routine may search either
3454*9880d681SAndroid Build Coastguard Worker /// forward or backward for a place to insert the instruction based upon
3455*9880d681SAndroid Build Coastguard Worker /// the relative values of StartCycle and EndCycle.
insert(SUnit * SU,int StartCycle,int EndCycle,int II)3456*9880d681SAndroid Build Coastguard Worker bool SMSchedule::insert(SUnit *SU, int StartCycle, int EndCycle, int II) {
3457*9880d681SAndroid Build Coastguard Worker bool forward = true;
3458*9880d681SAndroid Build Coastguard Worker if (StartCycle > EndCycle)
3459*9880d681SAndroid Build Coastguard Worker forward = false;
3460*9880d681SAndroid Build Coastguard Worker
3461*9880d681SAndroid Build Coastguard Worker // The terminating condition depends on the direction.
3462*9880d681SAndroid Build Coastguard Worker int termCycle = forward ? EndCycle + 1 : EndCycle - 1;
3463*9880d681SAndroid Build Coastguard Worker for (int curCycle = StartCycle; curCycle != termCycle;
3464*9880d681SAndroid Build Coastguard Worker forward ? ++curCycle : --curCycle) {
3465*9880d681SAndroid Build Coastguard Worker
3466*9880d681SAndroid Build Coastguard Worker // Add the already scheduled instructions at the specified cycle to the DFA.
3467*9880d681SAndroid Build Coastguard Worker Resources->clearResources();
3468*9880d681SAndroid Build Coastguard Worker for (int checkCycle = FirstCycle + ((curCycle - FirstCycle) % II);
3469*9880d681SAndroid Build Coastguard Worker checkCycle <= LastCycle; checkCycle += II) {
3470*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &cycleInstrs = ScheduledInstrs[checkCycle];
3471*9880d681SAndroid Build Coastguard Worker
3472*9880d681SAndroid Build Coastguard Worker for (std::deque<SUnit *>::iterator I = cycleInstrs.begin(),
3473*9880d681SAndroid Build Coastguard Worker E = cycleInstrs.end();
3474*9880d681SAndroid Build Coastguard Worker I != E; ++I) {
3475*9880d681SAndroid Build Coastguard Worker if (ST.getInstrInfo()->isZeroCost((*I)->getInstr()->getOpcode()))
3476*9880d681SAndroid Build Coastguard Worker continue;
3477*9880d681SAndroid Build Coastguard Worker assert(Resources->canReserveResources(*(*I)->getInstr()) &&
3478*9880d681SAndroid Build Coastguard Worker "These instructions have already been scheduled.");
3479*9880d681SAndroid Build Coastguard Worker Resources->reserveResources(*(*I)->getInstr());
3480*9880d681SAndroid Build Coastguard Worker }
3481*9880d681SAndroid Build Coastguard Worker }
3482*9880d681SAndroid Build Coastguard Worker if (ST.getInstrInfo()->isZeroCost(SU->getInstr()->getOpcode()) ||
3483*9880d681SAndroid Build Coastguard Worker Resources->canReserveResources(*SU->getInstr())) {
3484*9880d681SAndroid Build Coastguard Worker DEBUG({
3485*9880d681SAndroid Build Coastguard Worker dbgs() << "\tinsert at cycle " << curCycle << " ";
3486*9880d681SAndroid Build Coastguard Worker SU->getInstr()->dump();
3487*9880d681SAndroid Build Coastguard Worker });
3488*9880d681SAndroid Build Coastguard Worker
3489*9880d681SAndroid Build Coastguard Worker ScheduledInstrs[curCycle].push_back(SU);
3490*9880d681SAndroid Build Coastguard Worker InstrToCycle.insert(std::make_pair(SU, curCycle));
3491*9880d681SAndroid Build Coastguard Worker if (curCycle > LastCycle)
3492*9880d681SAndroid Build Coastguard Worker LastCycle = curCycle;
3493*9880d681SAndroid Build Coastguard Worker if (curCycle < FirstCycle)
3494*9880d681SAndroid Build Coastguard Worker FirstCycle = curCycle;
3495*9880d681SAndroid Build Coastguard Worker return true;
3496*9880d681SAndroid Build Coastguard Worker }
3497*9880d681SAndroid Build Coastguard Worker DEBUG({
3498*9880d681SAndroid Build Coastguard Worker dbgs() << "\tfailed to insert at cycle " << curCycle << " ";
3499*9880d681SAndroid Build Coastguard Worker SU->getInstr()->dump();
3500*9880d681SAndroid Build Coastguard Worker });
3501*9880d681SAndroid Build Coastguard Worker }
3502*9880d681SAndroid Build Coastguard Worker return false;
3503*9880d681SAndroid Build Coastguard Worker }
3504*9880d681SAndroid Build Coastguard Worker
3505*9880d681SAndroid Build Coastguard Worker // Return the cycle of the earliest scheduled instruction in the chain.
earliestCycleInChain(const SDep & Dep)3506*9880d681SAndroid Build Coastguard Worker int SMSchedule::earliestCycleInChain(const SDep &Dep) {
3507*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 8> Visited;
3508*9880d681SAndroid Build Coastguard Worker SmallVector<SDep, 8> Worklist;
3509*9880d681SAndroid Build Coastguard Worker Worklist.push_back(Dep);
3510*9880d681SAndroid Build Coastguard Worker int EarlyCycle = INT_MAX;
3511*9880d681SAndroid Build Coastguard Worker while (!Worklist.empty()) {
3512*9880d681SAndroid Build Coastguard Worker const SDep &Cur = Worklist.pop_back_val();
3513*9880d681SAndroid Build Coastguard Worker SUnit *PrevSU = Cur.getSUnit();
3514*9880d681SAndroid Build Coastguard Worker if (Visited.count(PrevSU))
3515*9880d681SAndroid Build Coastguard Worker continue;
3516*9880d681SAndroid Build Coastguard Worker std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(PrevSU);
3517*9880d681SAndroid Build Coastguard Worker if (it == InstrToCycle.end())
3518*9880d681SAndroid Build Coastguard Worker continue;
3519*9880d681SAndroid Build Coastguard Worker EarlyCycle = std::min(EarlyCycle, it->second);
3520*9880d681SAndroid Build Coastguard Worker for (const auto &PI : PrevSU->Preds)
3521*9880d681SAndroid Build Coastguard Worker if (SwingSchedulerDAG::isOrder(PrevSU, PI))
3522*9880d681SAndroid Build Coastguard Worker Worklist.push_back(PI);
3523*9880d681SAndroid Build Coastguard Worker Visited.insert(PrevSU);
3524*9880d681SAndroid Build Coastguard Worker }
3525*9880d681SAndroid Build Coastguard Worker return EarlyCycle;
3526*9880d681SAndroid Build Coastguard Worker }
3527*9880d681SAndroid Build Coastguard Worker
3528*9880d681SAndroid Build Coastguard Worker // Return the cycle of the latest scheduled instruction in the chain.
latestCycleInChain(const SDep & Dep)3529*9880d681SAndroid Build Coastguard Worker int SMSchedule::latestCycleInChain(const SDep &Dep) {
3530*9880d681SAndroid Build Coastguard Worker SmallPtrSet<SUnit *, 8> Visited;
3531*9880d681SAndroid Build Coastguard Worker SmallVector<SDep, 8> Worklist;
3532*9880d681SAndroid Build Coastguard Worker Worklist.push_back(Dep);
3533*9880d681SAndroid Build Coastguard Worker int LateCycle = INT_MIN;
3534*9880d681SAndroid Build Coastguard Worker while (!Worklist.empty()) {
3535*9880d681SAndroid Build Coastguard Worker const SDep &Cur = Worklist.pop_back_val();
3536*9880d681SAndroid Build Coastguard Worker SUnit *SuccSU = Cur.getSUnit();
3537*9880d681SAndroid Build Coastguard Worker if (Visited.count(SuccSU))
3538*9880d681SAndroid Build Coastguard Worker continue;
3539*9880d681SAndroid Build Coastguard Worker std::map<SUnit *, int>::const_iterator it = InstrToCycle.find(SuccSU);
3540*9880d681SAndroid Build Coastguard Worker if (it == InstrToCycle.end())
3541*9880d681SAndroid Build Coastguard Worker continue;
3542*9880d681SAndroid Build Coastguard Worker LateCycle = std::max(LateCycle, it->second);
3543*9880d681SAndroid Build Coastguard Worker for (const auto &SI : SuccSU->Succs)
3544*9880d681SAndroid Build Coastguard Worker if (SwingSchedulerDAG::isOrder(SuccSU, SI))
3545*9880d681SAndroid Build Coastguard Worker Worklist.push_back(SI);
3546*9880d681SAndroid Build Coastguard Worker Visited.insert(SuccSU);
3547*9880d681SAndroid Build Coastguard Worker }
3548*9880d681SAndroid Build Coastguard Worker return LateCycle;
3549*9880d681SAndroid Build Coastguard Worker }
3550*9880d681SAndroid Build Coastguard Worker
3551*9880d681SAndroid Build Coastguard Worker /// If an instruction has a use that spans multiple iterations, then
3552*9880d681SAndroid Build Coastguard Worker /// return true. These instructions are characterized by having a back-ege
3553*9880d681SAndroid Build Coastguard Worker /// to a Phi, which contains a reference to another Phi.
multipleIterations(SUnit * SU,SwingSchedulerDAG * DAG)3554*9880d681SAndroid Build Coastguard Worker static SUnit *multipleIterations(SUnit *SU, SwingSchedulerDAG *DAG) {
3555*9880d681SAndroid Build Coastguard Worker for (auto &P : SU->Preds)
3556*9880d681SAndroid Build Coastguard Worker if (DAG->isBackedge(SU, P) && P.getSUnit()->getInstr()->isPHI())
3557*9880d681SAndroid Build Coastguard Worker for (auto &S : P.getSUnit()->Succs)
3558*9880d681SAndroid Build Coastguard Worker if (S.getKind() == SDep::Order && S.getSUnit()->getInstr()->isPHI())
3559*9880d681SAndroid Build Coastguard Worker return P.getSUnit();
3560*9880d681SAndroid Build Coastguard Worker return nullptr;
3561*9880d681SAndroid Build Coastguard Worker }
3562*9880d681SAndroid Build Coastguard Worker
3563*9880d681SAndroid Build Coastguard Worker /// Compute the scheduling start slot for the instruction. The start slot
3564*9880d681SAndroid Build Coastguard Worker /// depends on any predecessor or successor nodes scheduled already.
computeStart(SUnit * SU,int * MaxEarlyStart,int * MinLateStart,int * MinEnd,int * MaxStart,int II,SwingSchedulerDAG * DAG)3565*9880d681SAndroid Build Coastguard Worker void SMSchedule::computeStart(SUnit *SU, int *MaxEarlyStart, int *MinLateStart,
3566*9880d681SAndroid Build Coastguard Worker int *MinEnd, int *MaxStart, int II,
3567*9880d681SAndroid Build Coastguard Worker SwingSchedulerDAG *DAG) {
3568*9880d681SAndroid Build Coastguard Worker // Iterate over each instruction that has been scheduled already. The start
3569*9880d681SAndroid Build Coastguard Worker // slot computuation depends on whether the previously scheduled instruction
3570*9880d681SAndroid Build Coastguard Worker // is a predecessor or successor of the specified instruction.
3571*9880d681SAndroid Build Coastguard Worker for (int cycle = getFirstCycle(); cycle <= LastCycle; ++cycle) {
3572*9880d681SAndroid Build Coastguard Worker
3573*9880d681SAndroid Build Coastguard Worker // Iterate over each instruction in the current cycle.
3574*9880d681SAndroid Build Coastguard Worker for (SUnit *I : getInstructions(cycle)) {
3575*9880d681SAndroid Build Coastguard Worker // Because we're processing a DAG for the dependences, we recognize
3576*9880d681SAndroid Build Coastguard Worker // the back-edge in recurrences by anti dependences.
3577*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = (unsigned)SU->Preds.size(); i != e; ++i) {
3578*9880d681SAndroid Build Coastguard Worker const SDep &Dep = SU->Preds[i];
3579*9880d681SAndroid Build Coastguard Worker if (Dep.getSUnit() == I) {
3580*9880d681SAndroid Build Coastguard Worker if (!DAG->isBackedge(SU, Dep)) {
3581*9880d681SAndroid Build Coastguard Worker int EarlyStart = cycle + DAG->getLatency(SU, Dep) -
3582*9880d681SAndroid Build Coastguard Worker DAG->getDistance(Dep.getSUnit(), SU, Dep) * II;
3583*9880d681SAndroid Build Coastguard Worker *MaxEarlyStart = std::max(*MaxEarlyStart, EarlyStart);
3584*9880d681SAndroid Build Coastguard Worker if (DAG->isLoopCarriedOrder(SU, Dep, false)) {
3585*9880d681SAndroid Build Coastguard Worker int End = earliestCycleInChain(Dep) + (II - 1);
3586*9880d681SAndroid Build Coastguard Worker *MinEnd = std::min(*MinEnd, End);
3587*9880d681SAndroid Build Coastguard Worker }
3588*9880d681SAndroid Build Coastguard Worker } else {
3589*9880d681SAndroid Build Coastguard Worker int LateStart = cycle - DAG->getLatency(SU, Dep) +
3590*9880d681SAndroid Build Coastguard Worker DAG->getDistance(SU, Dep.getSUnit(), Dep) * II;
3591*9880d681SAndroid Build Coastguard Worker *MinLateStart = std::min(*MinLateStart, LateStart);
3592*9880d681SAndroid Build Coastguard Worker }
3593*9880d681SAndroid Build Coastguard Worker }
3594*9880d681SAndroid Build Coastguard Worker // For instruction that requires multiple iterations, make sure that
3595*9880d681SAndroid Build Coastguard Worker // the dependent instruction is not scheduled past the definition.
3596*9880d681SAndroid Build Coastguard Worker SUnit *BE = multipleIterations(I, DAG);
3597*9880d681SAndroid Build Coastguard Worker if (BE && Dep.getSUnit() == BE && !SU->getInstr()->isPHI() &&
3598*9880d681SAndroid Build Coastguard Worker !SU->isPred(I))
3599*9880d681SAndroid Build Coastguard Worker *MinLateStart = std::min(*MinLateStart, cycle);
3600*9880d681SAndroid Build Coastguard Worker }
3601*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = (unsigned)SU->Succs.size(); i != e; ++i)
3602*9880d681SAndroid Build Coastguard Worker if (SU->Succs[i].getSUnit() == I) {
3603*9880d681SAndroid Build Coastguard Worker const SDep &Dep = SU->Succs[i];
3604*9880d681SAndroid Build Coastguard Worker if (!DAG->isBackedge(SU, Dep)) {
3605*9880d681SAndroid Build Coastguard Worker int LateStart = cycle - DAG->getLatency(SU, Dep) +
3606*9880d681SAndroid Build Coastguard Worker DAG->getDistance(SU, Dep.getSUnit(), Dep) * II;
3607*9880d681SAndroid Build Coastguard Worker *MinLateStart = std::min(*MinLateStart, LateStart);
3608*9880d681SAndroid Build Coastguard Worker if (DAG->isLoopCarriedOrder(SU, Dep)) {
3609*9880d681SAndroid Build Coastguard Worker int Start = latestCycleInChain(Dep) + 1 - II;
3610*9880d681SAndroid Build Coastguard Worker *MaxStart = std::max(*MaxStart, Start);
3611*9880d681SAndroid Build Coastguard Worker }
3612*9880d681SAndroid Build Coastguard Worker } else {
3613*9880d681SAndroid Build Coastguard Worker int EarlyStart = cycle + DAG->getLatency(SU, Dep) -
3614*9880d681SAndroid Build Coastguard Worker DAG->getDistance(Dep.getSUnit(), SU, Dep) * II;
3615*9880d681SAndroid Build Coastguard Worker *MaxEarlyStart = std::max(*MaxEarlyStart, EarlyStart);
3616*9880d681SAndroid Build Coastguard Worker }
3617*9880d681SAndroid Build Coastguard Worker }
3618*9880d681SAndroid Build Coastguard Worker }
3619*9880d681SAndroid Build Coastguard Worker }
3620*9880d681SAndroid Build Coastguard Worker }
3621*9880d681SAndroid Build Coastguard Worker
3622*9880d681SAndroid Build Coastguard Worker /// Order the instructions within a cycle so that the definitions occur
3623*9880d681SAndroid Build Coastguard Worker /// before the uses. Returns true if the instruction is added to the start
3624*9880d681SAndroid Build Coastguard Worker /// of the list, or false if added to the end.
orderDependence(SwingSchedulerDAG * SSD,SUnit * SU,std::deque<SUnit * > & Insts)3625*9880d681SAndroid Build Coastguard Worker bool SMSchedule::orderDependence(SwingSchedulerDAG *SSD, SUnit *SU,
3626*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &Insts) {
3627*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = SU->getInstr();
3628*9880d681SAndroid Build Coastguard Worker bool OrderBeforeUse = false;
3629*9880d681SAndroid Build Coastguard Worker bool OrderAfterDef = false;
3630*9880d681SAndroid Build Coastguard Worker bool OrderBeforeDef = false;
3631*9880d681SAndroid Build Coastguard Worker unsigned MoveDef = 0;
3632*9880d681SAndroid Build Coastguard Worker unsigned MoveUse = 0;
3633*9880d681SAndroid Build Coastguard Worker int StageInst1 = stageScheduled(SU);
3634*9880d681SAndroid Build Coastguard Worker
3635*9880d681SAndroid Build Coastguard Worker unsigned Pos = 0;
3636*9880d681SAndroid Build Coastguard Worker for (std::deque<SUnit *>::iterator I = Insts.begin(), E = Insts.end(); I != E;
3637*9880d681SAndroid Build Coastguard Worker ++I, ++Pos) {
3638*9880d681SAndroid Build Coastguard Worker // Relative order of Phis does not matter.
3639*9880d681SAndroid Build Coastguard Worker if (MI->isPHI() && (*I)->getInstr()->isPHI())
3640*9880d681SAndroid Build Coastguard Worker continue;
3641*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MI->getNumOperands(); i < e; ++i) {
3642*9880d681SAndroid Build Coastguard Worker MachineOperand &MO = MI->getOperand(i);
3643*9880d681SAndroid Build Coastguard Worker if (!MO.isReg() || !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
3644*9880d681SAndroid Build Coastguard Worker continue;
3645*9880d681SAndroid Build Coastguard Worker unsigned Reg = MO.getReg();
3646*9880d681SAndroid Build Coastguard Worker unsigned BasePos, OffsetPos;
3647*9880d681SAndroid Build Coastguard Worker if (ST.getInstrInfo()->getBaseAndOffsetPosition(MI, BasePos, OffsetPos))
3648*9880d681SAndroid Build Coastguard Worker if (MI->getOperand(BasePos).getReg() == Reg)
3649*9880d681SAndroid Build Coastguard Worker if (unsigned NewReg = SSD->getInstrBaseReg(SU))
3650*9880d681SAndroid Build Coastguard Worker Reg = NewReg;
3651*9880d681SAndroid Build Coastguard Worker bool Reads, Writes;
3652*9880d681SAndroid Build Coastguard Worker std::tie(Reads, Writes) =
3653*9880d681SAndroid Build Coastguard Worker (*I)->getInstr()->readsWritesVirtualRegister(Reg);
3654*9880d681SAndroid Build Coastguard Worker if (MO.isDef() && Reads && stageScheduled(*I) <= StageInst1) {
3655*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3656*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3657*9880d681SAndroid Build Coastguard Worker } else if (MO.isDef() && Reads && stageScheduled(*I) > StageInst1) {
3658*9880d681SAndroid Build Coastguard Worker // Add the instruction after the scheduled instruction.
3659*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3660*9880d681SAndroid Build Coastguard Worker MoveDef = Pos;
3661*9880d681SAndroid Build Coastguard Worker } else if (MO.isUse() && Writes && stageScheduled(*I) == StageInst1) {
3662*9880d681SAndroid Build Coastguard Worker if (cycleScheduled(*I) == cycleScheduled(SU) && !(*I)->isSucc(SU)) {
3663*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3664*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3665*9880d681SAndroid Build Coastguard Worker } else {
3666*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3667*9880d681SAndroid Build Coastguard Worker MoveDef = Pos;
3668*9880d681SAndroid Build Coastguard Worker }
3669*9880d681SAndroid Build Coastguard Worker } else if (MO.isUse() && Writes && stageScheduled(*I) > StageInst1) {
3670*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3671*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3672*9880d681SAndroid Build Coastguard Worker if (MoveUse != 0) {
3673*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3674*9880d681SAndroid Build Coastguard Worker MoveDef = Pos - 1;
3675*9880d681SAndroid Build Coastguard Worker }
3676*9880d681SAndroid Build Coastguard Worker } else if (MO.isUse() && Writes && stageScheduled(*I) < StageInst1) {
3677*9880d681SAndroid Build Coastguard Worker // Add the instruction before the scheduled instruction.
3678*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3679*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3680*9880d681SAndroid Build Coastguard Worker } else if (MO.isUse() && stageScheduled(*I) == StageInst1 &&
3681*9880d681SAndroid Build Coastguard Worker isLoopCarriedDefOfUse(SSD, (*I)->getInstr(), MO)) {
3682*9880d681SAndroid Build Coastguard Worker OrderBeforeDef = true;
3683*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3684*9880d681SAndroid Build Coastguard Worker }
3685*9880d681SAndroid Build Coastguard Worker }
3686*9880d681SAndroid Build Coastguard Worker // Check for order dependences between instructions. Make sure the source
3687*9880d681SAndroid Build Coastguard Worker // is ordered before the destination.
3688*9880d681SAndroid Build Coastguard Worker for (auto &S : SU->Succs)
3689*9880d681SAndroid Build Coastguard Worker if (S.getKind() == SDep::Order) {
3690*9880d681SAndroid Build Coastguard Worker if (S.getSUnit() == *I && stageScheduled(*I) == StageInst1) {
3691*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3692*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3693*9880d681SAndroid Build Coastguard Worker }
3694*9880d681SAndroid Build Coastguard Worker } else if (TargetRegisterInfo::isPhysicalRegister(S.getReg())) {
3695*9880d681SAndroid Build Coastguard Worker if (cycleScheduled(SU) != cycleScheduled(S.getSUnit())) {
3696*9880d681SAndroid Build Coastguard Worker if (S.isAssignedRegDep()) {
3697*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3698*9880d681SAndroid Build Coastguard Worker MoveDef = Pos;
3699*9880d681SAndroid Build Coastguard Worker }
3700*9880d681SAndroid Build Coastguard Worker } else {
3701*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3702*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3703*9880d681SAndroid Build Coastguard Worker }
3704*9880d681SAndroid Build Coastguard Worker }
3705*9880d681SAndroid Build Coastguard Worker for (auto &P : SU->Preds)
3706*9880d681SAndroid Build Coastguard Worker if (P.getKind() == SDep::Order) {
3707*9880d681SAndroid Build Coastguard Worker if (P.getSUnit() == *I && stageScheduled(*I) == StageInst1) {
3708*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3709*9880d681SAndroid Build Coastguard Worker MoveDef = Pos;
3710*9880d681SAndroid Build Coastguard Worker }
3711*9880d681SAndroid Build Coastguard Worker } else if (TargetRegisterInfo::isPhysicalRegister(P.getReg())) {
3712*9880d681SAndroid Build Coastguard Worker if (cycleScheduled(SU) != cycleScheduled(P.getSUnit())) {
3713*9880d681SAndroid Build Coastguard Worker if (P.isAssignedRegDep()) {
3714*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = true;
3715*9880d681SAndroid Build Coastguard Worker MoveUse = Pos;
3716*9880d681SAndroid Build Coastguard Worker }
3717*9880d681SAndroid Build Coastguard Worker } else {
3718*9880d681SAndroid Build Coastguard Worker OrderAfterDef = true;
3719*9880d681SAndroid Build Coastguard Worker MoveDef = Pos;
3720*9880d681SAndroid Build Coastguard Worker }
3721*9880d681SAndroid Build Coastguard Worker }
3722*9880d681SAndroid Build Coastguard Worker }
3723*9880d681SAndroid Build Coastguard Worker
3724*9880d681SAndroid Build Coastguard Worker // A circular dependence.
3725*9880d681SAndroid Build Coastguard Worker if (OrderAfterDef && OrderBeforeUse && MoveUse == MoveDef)
3726*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = false;
3727*9880d681SAndroid Build Coastguard Worker
3728*9880d681SAndroid Build Coastguard Worker // OrderAfterDef takes precedences over OrderBeforeDef. The latter is due
3729*9880d681SAndroid Build Coastguard Worker // to a loop-carried dependence.
3730*9880d681SAndroid Build Coastguard Worker if (OrderBeforeDef)
3731*9880d681SAndroid Build Coastguard Worker OrderBeforeUse = !OrderAfterDef || (MoveUse > MoveDef);
3732*9880d681SAndroid Build Coastguard Worker
3733*9880d681SAndroid Build Coastguard Worker // The uncommon case when the instruction order needs to be updated because
3734*9880d681SAndroid Build Coastguard Worker // there is both a use and def.
3735*9880d681SAndroid Build Coastguard Worker if (OrderBeforeUse && OrderAfterDef) {
3736*9880d681SAndroid Build Coastguard Worker SUnit *UseSU = Insts.at(MoveUse);
3737*9880d681SAndroid Build Coastguard Worker SUnit *DefSU = Insts.at(MoveDef);
3738*9880d681SAndroid Build Coastguard Worker if (MoveUse > MoveDef) {
3739*9880d681SAndroid Build Coastguard Worker Insts.erase(Insts.begin() + MoveUse);
3740*9880d681SAndroid Build Coastguard Worker Insts.erase(Insts.begin() + MoveDef);
3741*9880d681SAndroid Build Coastguard Worker } else {
3742*9880d681SAndroid Build Coastguard Worker Insts.erase(Insts.begin() + MoveDef);
3743*9880d681SAndroid Build Coastguard Worker Insts.erase(Insts.begin() + MoveUse);
3744*9880d681SAndroid Build Coastguard Worker }
3745*9880d681SAndroid Build Coastguard Worker if (orderDependence(SSD, UseSU, Insts)) {
3746*9880d681SAndroid Build Coastguard Worker Insts.push_front(SU);
3747*9880d681SAndroid Build Coastguard Worker orderDependence(SSD, DefSU, Insts);
3748*9880d681SAndroid Build Coastguard Worker return true;
3749*9880d681SAndroid Build Coastguard Worker }
3750*9880d681SAndroid Build Coastguard Worker Insts.pop_back();
3751*9880d681SAndroid Build Coastguard Worker Insts.push_back(SU);
3752*9880d681SAndroid Build Coastguard Worker Insts.push_back(UseSU);
3753*9880d681SAndroid Build Coastguard Worker orderDependence(SSD, DefSU, Insts);
3754*9880d681SAndroid Build Coastguard Worker return false;
3755*9880d681SAndroid Build Coastguard Worker }
3756*9880d681SAndroid Build Coastguard Worker // Put the new instruction first if there is a use in the list. Otherwise,
3757*9880d681SAndroid Build Coastguard Worker // put it at the end of the list.
3758*9880d681SAndroid Build Coastguard Worker if (OrderBeforeUse)
3759*9880d681SAndroid Build Coastguard Worker Insts.push_front(SU);
3760*9880d681SAndroid Build Coastguard Worker else
3761*9880d681SAndroid Build Coastguard Worker Insts.push_back(SU);
3762*9880d681SAndroid Build Coastguard Worker return OrderBeforeUse;
3763*9880d681SAndroid Build Coastguard Worker }
3764*9880d681SAndroid Build Coastguard Worker
3765*9880d681SAndroid Build Coastguard Worker /// Return true if the scheduled Phi has a loop carried operand.
isLoopCarried(SwingSchedulerDAG * SSD,MachineInstr & Phi)3766*9880d681SAndroid Build Coastguard Worker bool SMSchedule::isLoopCarried(SwingSchedulerDAG *SSD, MachineInstr &Phi) {
3767*9880d681SAndroid Build Coastguard Worker if (!Phi.isPHI())
3768*9880d681SAndroid Build Coastguard Worker return false;
3769*9880d681SAndroid Build Coastguard Worker assert(Phi.isPHI() && "Expecing a Phi.");
3770*9880d681SAndroid Build Coastguard Worker SUnit *DefSU = SSD->getSUnit(&Phi);
3771*9880d681SAndroid Build Coastguard Worker unsigned DefCycle = cycleScheduled(DefSU);
3772*9880d681SAndroid Build Coastguard Worker int DefStage = stageScheduled(DefSU);
3773*9880d681SAndroid Build Coastguard Worker
3774*9880d681SAndroid Build Coastguard Worker unsigned InitVal = 0;
3775*9880d681SAndroid Build Coastguard Worker unsigned LoopVal = 0;
3776*9880d681SAndroid Build Coastguard Worker getPhiRegs(Phi, Phi.getParent(), InitVal, LoopVal);
3777*9880d681SAndroid Build Coastguard Worker SUnit *UseSU = SSD->getSUnit(MRI.getVRegDef(LoopVal));
3778*9880d681SAndroid Build Coastguard Worker if (!UseSU)
3779*9880d681SAndroid Build Coastguard Worker return true;
3780*9880d681SAndroid Build Coastguard Worker if (UseSU->getInstr()->isPHI())
3781*9880d681SAndroid Build Coastguard Worker return true;
3782*9880d681SAndroid Build Coastguard Worker unsigned LoopCycle = cycleScheduled(UseSU);
3783*9880d681SAndroid Build Coastguard Worker int LoopStage = stageScheduled(UseSU);
3784*9880d681SAndroid Build Coastguard Worker return LoopCycle > DefCycle ||
3785*9880d681SAndroid Build Coastguard Worker (LoopCycle <= DefCycle && LoopStage <= DefStage);
3786*9880d681SAndroid Build Coastguard Worker }
3787*9880d681SAndroid Build Coastguard Worker
3788*9880d681SAndroid Build Coastguard Worker /// Return true if the instruction is a definition that is loop carried
3789*9880d681SAndroid Build Coastguard Worker /// and defines the use on the next iteration.
3790*9880d681SAndroid Build Coastguard Worker /// v1 = phi(v2, v3)
3791*9880d681SAndroid Build Coastguard Worker /// (Def) v3 = op v1
3792*9880d681SAndroid Build Coastguard Worker /// (MO) = v1
3793*9880d681SAndroid Build Coastguard Worker /// If MO appears before Def, then then v1 and v3 may get assigned to the same
3794*9880d681SAndroid Build Coastguard Worker /// register.
isLoopCarriedDefOfUse(SwingSchedulerDAG * SSD,MachineInstr * Def,MachineOperand & MO)3795*9880d681SAndroid Build Coastguard Worker bool SMSchedule::isLoopCarriedDefOfUse(SwingSchedulerDAG *SSD,
3796*9880d681SAndroid Build Coastguard Worker MachineInstr *Def, MachineOperand &MO) {
3797*9880d681SAndroid Build Coastguard Worker if (!MO.isReg())
3798*9880d681SAndroid Build Coastguard Worker return false;
3799*9880d681SAndroid Build Coastguard Worker if (Def->isPHI())
3800*9880d681SAndroid Build Coastguard Worker return false;
3801*9880d681SAndroid Build Coastguard Worker MachineInstr *Phi = MRI.getVRegDef(MO.getReg());
3802*9880d681SAndroid Build Coastguard Worker if (!Phi || !Phi->isPHI() || Phi->getParent() != Def->getParent())
3803*9880d681SAndroid Build Coastguard Worker return false;
3804*9880d681SAndroid Build Coastguard Worker if (!isLoopCarried(SSD, *Phi))
3805*9880d681SAndroid Build Coastguard Worker return false;
3806*9880d681SAndroid Build Coastguard Worker unsigned LoopReg = getLoopPhiReg(*Phi, Phi->getParent());
3807*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = Def->getNumOperands(); i != e; ++i) {
3808*9880d681SAndroid Build Coastguard Worker MachineOperand &DMO = Def->getOperand(i);
3809*9880d681SAndroid Build Coastguard Worker if (!DMO.isReg() || !DMO.isDef())
3810*9880d681SAndroid Build Coastguard Worker continue;
3811*9880d681SAndroid Build Coastguard Worker if (DMO.getReg() == LoopReg)
3812*9880d681SAndroid Build Coastguard Worker return true;
3813*9880d681SAndroid Build Coastguard Worker }
3814*9880d681SAndroid Build Coastguard Worker return false;
3815*9880d681SAndroid Build Coastguard Worker }
3816*9880d681SAndroid Build Coastguard Worker
3817*9880d681SAndroid Build Coastguard Worker // Check if the generated schedule is valid. This function checks if
3818*9880d681SAndroid Build Coastguard Worker // an instruction that uses a physical register is scheduled in a
3819*9880d681SAndroid Build Coastguard Worker // different stage than the definition. The pipeliner does not handle
3820*9880d681SAndroid Build Coastguard Worker // physical register values that may cross a basic block boundary.
isValidSchedule(SwingSchedulerDAG * SSD)3821*9880d681SAndroid Build Coastguard Worker bool SMSchedule::isValidSchedule(SwingSchedulerDAG *SSD) {
3822*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *TRI = ST.getRegisterInfo();
3823*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = SSD->SUnits.size(); i < e; ++i) {
3824*9880d681SAndroid Build Coastguard Worker SUnit &SU = SSD->SUnits[i];
3825*9880d681SAndroid Build Coastguard Worker if (!SU.hasPhysRegDefs)
3826*9880d681SAndroid Build Coastguard Worker continue;
3827*9880d681SAndroid Build Coastguard Worker int StageDef = stageScheduled(&SU);
3828*9880d681SAndroid Build Coastguard Worker assert(StageDef != -1 && "Instruction should have been scheduled.");
3829*9880d681SAndroid Build Coastguard Worker for (auto &SI : SU.Succs)
3830*9880d681SAndroid Build Coastguard Worker if (SI.isAssignedRegDep())
3831*9880d681SAndroid Build Coastguard Worker if (TRI->isPhysicalRegister(SI.getReg()))
3832*9880d681SAndroid Build Coastguard Worker if (stageScheduled(SI.getSUnit()) != StageDef)
3833*9880d681SAndroid Build Coastguard Worker return false;
3834*9880d681SAndroid Build Coastguard Worker }
3835*9880d681SAndroid Build Coastguard Worker return true;
3836*9880d681SAndroid Build Coastguard Worker }
3837*9880d681SAndroid Build Coastguard Worker
3838*9880d681SAndroid Build Coastguard Worker /// After the schedule has been formed, call this function to combine
3839*9880d681SAndroid Build Coastguard Worker /// the instructions from the different stages/cycles. That is, this
3840*9880d681SAndroid Build Coastguard Worker /// function creates a schedule that represents a single iteration.
finalizeSchedule(SwingSchedulerDAG * SSD)3841*9880d681SAndroid Build Coastguard Worker void SMSchedule::finalizeSchedule(SwingSchedulerDAG *SSD) {
3842*9880d681SAndroid Build Coastguard Worker // Move all instructions to the first stage from later stages.
3843*9880d681SAndroid Build Coastguard Worker for (int cycle = getFirstCycle(); cycle <= getFinalCycle(); ++cycle) {
3844*9880d681SAndroid Build Coastguard Worker for (int stage = 1, lastStage = getMaxStageCount(); stage <= lastStage;
3845*9880d681SAndroid Build Coastguard Worker ++stage) {
3846*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &cycleInstrs =
3847*9880d681SAndroid Build Coastguard Worker ScheduledInstrs[cycle + (stage * InitiationInterval)];
3848*9880d681SAndroid Build Coastguard Worker for (std::deque<SUnit *>::reverse_iterator I = cycleInstrs.rbegin(),
3849*9880d681SAndroid Build Coastguard Worker E = cycleInstrs.rend();
3850*9880d681SAndroid Build Coastguard Worker I != E; ++I)
3851*9880d681SAndroid Build Coastguard Worker ScheduledInstrs[cycle].push_front(*I);
3852*9880d681SAndroid Build Coastguard Worker }
3853*9880d681SAndroid Build Coastguard Worker }
3854*9880d681SAndroid Build Coastguard Worker // Iterate over the definitions in each instruction, and compute the
3855*9880d681SAndroid Build Coastguard Worker // stage difference for each use. Keep the maximum value.
3856*9880d681SAndroid Build Coastguard Worker for (auto &I : InstrToCycle) {
3857*9880d681SAndroid Build Coastguard Worker int DefStage = stageScheduled(I.first);
3858*9880d681SAndroid Build Coastguard Worker MachineInstr *MI = I.first->getInstr();
3859*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = MI->getNumOperands(); i < e; ++i) {
3860*9880d681SAndroid Build Coastguard Worker MachineOperand &Op = MI->getOperand(i);
3861*9880d681SAndroid Build Coastguard Worker if (!Op.isReg() || !Op.isDef())
3862*9880d681SAndroid Build Coastguard Worker continue;
3863*9880d681SAndroid Build Coastguard Worker
3864*9880d681SAndroid Build Coastguard Worker unsigned Reg = Op.getReg();
3865*9880d681SAndroid Build Coastguard Worker unsigned MaxDiff = 0;
3866*9880d681SAndroid Build Coastguard Worker bool PhiIsSwapped = false;
3867*9880d681SAndroid Build Coastguard Worker for (MachineRegisterInfo::use_iterator UI = MRI.use_begin(Reg),
3868*9880d681SAndroid Build Coastguard Worker EI = MRI.use_end();
3869*9880d681SAndroid Build Coastguard Worker UI != EI; ++UI) {
3870*9880d681SAndroid Build Coastguard Worker MachineOperand &UseOp = *UI;
3871*9880d681SAndroid Build Coastguard Worker MachineInstr *UseMI = UseOp.getParent();
3872*9880d681SAndroid Build Coastguard Worker SUnit *SUnitUse = SSD->getSUnit(UseMI);
3873*9880d681SAndroid Build Coastguard Worker int UseStage = stageScheduled(SUnitUse);
3874*9880d681SAndroid Build Coastguard Worker unsigned Diff = 0;
3875*9880d681SAndroid Build Coastguard Worker if (UseStage != -1 && UseStage >= DefStage)
3876*9880d681SAndroid Build Coastguard Worker Diff = UseStage - DefStage;
3877*9880d681SAndroid Build Coastguard Worker if (MI->isPHI()) {
3878*9880d681SAndroid Build Coastguard Worker if (isLoopCarried(SSD, *MI))
3879*9880d681SAndroid Build Coastguard Worker ++Diff;
3880*9880d681SAndroid Build Coastguard Worker else
3881*9880d681SAndroid Build Coastguard Worker PhiIsSwapped = true;
3882*9880d681SAndroid Build Coastguard Worker }
3883*9880d681SAndroid Build Coastguard Worker MaxDiff = std::max(Diff, MaxDiff);
3884*9880d681SAndroid Build Coastguard Worker }
3885*9880d681SAndroid Build Coastguard Worker RegToStageDiff[Reg] = std::make_pair(MaxDiff, PhiIsSwapped);
3886*9880d681SAndroid Build Coastguard Worker }
3887*9880d681SAndroid Build Coastguard Worker }
3888*9880d681SAndroid Build Coastguard Worker
3889*9880d681SAndroid Build Coastguard Worker // Erase all the elements in the later stages. Only one iteration should
3890*9880d681SAndroid Build Coastguard Worker // remain in the scheduled list, and it contains all the instructions.
3891*9880d681SAndroid Build Coastguard Worker for (int cycle = getFinalCycle() + 1; cycle <= LastCycle; ++cycle)
3892*9880d681SAndroid Build Coastguard Worker ScheduledInstrs.erase(cycle);
3893*9880d681SAndroid Build Coastguard Worker
3894*9880d681SAndroid Build Coastguard Worker // Change the registers in instruction as specified in the InstrChanges
3895*9880d681SAndroid Build Coastguard Worker // map. We need to use the new registers to create the correct order.
3896*9880d681SAndroid Build Coastguard Worker for (int i = 0, e = SSD->SUnits.size(); i != e; ++i) {
3897*9880d681SAndroid Build Coastguard Worker SUnit *SU = &SSD->SUnits[i];
3898*9880d681SAndroid Build Coastguard Worker SSD->applyInstrChange(SU->getInstr(), *this, true);
3899*9880d681SAndroid Build Coastguard Worker }
3900*9880d681SAndroid Build Coastguard Worker
3901*9880d681SAndroid Build Coastguard Worker // Reorder the instructions in each cycle to fix and improve the
3902*9880d681SAndroid Build Coastguard Worker // generated code.
3903*9880d681SAndroid Build Coastguard Worker for (int Cycle = getFirstCycle(), E = getFinalCycle(); Cycle <= E; ++Cycle) {
3904*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> &cycleInstrs = ScheduledInstrs[Cycle];
3905*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> newOrderZC;
3906*9880d681SAndroid Build Coastguard Worker // Put the zero-cost, pseudo instructions at the start of the cycle.
3907*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = cycleInstrs.size(); i < e; ++i) {
3908*9880d681SAndroid Build Coastguard Worker SUnit *SU = cycleInstrs[i];
3909*9880d681SAndroid Build Coastguard Worker if (ST.getInstrInfo()->isZeroCost(SU->getInstr()->getOpcode()))
3910*9880d681SAndroid Build Coastguard Worker orderDependence(SSD, SU, newOrderZC);
3911*9880d681SAndroid Build Coastguard Worker }
3912*9880d681SAndroid Build Coastguard Worker std::deque<SUnit *> newOrderI;
3913*9880d681SAndroid Build Coastguard Worker // Then, add the regular instructions back.
3914*9880d681SAndroid Build Coastguard Worker for (unsigned i = 0, e = cycleInstrs.size(); i < e; ++i) {
3915*9880d681SAndroid Build Coastguard Worker SUnit *SU = cycleInstrs[i];
3916*9880d681SAndroid Build Coastguard Worker if (!ST.getInstrInfo()->isZeroCost(SU->getInstr()->getOpcode()))
3917*9880d681SAndroid Build Coastguard Worker orderDependence(SSD, SU, newOrderI);
3918*9880d681SAndroid Build Coastguard Worker }
3919*9880d681SAndroid Build Coastguard Worker // Replace the old order with the new order.
3920*9880d681SAndroid Build Coastguard Worker cycleInstrs.swap(newOrderZC);
3921*9880d681SAndroid Build Coastguard Worker cycleInstrs.insert(cycleInstrs.end(), newOrderI.begin(), newOrderI.end());
3922*9880d681SAndroid Build Coastguard Worker }
3923*9880d681SAndroid Build Coastguard Worker
3924*9880d681SAndroid Build Coastguard Worker DEBUG(dump(););
3925*9880d681SAndroid Build Coastguard Worker }
3926*9880d681SAndroid Build Coastguard Worker
3927*9880d681SAndroid Build Coastguard Worker /// Print the schedule information to the given output.
print(raw_ostream & os) const3928*9880d681SAndroid Build Coastguard Worker void SMSchedule::print(raw_ostream &os) const {
3929*9880d681SAndroid Build Coastguard Worker // Iterate over each cycle.
3930*9880d681SAndroid Build Coastguard Worker for (int cycle = getFirstCycle(); cycle <= getFinalCycle(); ++cycle) {
3931*9880d681SAndroid Build Coastguard Worker // Iterate over each instruction in the cycle.
3932*9880d681SAndroid Build Coastguard Worker const_sched_iterator cycleInstrs = ScheduledInstrs.find(cycle);
3933*9880d681SAndroid Build Coastguard Worker for (SUnit *CI : cycleInstrs->second) {
3934*9880d681SAndroid Build Coastguard Worker os << "cycle " << cycle << " (" << stageScheduled(CI) << ") ";
3935*9880d681SAndroid Build Coastguard Worker os << "(" << CI->NodeNum << ") ";
3936*9880d681SAndroid Build Coastguard Worker CI->getInstr()->print(os);
3937*9880d681SAndroid Build Coastguard Worker os << "\n";
3938*9880d681SAndroid Build Coastguard Worker }
3939*9880d681SAndroid Build Coastguard Worker }
3940*9880d681SAndroid Build Coastguard Worker }
3941*9880d681SAndroid Build Coastguard Worker
3942*9880d681SAndroid Build Coastguard Worker /// Utility function used for debugging to print the schedule.
dump() const3943*9880d681SAndroid Build Coastguard Worker void SMSchedule::dump() const { print(dbgs()); }
3944