xref: /aosp_15_r20/external/llvm/lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- ResourcePriorityQueue.cpp - A DFA-oriented priority queue -*- C++ -*-==//
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 // This file implements the ResourcePriorityQueue class, which is a
11*9880d681SAndroid Build Coastguard Worker // SchedulingPriorityQueue that prioritizes instructions using DFA state to
12*9880d681SAndroid Build Coastguard Worker // reduce the length of the critical path through the basic block
13*9880d681SAndroid Build Coastguard Worker // on VLIW platforms.
14*9880d681SAndroid Build Coastguard Worker // The scheduler is basically a top-down adaptable list scheduler with DFA
15*9880d681SAndroid Build Coastguard Worker // resource tracking added to the cost function.
16*9880d681SAndroid Build Coastguard Worker // DFA is queried as a state machine to model "packets/bundles" during
17*9880d681SAndroid Build Coastguard Worker // schedule. Currently packets/bundles are discarded at the end of
18*9880d681SAndroid Build Coastguard Worker // scheduling, affecting only order of instructions.
19*9880d681SAndroid Build Coastguard Worker //
20*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/ResourcePriorityQueue.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstr.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/SelectionDAGNodes.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/CommandLine.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetLowering.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker using namespace llvm;
33*9880d681SAndroid Build Coastguard Worker 
34*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "scheduler"
35*9880d681SAndroid Build Coastguard Worker 
36*9880d681SAndroid Build Coastguard Worker static cl::opt<bool> DisableDFASched("disable-dfa-sched", cl::Hidden,
37*9880d681SAndroid Build Coastguard Worker   cl::ZeroOrMore, cl::init(false),
38*9880d681SAndroid Build Coastguard Worker   cl::desc("Disable use of DFA during scheduling"));
39*9880d681SAndroid Build Coastguard Worker 
40*9880d681SAndroid Build Coastguard Worker static cl::opt<int> RegPressureThreshold(
41*9880d681SAndroid Build Coastguard Worker   "dfa-sched-reg-pressure-threshold", cl::Hidden, cl::ZeroOrMore, cl::init(5),
42*9880d681SAndroid Build Coastguard Worker   cl::desc("Track reg pressure and switch priority to in-depth"));
43*9880d681SAndroid Build Coastguard Worker 
ResourcePriorityQueue(SelectionDAGISel * IS)44*9880d681SAndroid Build Coastguard Worker ResourcePriorityQueue::ResourcePriorityQueue(SelectionDAGISel *IS)
45*9880d681SAndroid Build Coastguard Worker     : Picker(this), InstrItins(IS->MF->getSubtarget().getInstrItineraryData()) {
46*9880d681SAndroid Build Coastguard Worker   const TargetSubtargetInfo &STI = IS->MF->getSubtarget();
47*9880d681SAndroid Build Coastguard Worker   TRI = STI.getRegisterInfo();
48*9880d681SAndroid Build Coastguard Worker   TLI = IS->TLI;
49*9880d681SAndroid Build Coastguard Worker   TII = STI.getInstrInfo();
50*9880d681SAndroid Build Coastguard Worker   ResourcesModel.reset(TII->CreateTargetScheduleState(STI));
51*9880d681SAndroid Build Coastguard Worker   // This hard requirement could be relaxed, but for now
52*9880d681SAndroid Build Coastguard Worker   // do not let it proceed.
53*9880d681SAndroid Build Coastguard Worker   assert(ResourcesModel && "Unimplemented CreateTargetScheduleState.");
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   unsigned NumRC = TRI->getNumRegClasses();
56*9880d681SAndroid Build Coastguard Worker   RegLimit.resize(NumRC);
57*9880d681SAndroid Build Coastguard Worker   RegPressure.resize(NumRC);
58*9880d681SAndroid Build Coastguard Worker   std::fill(RegLimit.begin(), RegLimit.end(), 0);
59*9880d681SAndroid Build Coastguard Worker   std::fill(RegPressure.begin(), RegPressure.end(), 0);
60*9880d681SAndroid Build Coastguard Worker   for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
61*9880d681SAndroid Build Coastguard Worker                                              E = TRI->regclass_end();
62*9880d681SAndroid Build Coastguard Worker        I != E; ++I)
63*9880d681SAndroid Build Coastguard Worker     RegLimit[(*I)->getID()] = TRI->getRegPressureLimit(*I, *IS->MF);
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   ParallelLiveRanges = 0;
66*9880d681SAndroid Build Coastguard Worker   HorizontalVerticalBalance = 0;
67*9880d681SAndroid Build Coastguard Worker }
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker unsigned
numberRCValPredInSU(SUnit * SU,unsigned RCId)70*9880d681SAndroid Build Coastguard Worker ResourcePriorityQueue::numberRCValPredInSU(SUnit *SU, unsigned RCId) {
71*9880d681SAndroid Build Coastguard Worker   unsigned NumberDeps = 0;
72*9880d681SAndroid Build Coastguard Worker   for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
73*9880d681SAndroid Build Coastguard Worker        I != E; ++I) {
74*9880d681SAndroid Build Coastguard Worker     if (I->isCtrl())
75*9880d681SAndroid Build Coastguard Worker       continue;
76*9880d681SAndroid Build Coastguard Worker 
77*9880d681SAndroid Build Coastguard Worker     SUnit *PredSU = I->getSUnit();
78*9880d681SAndroid Build Coastguard Worker     const SDNode *ScegN = PredSU->getNode();
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker     if (!ScegN)
81*9880d681SAndroid Build Coastguard Worker       continue;
82*9880d681SAndroid Build Coastguard Worker 
83*9880d681SAndroid Build Coastguard Worker     // If value is passed to CopyToReg, it is probably
84*9880d681SAndroid Build Coastguard Worker     // live outside BB.
85*9880d681SAndroid Build Coastguard Worker     switch (ScegN->getOpcode()) {
86*9880d681SAndroid Build Coastguard Worker       default:  break;
87*9880d681SAndroid Build Coastguard Worker       case ISD::TokenFactor:    break;
88*9880d681SAndroid Build Coastguard Worker       case ISD::CopyFromReg:    NumberDeps++;  break;
89*9880d681SAndroid Build Coastguard Worker       case ISD::CopyToReg:      break;
90*9880d681SAndroid Build Coastguard Worker       case ISD::INLINEASM:      break;
91*9880d681SAndroid Build Coastguard Worker     }
92*9880d681SAndroid Build Coastguard Worker     if (!ScegN->isMachineOpcode())
93*9880d681SAndroid Build Coastguard Worker       continue;
94*9880d681SAndroid Build Coastguard Worker 
95*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = ScegN->getNumValues(); i != e; ++i) {
96*9880d681SAndroid Build Coastguard Worker       MVT VT = ScegN->getSimpleValueType(i);
97*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT)
98*9880d681SAndroid Build Coastguard Worker           && (TLI->getRegClassFor(VT)->getID() == RCId)) {
99*9880d681SAndroid Build Coastguard Worker         NumberDeps++;
100*9880d681SAndroid Build Coastguard Worker         break;
101*9880d681SAndroid Build Coastguard Worker       }
102*9880d681SAndroid Build Coastguard Worker     }
103*9880d681SAndroid Build Coastguard Worker   }
104*9880d681SAndroid Build Coastguard Worker   return NumberDeps;
105*9880d681SAndroid Build Coastguard Worker }
106*9880d681SAndroid Build Coastguard Worker 
numberRCValSuccInSU(SUnit * SU,unsigned RCId)107*9880d681SAndroid Build Coastguard Worker unsigned ResourcePriorityQueue::numberRCValSuccInSU(SUnit *SU,
108*9880d681SAndroid Build Coastguard Worker                                                     unsigned RCId) {
109*9880d681SAndroid Build Coastguard Worker   unsigned NumberDeps = 0;
110*9880d681SAndroid Build Coastguard Worker   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
111*9880d681SAndroid Build Coastguard Worker        I != E; ++I) {
112*9880d681SAndroid Build Coastguard Worker     if (I->isCtrl())
113*9880d681SAndroid Build Coastguard Worker       continue;
114*9880d681SAndroid Build Coastguard Worker 
115*9880d681SAndroid Build Coastguard Worker     SUnit *SuccSU = I->getSUnit();
116*9880d681SAndroid Build Coastguard Worker     const SDNode *ScegN = SuccSU->getNode();
117*9880d681SAndroid Build Coastguard Worker     if (!ScegN)
118*9880d681SAndroid Build Coastguard Worker       continue;
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker     // If value is passed to CopyToReg, it is probably
121*9880d681SAndroid Build Coastguard Worker     // live outside BB.
122*9880d681SAndroid Build Coastguard Worker     switch (ScegN->getOpcode()) {
123*9880d681SAndroid Build Coastguard Worker       default:  break;
124*9880d681SAndroid Build Coastguard Worker       case ISD::TokenFactor:    break;
125*9880d681SAndroid Build Coastguard Worker       case ISD::CopyFromReg:    break;
126*9880d681SAndroid Build Coastguard Worker       case ISD::CopyToReg:      NumberDeps++;  break;
127*9880d681SAndroid Build Coastguard Worker       case ISD::INLINEASM:      break;
128*9880d681SAndroid Build Coastguard Worker     }
129*9880d681SAndroid Build Coastguard Worker     if (!ScegN->isMachineOpcode())
130*9880d681SAndroid Build Coastguard Worker       continue;
131*9880d681SAndroid Build Coastguard Worker 
132*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = ScegN->getNumOperands(); i != e; ++i) {
133*9880d681SAndroid Build Coastguard Worker       const SDValue &Op = ScegN->getOperand(i);
134*9880d681SAndroid Build Coastguard Worker       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
135*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT)
136*9880d681SAndroid Build Coastguard Worker           && (TLI->getRegClassFor(VT)->getID() == RCId)) {
137*9880d681SAndroid Build Coastguard Worker         NumberDeps++;
138*9880d681SAndroid Build Coastguard Worker         break;
139*9880d681SAndroid Build Coastguard Worker       }
140*9880d681SAndroid Build Coastguard Worker     }
141*9880d681SAndroid Build Coastguard Worker   }
142*9880d681SAndroid Build Coastguard Worker   return NumberDeps;
143*9880d681SAndroid Build Coastguard Worker }
144*9880d681SAndroid Build Coastguard Worker 
numberCtrlDepsInSU(SUnit * SU)145*9880d681SAndroid Build Coastguard Worker static unsigned numberCtrlDepsInSU(SUnit *SU) {
146*9880d681SAndroid Build Coastguard Worker   unsigned NumberDeps = 0;
147*9880d681SAndroid Build Coastguard Worker   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
148*9880d681SAndroid Build Coastguard Worker        I != E; ++I)
149*9880d681SAndroid Build Coastguard Worker     if (I->isCtrl())
150*9880d681SAndroid Build Coastguard Worker       NumberDeps++;
151*9880d681SAndroid Build Coastguard Worker 
152*9880d681SAndroid Build Coastguard Worker   return NumberDeps;
153*9880d681SAndroid Build Coastguard Worker }
154*9880d681SAndroid Build Coastguard Worker 
numberCtrlPredInSU(SUnit * SU)155*9880d681SAndroid Build Coastguard Worker static unsigned numberCtrlPredInSU(SUnit *SU) {
156*9880d681SAndroid Build Coastguard Worker   unsigned NumberDeps = 0;
157*9880d681SAndroid Build Coastguard Worker   for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
158*9880d681SAndroid Build Coastguard Worker        I != E; ++I)
159*9880d681SAndroid Build Coastguard Worker     if (I->isCtrl())
160*9880d681SAndroid Build Coastguard Worker       NumberDeps++;
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker   return NumberDeps;
163*9880d681SAndroid Build Coastguard Worker }
164*9880d681SAndroid Build Coastguard Worker 
165*9880d681SAndroid Build Coastguard Worker ///
166*9880d681SAndroid Build Coastguard Worker /// Initialize nodes.
167*9880d681SAndroid Build Coastguard Worker ///
initNodes(std::vector<SUnit> & sunits)168*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::initNodes(std::vector<SUnit> &sunits) {
169*9880d681SAndroid Build Coastguard Worker   SUnits = &sunits;
170*9880d681SAndroid Build Coastguard Worker   NumNodesSolelyBlocking.resize(SUnits->size(), 0);
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = SUnits->size(); i != e; ++i) {
173*9880d681SAndroid Build Coastguard Worker     SUnit *SU = &(*SUnits)[i];
174*9880d681SAndroid Build Coastguard Worker     initNumRegDefsLeft(SU);
175*9880d681SAndroid Build Coastguard Worker     SU->NodeQueueId = 0;
176*9880d681SAndroid Build Coastguard Worker   }
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker /// This heuristic is used if DFA scheduling is not desired
180*9880d681SAndroid Build Coastguard Worker /// for some VLIW platform.
operator ()(const SUnit * LHS,const SUnit * RHS) const181*9880d681SAndroid Build Coastguard Worker bool resource_sort::operator()(const SUnit *LHS, const SUnit *RHS) const {
182*9880d681SAndroid Build Coastguard Worker   // The isScheduleHigh flag allows nodes with wraparound dependencies that
183*9880d681SAndroid Build Coastguard Worker   // cannot easily be modeled as edges with latencies to be scheduled as
184*9880d681SAndroid Build Coastguard Worker   // soon as possible in a top-down schedule.
185*9880d681SAndroid Build Coastguard Worker   if (LHS->isScheduleHigh && !RHS->isScheduleHigh)
186*9880d681SAndroid Build Coastguard Worker     return false;
187*9880d681SAndroid Build Coastguard Worker 
188*9880d681SAndroid Build Coastguard Worker   if (!LHS->isScheduleHigh && RHS->isScheduleHigh)
189*9880d681SAndroid Build Coastguard Worker     return true;
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker   unsigned LHSNum = LHS->NodeNum;
192*9880d681SAndroid Build Coastguard Worker   unsigned RHSNum = RHS->NodeNum;
193*9880d681SAndroid Build Coastguard Worker 
194*9880d681SAndroid Build Coastguard Worker   // The most important heuristic is scheduling the critical path.
195*9880d681SAndroid Build Coastguard Worker   unsigned LHSLatency = PQ->getLatency(LHSNum);
196*9880d681SAndroid Build Coastguard Worker   unsigned RHSLatency = PQ->getLatency(RHSNum);
197*9880d681SAndroid Build Coastguard Worker   if (LHSLatency < RHSLatency) return true;
198*9880d681SAndroid Build Coastguard Worker   if (LHSLatency > RHSLatency) return false;
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker   // After that, if two nodes have identical latencies, look to see if one will
201*9880d681SAndroid Build Coastguard Worker   // unblock more other nodes than the other.
202*9880d681SAndroid Build Coastguard Worker   unsigned LHSBlocked = PQ->getNumSolelyBlockNodes(LHSNum);
203*9880d681SAndroid Build Coastguard Worker   unsigned RHSBlocked = PQ->getNumSolelyBlockNodes(RHSNum);
204*9880d681SAndroid Build Coastguard Worker   if (LHSBlocked < RHSBlocked) return true;
205*9880d681SAndroid Build Coastguard Worker   if (LHSBlocked > RHSBlocked) return false;
206*9880d681SAndroid Build Coastguard Worker 
207*9880d681SAndroid Build Coastguard Worker   // Finally, just to provide a stable ordering, use the node number as a
208*9880d681SAndroid Build Coastguard Worker   // deciding factor.
209*9880d681SAndroid Build Coastguard Worker   return LHSNum < RHSNum;
210*9880d681SAndroid Build Coastguard Worker }
211*9880d681SAndroid Build Coastguard Worker 
212*9880d681SAndroid Build Coastguard Worker 
213*9880d681SAndroid Build Coastguard Worker /// getSingleUnscheduledPred - If there is exactly one unscheduled predecessor
214*9880d681SAndroid Build Coastguard Worker /// of SU, return it, otherwise return null.
getSingleUnscheduledPred(SUnit * SU)215*9880d681SAndroid Build Coastguard Worker SUnit *ResourcePriorityQueue::getSingleUnscheduledPred(SUnit *SU) {
216*9880d681SAndroid Build Coastguard Worker   SUnit *OnlyAvailablePred = nullptr;
217*9880d681SAndroid Build Coastguard Worker   for (SUnit::const_pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
218*9880d681SAndroid Build Coastguard Worker        I != E; ++I) {
219*9880d681SAndroid Build Coastguard Worker     SUnit &Pred = *I->getSUnit();
220*9880d681SAndroid Build Coastguard Worker     if (!Pred.isScheduled) {
221*9880d681SAndroid Build Coastguard Worker       // We found an available, but not scheduled, predecessor.  If it's the
222*9880d681SAndroid Build Coastguard Worker       // only one we have found, keep track of it... otherwise give up.
223*9880d681SAndroid Build Coastguard Worker       if (OnlyAvailablePred && OnlyAvailablePred != &Pred)
224*9880d681SAndroid Build Coastguard Worker         return nullptr;
225*9880d681SAndroid Build Coastguard Worker       OnlyAvailablePred = &Pred;
226*9880d681SAndroid Build Coastguard Worker     }
227*9880d681SAndroid Build Coastguard Worker   }
228*9880d681SAndroid Build Coastguard Worker   return OnlyAvailablePred;
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker 
push(SUnit * SU)231*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::push(SUnit *SU) {
232*9880d681SAndroid Build Coastguard Worker   // Look at all of the successors of this node.  Count the number of nodes that
233*9880d681SAndroid Build Coastguard Worker   // this node is the sole unscheduled node for.
234*9880d681SAndroid Build Coastguard Worker   unsigned NumNodesBlocking = 0;
235*9880d681SAndroid Build Coastguard Worker   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
236*9880d681SAndroid Build Coastguard Worker        I != E; ++I)
237*9880d681SAndroid Build Coastguard Worker     if (getSingleUnscheduledPred(I->getSUnit()) == SU)
238*9880d681SAndroid Build Coastguard Worker       ++NumNodesBlocking;
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker   NumNodesSolelyBlocking[SU->NodeNum] = NumNodesBlocking;
241*9880d681SAndroid Build Coastguard Worker   Queue.push_back(SU);
242*9880d681SAndroid Build Coastguard Worker }
243*9880d681SAndroid Build Coastguard Worker 
244*9880d681SAndroid Build Coastguard Worker /// Check if scheduling of this SU is possible
245*9880d681SAndroid Build Coastguard Worker /// in the current packet.
isResourceAvailable(SUnit * SU)246*9880d681SAndroid Build Coastguard Worker bool ResourcePriorityQueue::isResourceAvailable(SUnit *SU) {
247*9880d681SAndroid Build Coastguard Worker   if (!SU || !SU->getNode())
248*9880d681SAndroid Build Coastguard Worker     return false;
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker   // If this is a compound instruction,
251*9880d681SAndroid Build Coastguard Worker   // it is likely to be a call. Do not delay it.
252*9880d681SAndroid Build Coastguard Worker   if (SU->getNode()->getGluedNode())
253*9880d681SAndroid Build Coastguard Worker     return true;
254*9880d681SAndroid Build Coastguard Worker 
255*9880d681SAndroid Build Coastguard Worker   // First see if the pipeline could receive this instruction
256*9880d681SAndroid Build Coastguard Worker   // in the current cycle.
257*9880d681SAndroid Build Coastguard Worker   if (SU->getNode()->isMachineOpcode())
258*9880d681SAndroid Build Coastguard Worker     switch (SU->getNode()->getMachineOpcode()) {
259*9880d681SAndroid Build Coastguard Worker     default:
260*9880d681SAndroid Build Coastguard Worker       if (!ResourcesModel->canReserveResources(&TII->get(
261*9880d681SAndroid Build Coastguard Worker           SU->getNode()->getMachineOpcode())))
262*9880d681SAndroid Build Coastguard Worker            return false;
263*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::EXTRACT_SUBREG:
264*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::INSERT_SUBREG:
265*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::SUBREG_TO_REG:
266*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::REG_SEQUENCE:
267*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::IMPLICIT_DEF:
268*9880d681SAndroid Build Coastguard Worker         break;
269*9880d681SAndroid Build Coastguard Worker     }
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   // Now see if there are no other dependencies
272*9880d681SAndroid Build Coastguard Worker   // to instructions already in the packet.
273*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = Packet.size(); i != e; ++i)
274*9880d681SAndroid Build Coastguard Worker     for (SUnit::const_succ_iterator I = Packet[i]->Succs.begin(),
275*9880d681SAndroid Build Coastguard Worker          E = Packet[i]->Succs.end(); I != E; ++I) {
276*9880d681SAndroid Build Coastguard Worker       // Since we do not add pseudos to packets, might as well
277*9880d681SAndroid Build Coastguard Worker       // ignore order deps.
278*9880d681SAndroid Build Coastguard Worker       if (I->isCtrl())
279*9880d681SAndroid Build Coastguard Worker         continue;
280*9880d681SAndroid Build Coastguard Worker 
281*9880d681SAndroid Build Coastguard Worker       if (I->getSUnit() == SU)
282*9880d681SAndroid Build Coastguard Worker         return false;
283*9880d681SAndroid Build Coastguard Worker     }
284*9880d681SAndroid Build Coastguard Worker 
285*9880d681SAndroid Build Coastguard Worker   return true;
286*9880d681SAndroid Build Coastguard Worker }
287*9880d681SAndroid Build Coastguard Worker 
288*9880d681SAndroid Build Coastguard Worker /// Keep track of available resources.
reserveResources(SUnit * SU)289*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::reserveResources(SUnit *SU) {
290*9880d681SAndroid Build Coastguard Worker   // If this SU does not fit in the packet
291*9880d681SAndroid Build Coastguard Worker   // start a new one.
292*9880d681SAndroid Build Coastguard Worker   if (!isResourceAvailable(SU) || SU->getNode()->getGluedNode()) {
293*9880d681SAndroid Build Coastguard Worker     ResourcesModel->clearResources();
294*9880d681SAndroid Build Coastguard Worker     Packet.clear();
295*9880d681SAndroid Build Coastguard Worker   }
296*9880d681SAndroid Build Coastguard Worker 
297*9880d681SAndroid Build Coastguard Worker   if (SU->getNode() && SU->getNode()->isMachineOpcode()) {
298*9880d681SAndroid Build Coastguard Worker     switch (SU->getNode()->getMachineOpcode()) {
299*9880d681SAndroid Build Coastguard Worker     default:
300*9880d681SAndroid Build Coastguard Worker       ResourcesModel->reserveResources(&TII->get(
301*9880d681SAndroid Build Coastguard Worker         SU->getNode()->getMachineOpcode()));
302*9880d681SAndroid Build Coastguard Worker       break;
303*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::EXTRACT_SUBREG:
304*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::INSERT_SUBREG:
305*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::SUBREG_TO_REG:
306*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::REG_SEQUENCE:
307*9880d681SAndroid Build Coastguard Worker     case TargetOpcode::IMPLICIT_DEF:
308*9880d681SAndroid Build Coastguard Worker       break;
309*9880d681SAndroid Build Coastguard Worker     }
310*9880d681SAndroid Build Coastguard Worker     Packet.push_back(SU);
311*9880d681SAndroid Build Coastguard Worker   }
312*9880d681SAndroid Build Coastguard Worker   // Forcefully end packet for PseudoOps.
313*9880d681SAndroid Build Coastguard Worker   else {
314*9880d681SAndroid Build Coastguard Worker     ResourcesModel->clearResources();
315*9880d681SAndroid Build Coastguard Worker     Packet.clear();
316*9880d681SAndroid Build Coastguard Worker   }
317*9880d681SAndroid Build Coastguard Worker 
318*9880d681SAndroid Build Coastguard Worker   // If packet is now full, reset the state so in the next cycle
319*9880d681SAndroid Build Coastguard Worker   // we start fresh.
320*9880d681SAndroid Build Coastguard Worker   if (Packet.size() >= InstrItins->SchedModel.IssueWidth) {
321*9880d681SAndroid Build Coastguard Worker     ResourcesModel->clearResources();
322*9880d681SAndroid Build Coastguard Worker     Packet.clear();
323*9880d681SAndroid Build Coastguard Worker   }
324*9880d681SAndroid Build Coastguard Worker }
325*9880d681SAndroid Build Coastguard Worker 
rawRegPressureDelta(SUnit * SU,unsigned RCId)326*9880d681SAndroid Build Coastguard Worker int ResourcePriorityQueue::rawRegPressureDelta(SUnit *SU, unsigned RCId) {
327*9880d681SAndroid Build Coastguard Worker   int RegBalance = 0;
328*9880d681SAndroid Build Coastguard Worker 
329*9880d681SAndroid Build Coastguard Worker   if (!SU || !SU->getNode() || !SU->getNode()->isMachineOpcode())
330*9880d681SAndroid Build Coastguard Worker     return RegBalance;
331*9880d681SAndroid Build Coastguard Worker 
332*9880d681SAndroid Build Coastguard Worker   // Gen estimate.
333*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = SU->getNode()->getNumValues(); i != e; ++i) {
334*9880d681SAndroid Build Coastguard Worker       MVT VT = SU->getNode()->getSimpleValueType(i);
335*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT)
336*9880d681SAndroid Build Coastguard Worker           && TLI->getRegClassFor(VT)
337*9880d681SAndroid Build Coastguard Worker           && TLI->getRegClassFor(VT)->getID() == RCId)
338*9880d681SAndroid Build Coastguard Worker         RegBalance += numberRCValSuccInSU(SU, RCId);
339*9880d681SAndroid Build Coastguard Worker   }
340*9880d681SAndroid Build Coastguard Worker   // Kill estimate.
341*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0, e = SU->getNode()->getNumOperands(); i != e; ++i) {
342*9880d681SAndroid Build Coastguard Worker       const SDValue &Op = SU->getNode()->getOperand(i);
343*9880d681SAndroid Build Coastguard Worker       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
344*9880d681SAndroid Build Coastguard Worker       if (isa<ConstantSDNode>(Op.getNode()))
345*9880d681SAndroid Build Coastguard Worker         continue;
346*9880d681SAndroid Build Coastguard Worker 
347*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT) && TLI->getRegClassFor(VT)
348*9880d681SAndroid Build Coastguard Worker           && TLI->getRegClassFor(VT)->getID() == RCId)
349*9880d681SAndroid Build Coastguard Worker         RegBalance -= numberRCValPredInSU(SU, RCId);
350*9880d681SAndroid Build Coastguard Worker   }
351*9880d681SAndroid Build Coastguard Worker   return RegBalance;
352*9880d681SAndroid Build Coastguard Worker }
353*9880d681SAndroid Build Coastguard Worker 
354*9880d681SAndroid Build Coastguard Worker /// Estimates change in reg pressure from this SU.
355*9880d681SAndroid Build Coastguard Worker /// It is achieved by trivial tracking of defined
356*9880d681SAndroid Build Coastguard Worker /// and used vregs in dependent instructions.
357*9880d681SAndroid Build Coastguard Worker /// The RawPressure flag makes this function to ignore
358*9880d681SAndroid Build Coastguard Worker /// existing reg file sizes, and report raw def/use
359*9880d681SAndroid Build Coastguard Worker /// balance.
regPressureDelta(SUnit * SU,bool RawPressure)360*9880d681SAndroid Build Coastguard Worker int ResourcePriorityQueue::regPressureDelta(SUnit *SU, bool RawPressure) {
361*9880d681SAndroid Build Coastguard Worker   int RegBalance = 0;
362*9880d681SAndroid Build Coastguard Worker 
363*9880d681SAndroid Build Coastguard Worker   if (!SU || !SU->getNode() || !SU->getNode()->isMachineOpcode())
364*9880d681SAndroid Build Coastguard Worker     return RegBalance;
365*9880d681SAndroid Build Coastguard Worker 
366*9880d681SAndroid Build Coastguard Worker   if (RawPressure) {
367*9880d681SAndroid Build Coastguard Worker     for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
368*9880d681SAndroid Build Coastguard Worker              E = TRI->regclass_end(); I != E; ++I) {
369*9880d681SAndroid Build Coastguard Worker       const TargetRegisterClass *RC = *I;
370*9880d681SAndroid Build Coastguard Worker       RegBalance += rawRegPressureDelta(SU, RC->getID());
371*9880d681SAndroid Build Coastguard Worker     }
372*9880d681SAndroid Build Coastguard Worker   }
373*9880d681SAndroid Build Coastguard Worker   else {
374*9880d681SAndroid Build Coastguard Worker     for (TargetRegisterInfo::regclass_iterator I = TRI->regclass_begin(),
375*9880d681SAndroid Build Coastguard Worker          E = TRI->regclass_end(); I != E; ++I) {
376*9880d681SAndroid Build Coastguard Worker       const TargetRegisterClass *RC = *I;
377*9880d681SAndroid Build Coastguard Worker       if ((RegPressure[RC->getID()] +
378*9880d681SAndroid Build Coastguard Worker            rawRegPressureDelta(SU, RC->getID()) > 0) &&
379*9880d681SAndroid Build Coastguard Worker           (RegPressure[RC->getID()] +
380*9880d681SAndroid Build Coastguard Worker            rawRegPressureDelta(SU, RC->getID())  >= RegLimit[RC->getID()]))
381*9880d681SAndroid Build Coastguard Worker         RegBalance += rawRegPressureDelta(SU, RC->getID());
382*9880d681SAndroid Build Coastguard Worker     }
383*9880d681SAndroid Build Coastguard Worker   }
384*9880d681SAndroid Build Coastguard Worker 
385*9880d681SAndroid Build Coastguard Worker   return RegBalance;
386*9880d681SAndroid Build Coastguard Worker }
387*9880d681SAndroid Build Coastguard Worker 
388*9880d681SAndroid Build Coastguard Worker // Constants used to denote relative importance of
389*9880d681SAndroid Build Coastguard Worker // heuristic components for cost computation.
390*9880d681SAndroid Build Coastguard Worker static const unsigned PriorityOne = 200;
391*9880d681SAndroid Build Coastguard Worker static const unsigned PriorityTwo = 50;
392*9880d681SAndroid Build Coastguard Worker static const unsigned PriorityThree = 15;
393*9880d681SAndroid Build Coastguard Worker static const unsigned PriorityFour = 5;
394*9880d681SAndroid Build Coastguard Worker static const unsigned ScaleOne = 20;
395*9880d681SAndroid Build Coastguard Worker static const unsigned ScaleTwo = 10;
396*9880d681SAndroid Build Coastguard Worker static const unsigned ScaleThree = 5;
397*9880d681SAndroid Build Coastguard Worker static const unsigned FactorOne = 2;
398*9880d681SAndroid Build Coastguard Worker 
399*9880d681SAndroid Build Coastguard Worker /// Returns single number reflecting benefit of scheduling SU
400*9880d681SAndroid Build Coastguard Worker /// in the current cycle.
SUSchedulingCost(SUnit * SU)401*9880d681SAndroid Build Coastguard Worker int ResourcePriorityQueue::SUSchedulingCost(SUnit *SU) {
402*9880d681SAndroid Build Coastguard Worker   // Initial trivial priority.
403*9880d681SAndroid Build Coastguard Worker   int ResCount = 1;
404*9880d681SAndroid Build Coastguard Worker 
405*9880d681SAndroid Build Coastguard Worker   // Do not waste time on a node that is already scheduled.
406*9880d681SAndroid Build Coastguard Worker   if (SU->isScheduled)
407*9880d681SAndroid Build Coastguard Worker     return ResCount;
408*9880d681SAndroid Build Coastguard Worker 
409*9880d681SAndroid Build Coastguard Worker   // Forced priority is high.
410*9880d681SAndroid Build Coastguard Worker   if (SU->isScheduleHigh)
411*9880d681SAndroid Build Coastguard Worker     ResCount += PriorityOne;
412*9880d681SAndroid Build Coastguard Worker 
413*9880d681SAndroid Build Coastguard Worker   // Adaptable scheduling
414*9880d681SAndroid Build Coastguard Worker   // A small, but very parallel
415*9880d681SAndroid Build Coastguard Worker   // region, where reg pressure is an issue.
416*9880d681SAndroid Build Coastguard Worker   if (HorizontalVerticalBalance > RegPressureThreshold) {
417*9880d681SAndroid Build Coastguard Worker     // Critical path first
418*9880d681SAndroid Build Coastguard Worker     ResCount += (SU->getHeight() * ScaleTwo);
419*9880d681SAndroid Build Coastguard Worker     // If resources are available for it, multiply the
420*9880d681SAndroid Build Coastguard Worker     // chance of scheduling.
421*9880d681SAndroid Build Coastguard Worker     if (isResourceAvailable(SU))
422*9880d681SAndroid Build Coastguard Worker       ResCount <<= FactorOne;
423*9880d681SAndroid Build Coastguard Worker 
424*9880d681SAndroid Build Coastguard Worker     // Consider change to reg pressure from scheduling
425*9880d681SAndroid Build Coastguard Worker     // this SU.
426*9880d681SAndroid Build Coastguard Worker     ResCount -= (regPressureDelta(SU,true) * ScaleOne);
427*9880d681SAndroid Build Coastguard Worker   }
428*9880d681SAndroid Build Coastguard Worker   // Default heuristic, greeady and
429*9880d681SAndroid Build Coastguard Worker   // critical path driven.
430*9880d681SAndroid Build Coastguard Worker   else {
431*9880d681SAndroid Build Coastguard Worker     // Critical path first.
432*9880d681SAndroid Build Coastguard Worker     ResCount += (SU->getHeight() * ScaleTwo);
433*9880d681SAndroid Build Coastguard Worker     // Now see how many instructions is blocked by this SU.
434*9880d681SAndroid Build Coastguard Worker     ResCount += (NumNodesSolelyBlocking[SU->NodeNum] * ScaleTwo);
435*9880d681SAndroid Build Coastguard Worker     // If resources are available for it, multiply the
436*9880d681SAndroid Build Coastguard Worker     // chance of scheduling.
437*9880d681SAndroid Build Coastguard Worker     if (isResourceAvailable(SU))
438*9880d681SAndroid Build Coastguard Worker       ResCount <<= FactorOne;
439*9880d681SAndroid Build Coastguard Worker 
440*9880d681SAndroid Build Coastguard Worker     ResCount -= (regPressureDelta(SU) * ScaleTwo);
441*9880d681SAndroid Build Coastguard Worker   }
442*9880d681SAndroid Build Coastguard Worker 
443*9880d681SAndroid Build Coastguard Worker   // These are platform-specific things.
444*9880d681SAndroid Build Coastguard Worker   // Will need to go into the back end
445*9880d681SAndroid Build Coastguard Worker   // and accessed from here via a hook.
446*9880d681SAndroid Build Coastguard Worker   for (SDNode *N = SU->getNode(); N; N = N->getGluedNode()) {
447*9880d681SAndroid Build Coastguard Worker     if (N->isMachineOpcode()) {
448*9880d681SAndroid Build Coastguard Worker       const MCInstrDesc &TID = TII->get(N->getMachineOpcode());
449*9880d681SAndroid Build Coastguard Worker       if (TID.isCall())
450*9880d681SAndroid Build Coastguard Worker         ResCount += (PriorityTwo + (ScaleThree*N->getNumValues()));
451*9880d681SAndroid Build Coastguard Worker     }
452*9880d681SAndroid Build Coastguard Worker     else
453*9880d681SAndroid Build Coastguard Worker       switch (N->getOpcode()) {
454*9880d681SAndroid Build Coastguard Worker       default:  break;
455*9880d681SAndroid Build Coastguard Worker       case ISD::TokenFactor:
456*9880d681SAndroid Build Coastguard Worker       case ISD::CopyFromReg:
457*9880d681SAndroid Build Coastguard Worker       case ISD::CopyToReg:
458*9880d681SAndroid Build Coastguard Worker         ResCount += PriorityFour;
459*9880d681SAndroid Build Coastguard Worker         break;
460*9880d681SAndroid Build Coastguard Worker 
461*9880d681SAndroid Build Coastguard Worker       case ISD::INLINEASM:
462*9880d681SAndroid Build Coastguard Worker         ResCount += PriorityThree;
463*9880d681SAndroid Build Coastguard Worker         break;
464*9880d681SAndroid Build Coastguard Worker       }
465*9880d681SAndroid Build Coastguard Worker   }
466*9880d681SAndroid Build Coastguard Worker   return ResCount;
467*9880d681SAndroid Build Coastguard Worker }
468*9880d681SAndroid Build Coastguard Worker 
469*9880d681SAndroid Build Coastguard Worker 
470*9880d681SAndroid Build Coastguard Worker /// Main resource tracking point.
scheduledNode(SUnit * SU)471*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::scheduledNode(SUnit *SU) {
472*9880d681SAndroid Build Coastguard Worker   // Use NULL entry as an event marker to reset
473*9880d681SAndroid Build Coastguard Worker   // the DFA state.
474*9880d681SAndroid Build Coastguard Worker   if (!SU) {
475*9880d681SAndroid Build Coastguard Worker     ResourcesModel->clearResources();
476*9880d681SAndroid Build Coastguard Worker     Packet.clear();
477*9880d681SAndroid Build Coastguard Worker     return;
478*9880d681SAndroid Build Coastguard Worker   }
479*9880d681SAndroid Build Coastguard Worker 
480*9880d681SAndroid Build Coastguard Worker   const SDNode *ScegN = SU->getNode();
481*9880d681SAndroid Build Coastguard Worker   // Update reg pressure tracking.
482*9880d681SAndroid Build Coastguard Worker   // First update current node.
483*9880d681SAndroid Build Coastguard Worker   if (ScegN->isMachineOpcode()) {
484*9880d681SAndroid Build Coastguard Worker     // Estimate generated regs.
485*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = ScegN->getNumValues(); i != e; ++i) {
486*9880d681SAndroid Build Coastguard Worker       MVT VT = ScegN->getSimpleValueType(i);
487*9880d681SAndroid Build Coastguard Worker 
488*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT)) {
489*9880d681SAndroid Build Coastguard Worker         const TargetRegisterClass *RC = TLI->getRegClassFor(VT);
490*9880d681SAndroid Build Coastguard Worker         if (RC)
491*9880d681SAndroid Build Coastguard Worker           RegPressure[RC->getID()] += numberRCValSuccInSU(SU, RC->getID());
492*9880d681SAndroid Build Coastguard Worker       }
493*9880d681SAndroid Build Coastguard Worker     }
494*9880d681SAndroid Build Coastguard Worker     // Estimate killed regs.
495*9880d681SAndroid Build Coastguard Worker     for (unsigned i = 0, e = ScegN->getNumOperands(); i != e; ++i) {
496*9880d681SAndroid Build Coastguard Worker       const SDValue &Op = ScegN->getOperand(i);
497*9880d681SAndroid Build Coastguard Worker       MVT VT = Op.getNode()->getSimpleValueType(Op.getResNo());
498*9880d681SAndroid Build Coastguard Worker 
499*9880d681SAndroid Build Coastguard Worker       if (TLI->isTypeLegal(VT)) {
500*9880d681SAndroid Build Coastguard Worker         const TargetRegisterClass *RC = TLI->getRegClassFor(VT);
501*9880d681SAndroid Build Coastguard Worker         if (RC) {
502*9880d681SAndroid Build Coastguard Worker           if (RegPressure[RC->getID()] >
503*9880d681SAndroid Build Coastguard Worker             (numberRCValPredInSU(SU, RC->getID())))
504*9880d681SAndroid Build Coastguard Worker             RegPressure[RC->getID()] -= numberRCValPredInSU(SU, RC->getID());
505*9880d681SAndroid Build Coastguard Worker           else RegPressure[RC->getID()] = 0;
506*9880d681SAndroid Build Coastguard Worker         }
507*9880d681SAndroid Build Coastguard Worker       }
508*9880d681SAndroid Build Coastguard Worker     }
509*9880d681SAndroid Build Coastguard Worker     for (SUnit::pred_iterator I = SU->Preds.begin(), E = SU->Preds.end();
510*9880d681SAndroid Build Coastguard Worker                               I != E; ++I) {
511*9880d681SAndroid Build Coastguard Worker       if (I->isCtrl() || (I->getSUnit()->NumRegDefsLeft == 0))
512*9880d681SAndroid Build Coastguard Worker         continue;
513*9880d681SAndroid Build Coastguard Worker       --I->getSUnit()->NumRegDefsLeft;
514*9880d681SAndroid Build Coastguard Worker     }
515*9880d681SAndroid Build Coastguard Worker   }
516*9880d681SAndroid Build Coastguard Worker 
517*9880d681SAndroid Build Coastguard Worker   // Reserve resources for this SU.
518*9880d681SAndroid Build Coastguard Worker   reserveResources(SU);
519*9880d681SAndroid Build Coastguard Worker 
520*9880d681SAndroid Build Coastguard Worker   // Adjust number of parallel live ranges.
521*9880d681SAndroid Build Coastguard Worker   // Heuristic is simple - node with no data successors reduces
522*9880d681SAndroid Build Coastguard Worker   // number of live ranges. All others, increase it.
523*9880d681SAndroid Build Coastguard Worker   unsigned NumberNonControlDeps = 0;
524*9880d681SAndroid Build Coastguard Worker 
525*9880d681SAndroid Build Coastguard Worker   for (SUnit::const_succ_iterator I = SU->Succs.begin(), E = SU->Succs.end();
526*9880d681SAndroid Build Coastguard Worker                                   I != E; ++I) {
527*9880d681SAndroid Build Coastguard Worker     adjustPriorityOfUnscheduledPreds(I->getSUnit());
528*9880d681SAndroid Build Coastguard Worker     if (!I->isCtrl())
529*9880d681SAndroid Build Coastguard Worker       NumberNonControlDeps++;
530*9880d681SAndroid Build Coastguard Worker   }
531*9880d681SAndroid Build Coastguard Worker 
532*9880d681SAndroid Build Coastguard Worker   if (!NumberNonControlDeps) {
533*9880d681SAndroid Build Coastguard Worker     if (ParallelLiveRanges >= SU->NumPreds)
534*9880d681SAndroid Build Coastguard Worker       ParallelLiveRanges -= SU->NumPreds;
535*9880d681SAndroid Build Coastguard Worker     else
536*9880d681SAndroid Build Coastguard Worker       ParallelLiveRanges = 0;
537*9880d681SAndroid Build Coastguard Worker 
538*9880d681SAndroid Build Coastguard Worker   }
539*9880d681SAndroid Build Coastguard Worker   else
540*9880d681SAndroid Build Coastguard Worker     ParallelLiveRanges += SU->NumRegDefsLeft;
541*9880d681SAndroid Build Coastguard Worker 
542*9880d681SAndroid Build Coastguard Worker   // Track parallel live chains.
543*9880d681SAndroid Build Coastguard Worker   HorizontalVerticalBalance += (SU->Succs.size() - numberCtrlDepsInSU(SU));
544*9880d681SAndroid Build Coastguard Worker   HorizontalVerticalBalance -= (SU->Preds.size() - numberCtrlPredInSU(SU));
545*9880d681SAndroid Build Coastguard Worker }
546*9880d681SAndroid Build Coastguard Worker 
initNumRegDefsLeft(SUnit * SU)547*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::initNumRegDefsLeft(SUnit *SU) {
548*9880d681SAndroid Build Coastguard Worker   unsigned  NodeNumDefs = 0;
549*9880d681SAndroid Build Coastguard Worker   for (SDNode *N = SU->getNode(); N; N = N->getGluedNode())
550*9880d681SAndroid Build Coastguard Worker     if (N->isMachineOpcode()) {
551*9880d681SAndroid Build Coastguard Worker       const MCInstrDesc &TID = TII->get(N->getMachineOpcode());
552*9880d681SAndroid Build Coastguard Worker       // No register need be allocated for this.
553*9880d681SAndroid Build Coastguard Worker       if (N->getMachineOpcode() == TargetOpcode::IMPLICIT_DEF) {
554*9880d681SAndroid Build Coastguard Worker         NodeNumDefs = 0;
555*9880d681SAndroid Build Coastguard Worker         break;
556*9880d681SAndroid Build Coastguard Worker       }
557*9880d681SAndroid Build Coastguard Worker       NodeNumDefs = std::min(N->getNumValues(), TID.getNumDefs());
558*9880d681SAndroid Build Coastguard Worker     }
559*9880d681SAndroid Build Coastguard Worker     else
560*9880d681SAndroid Build Coastguard Worker       switch(N->getOpcode()) {
561*9880d681SAndroid Build Coastguard Worker         default:     break;
562*9880d681SAndroid Build Coastguard Worker         case ISD::CopyFromReg:
563*9880d681SAndroid Build Coastguard Worker           NodeNumDefs++;
564*9880d681SAndroid Build Coastguard Worker           break;
565*9880d681SAndroid Build Coastguard Worker         case ISD::INLINEASM:
566*9880d681SAndroid Build Coastguard Worker           NodeNumDefs++;
567*9880d681SAndroid Build Coastguard Worker           break;
568*9880d681SAndroid Build Coastguard Worker       }
569*9880d681SAndroid Build Coastguard Worker 
570*9880d681SAndroid Build Coastguard Worker   SU->NumRegDefsLeft = NodeNumDefs;
571*9880d681SAndroid Build Coastguard Worker }
572*9880d681SAndroid Build Coastguard Worker 
573*9880d681SAndroid Build Coastguard Worker /// adjustPriorityOfUnscheduledPreds - One of the predecessors of SU was just
574*9880d681SAndroid Build Coastguard Worker /// scheduled.  If SU is not itself available, then there is at least one
575*9880d681SAndroid Build Coastguard Worker /// predecessor node that has not been scheduled yet.  If SU has exactly ONE
576*9880d681SAndroid Build Coastguard Worker /// unscheduled predecessor, we want to increase its priority: it getting
577*9880d681SAndroid Build Coastguard Worker /// scheduled will make this node available, so it is better than some other
578*9880d681SAndroid Build Coastguard Worker /// node of the same priority that will not make a node available.
adjustPriorityOfUnscheduledPreds(SUnit * SU)579*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::adjustPriorityOfUnscheduledPreds(SUnit *SU) {
580*9880d681SAndroid Build Coastguard Worker   if (SU->isAvailable) return;  // All preds scheduled.
581*9880d681SAndroid Build Coastguard Worker 
582*9880d681SAndroid Build Coastguard Worker   SUnit *OnlyAvailablePred = getSingleUnscheduledPred(SU);
583*9880d681SAndroid Build Coastguard Worker   if (!OnlyAvailablePred || !OnlyAvailablePred->isAvailable)
584*9880d681SAndroid Build Coastguard Worker     return;
585*9880d681SAndroid Build Coastguard Worker 
586*9880d681SAndroid Build Coastguard Worker   // Okay, we found a single predecessor that is available, but not scheduled.
587*9880d681SAndroid Build Coastguard Worker   // Since it is available, it must be in the priority queue.  First remove it.
588*9880d681SAndroid Build Coastguard Worker   remove(OnlyAvailablePred);
589*9880d681SAndroid Build Coastguard Worker 
590*9880d681SAndroid Build Coastguard Worker   // Reinsert the node into the priority queue, which recomputes its
591*9880d681SAndroid Build Coastguard Worker   // NumNodesSolelyBlocking value.
592*9880d681SAndroid Build Coastguard Worker   push(OnlyAvailablePred);
593*9880d681SAndroid Build Coastguard Worker }
594*9880d681SAndroid Build Coastguard Worker 
595*9880d681SAndroid Build Coastguard Worker 
596*9880d681SAndroid Build Coastguard Worker /// Main access point - returns next instructions
597*9880d681SAndroid Build Coastguard Worker /// to be placed in scheduling sequence.
pop()598*9880d681SAndroid Build Coastguard Worker SUnit *ResourcePriorityQueue::pop() {
599*9880d681SAndroid Build Coastguard Worker   if (empty())
600*9880d681SAndroid Build Coastguard Worker     return nullptr;
601*9880d681SAndroid Build Coastguard Worker 
602*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit *>::iterator Best = Queue.begin();
603*9880d681SAndroid Build Coastguard Worker   if (!DisableDFASched) {
604*9880d681SAndroid Build Coastguard Worker     int BestCost = SUSchedulingCost(*Best);
605*9880d681SAndroid Build Coastguard Worker     for (std::vector<SUnit *>::iterator I = std::next(Queue.begin()),
606*9880d681SAndroid Build Coastguard Worker            E = Queue.end(); I != E; ++I) {
607*9880d681SAndroid Build Coastguard Worker 
608*9880d681SAndroid Build Coastguard Worker       if (SUSchedulingCost(*I) > BestCost) {
609*9880d681SAndroid Build Coastguard Worker         BestCost = SUSchedulingCost(*I);
610*9880d681SAndroid Build Coastguard Worker         Best = I;
611*9880d681SAndroid Build Coastguard Worker       }
612*9880d681SAndroid Build Coastguard Worker     }
613*9880d681SAndroid Build Coastguard Worker   }
614*9880d681SAndroid Build Coastguard Worker   // Use default TD scheduling mechanism.
615*9880d681SAndroid Build Coastguard Worker   else {
616*9880d681SAndroid Build Coastguard Worker     for (std::vector<SUnit *>::iterator I = std::next(Queue.begin()),
617*9880d681SAndroid Build Coastguard Worker        E = Queue.end(); I != E; ++I)
618*9880d681SAndroid Build Coastguard Worker       if (Picker(*Best, *I))
619*9880d681SAndroid Build Coastguard Worker         Best = I;
620*9880d681SAndroid Build Coastguard Worker   }
621*9880d681SAndroid Build Coastguard Worker 
622*9880d681SAndroid Build Coastguard Worker   SUnit *V = *Best;
623*9880d681SAndroid Build Coastguard Worker   if (Best != std::prev(Queue.end()))
624*9880d681SAndroid Build Coastguard Worker     std::swap(*Best, Queue.back());
625*9880d681SAndroid Build Coastguard Worker 
626*9880d681SAndroid Build Coastguard Worker   Queue.pop_back();
627*9880d681SAndroid Build Coastguard Worker 
628*9880d681SAndroid Build Coastguard Worker   return V;
629*9880d681SAndroid Build Coastguard Worker }
630*9880d681SAndroid Build Coastguard Worker 
631*9880d681SAndroid Build Coastguard Worker 
remove(SUnit * SU)632*9880d681SAndroid Build Coastguard Worker void ResourcePriorityQueue::remove(SUnit *SU) {
633*9880d681SAndroid Build Coastguard Worker   assert(!Queue.empty() && "Queue is empty!");
634*9880d681SAndroid Build Coastguard Worker   std::vector<SUnit *>::iterator I = std::find(Queue.begin(), Queue.end(), SU);
635*9880d681SAndroid Build Coastguard Worker   if (I != std::prev(Queue.end()))
636*9880d681SAndroid Build Coastguard Worker     std::swap(*I, Queue.back());
637*9880d681SAndroid Build Coastguard Worker 
638*9880d681SAndroid Build Coastguard Worker   Queue.pop_back();
639*9880d681SAndroid Build Coastguard Worker }
640