Coverage Report

Created: 2024-01-17 10:31

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