16b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick//===----- ScoreboardHazardRecognizer.cpp - Scheduler Support -------------===//
2d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//
3d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//                     The LLVM Compiler Infrastructure
4d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//
5d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin// This file is distributed under the University of Illinois Open Source
6d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin// License. See LICENSE.TXT for details.
7d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//
8d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//===----------------------------------------------------------------------===//
9d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//
106b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick// This file implements the ScoreboardHazardRecognizer class, which
116b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick// encapsultes hazard-avoidance heuristics for scheduling, based on the
126b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick// scheduling itineraries specified for the target.
13d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//
14d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin//===----------------------------------------------------------------------===//
15d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
162da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
176b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
18774bc882fdb3bbb0558075360c6e5bc510a0bdadEvan Cheng#include "llvm/CodeGen/ScheduleDAG.h"
19ab8be96fd30ca9396e6b84fdddf1ac6208984cadEvan Cheng#include "llvm/MC/MCInstrItineraries.h"
20d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin#include "llvm/Support/Debug.h"
21d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin#include "llvm/Support/ErrorHandling.h"
223a5f0d444cf21e2b90d5eb965bb677c7ce098546David Goodwin#include "llvm/Support/raw_ostream.h"
23c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick#include "llvm/Target/TargetInstrInfo.h"
24d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
25fb98a43b311dec66188b3669a0da017829833617Bill Wendlingusing namespace llvm;
26d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
272da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#ifndef NDEBUG
282da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trickconst char *ScoreboardHazardRecognizer::DebugType = "";
292da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#endif
302da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
316b1207267f01877ff9b351786c902cb2ecd354c0Andrew TrickScoreboardHazardRecognizer::
322da8bc8a5f7705ac131184cd247f48500da0d74eAndrew TrickScoreboardHazardRecognizer(const InstrItineraryData *II,
332da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick                           const ScheduleDAG *SchedDAG,
342da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick                           const char *ParentDebugType) :
352da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
362da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount(0) {
372da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
382da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#ifndef NDEBUG
392da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  DebugType = ParentDebugType;
402da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#endif
412da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
42d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // Determine the maximum depth of any itinerary. This determines the depth of
43d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // the scoreboard. We always make the scoreboard at least 1 cycle deep to
44d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // avoid dealing with the boundary condition.
451298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  unsigned ScoreboardDepth = 1;
463ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (ItinData && !ItinData->isEmpty()) {
47d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    for (unsigned idx = 0; ; ++idx) {
483ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      if (ItinData->isEndMarker(idx))
49d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin        break;
50d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
513ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      const InstrStage *IS = ItinData->beginStage(idx);
523ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      const InstrStage *E = ItinData->endStage(idx);
532da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      unsigned CurCycle = 0;
54d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin      unsigned ItinDepth = 0;
552da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      for (; IS != E; ++IS) {
562da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        unsigned StageDepth = CurCycle + IS->getCycles();
572da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        if (ItinDepth < StageDepth) ItinDepth = StageDepth;
582da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        CurCycle += IS->getNextCycles();
592da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      }
60d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
616b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      // Find the next power-of-2 >= ItinDepth
626b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      while (ItinDepth > ScoreboardDepth) {
636b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick        ScoreboardDepth *= 2;
64d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // Don't set MaxLookAhead until we find at least one nonzero stage.
65d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // This way, an itinerary with no stages has MaxLookAhead==0, which
66d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // completely bypasses the scoreboard hazard logic.
67d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        MaxLookAhead = ScoreboardDepth;
686b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      }
69d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
70d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
71d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
7296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard.reset(ScoreboardDepth);
7396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard.reset(ScoreboardDepth);
74d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // If MaxLookAhead is not set above, then we are not enabled.
76fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  if (!isEnabled())
77d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick    DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
78fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  else {
792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // A nonempty itinerary must have a SchedModel.
802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    IssueWidth = ItinData->SchedModel->IssueWidth;
81d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick    DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
82d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick          << ScoreboardDepth << '\n');
83fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  }
84d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
85d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
866b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::Reset() {
872da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
8896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard.reset();
8996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard.reset();
90d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
91d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
92b720be6a50f4e1b3280d2b029ee38dda14577525Manman Ren#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
936b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::Scoreboard::dump() const {
9473242dd692c0226073c367c2fe573287a3d63fc1David Greene  dbgs() << "Scoreboard:\n";
951298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
961298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  unsigned last = Depth - 1;
971298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  while ((last > 0) && ((*this)[last] == 0))
98d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    last--;
99d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
100d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  for (unsigned i = 0; i <= last; i++) {
101b460a3382961c5be9952a75d46228f624edbd39fHal Finkel    unsigned FUs = (*this)[i];
10273242dd692c0226073c367c2fe573287a3d63fc1David Greene    dbgs() << "\t";
103b460a3382961c5be9952a75d46228f624edbd39fHal Finkel    for (int j = 31; j >= 0; j--)
104b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      dbgs() << ((FUs & (1 << j)) ? '1' : '0');
10573242dd692c0226073c367c2fe573287a3d63fc1David Greene    dbgs() << '\n';
106d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
107d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
10877e300e8f0b8db8eec448cae9c87d7c5bfad9757Manman Ren#endif
109d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
1102da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trickbool ScoreboardHazardRecognizer::atIssueLimit() const {
1112da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  if (IssueWidth == 0)
1122da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    return false;
1132da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
1142da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  return IssueCount == IssueWidth;
1152da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick}
1162da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
11746df4eb46e784036cf895db271fe29e1cf2a975aEvan ChengScheduleHazardRecognizer::HazardType
1182da8bc8a5f7705ac131184cd247f48500da0d74eAndrew TrickScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
1193ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (!ItinData || ItinData->isEmpty())
120047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    return NoHazard;
121047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
1222da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  // Note that stalls will be negative for bottom-up scheduling.
1232da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  int cycle = Stalls;
124047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
125047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // Use the itinerary for the underlying instruction to check for
126047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // free FU's in the scoreboard at the appropriate future cycles.
1272da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
128e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
129e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  if (MCID == NULL) {
1302da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    // Don't check hazards for non-machineinstr Nodes.
1312da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    return NoHazard;
1322da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  }
133e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned idx = MCID->getSchedClass();
1343ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  for (const InstrStage *IS = ItinData->beginStage(idx),
1353ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng         *E = ItinData->endStage(idx); IS != E; ++IS) {
136047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // We must find one of the stage's units free for every cycle the
137047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // stage is occupied. FIXME it would be more accurate to find the
138047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // same unit free in all the cycles.
139047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
1402da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      int StageCycle = cycle + (int)i;
1412da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      if (StageCycle < 0)
1422da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        continue;
1432da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
1442da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
1452da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
1462da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick               "Scoreboard depth exceeded!");
1472da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        // This stage was stalled beyond pipeline depth, so cannot conflict.
1482da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        break;
1492da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      }
1501298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
151b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnits = IS->getUnits();
15296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      switch (IS->getReservationKind()) {
15396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Required:
15496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Required FUs conflict with both reserved and required ones
1552da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        freeUnits &= ~ReservedScoreboard[StageCycle];
15696085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // FALLTHROUGH
15796085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Reserved:
15896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Reserved FUs can conflict only with required ones.
1592da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        freeUnits &= ~RequiredScoreboard[StageCycle];
16096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        break;
16196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      }
16296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov
163047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      if (!freeUnits) {
1649632f77f8dde9d2c9c9cb9d022b846a82c918cbdBenjamin Kramer        DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
16573242dd692c0226073c367c2fe573287a3d63fc1David Greene        DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
1662da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        DEBUG(DAG->dumpNode(SU));
167047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        return Hazard;
168047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      }
169d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
1701298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
171047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // Advance the cycle to the next stage.
172047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    cycle += IS->getNextCycles();
173d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
174d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
175d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  return NoHazard;
176d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
1771298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
1786b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
1793ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (!ItinData || ItinData->isEmpty())
180047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    return;
181047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
182047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // Use the itinerary for the underlying instruction to reserve FU's
183047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // in the scoreboard at the appropriate future cycles.
184e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
185e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  assert(MCID && "The scheduler must filter non-machineinstrs");
186e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  if (DAG->TII->isZeroCost(MCID->Opcode))
187c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick    return;
188c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
189c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick  ++IssueCount;
190c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
191c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick  unsigned cycle = 0;
192c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
193e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned idx = MCID->getSchedClass();
1943ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  for (const InstrStage *IS = ItinData->beginStage(idx),
1953ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng         *E = ItinData->endStage(idx); IS != E; ++IS) {
196047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // We must reserve one of the stage's units for every cycle the
197047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // stage is occupied. FIXME it would be more accurate to reserve
198047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // the same unit free in all the cycles.
199047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
20096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
201047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin             "Scoreboard depth exceeded!");
2021298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
203b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnits = IS->getUnits();
20496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      switch (IS->getReservationKind()) {
20596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Required:
20696085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Required FUs conflict with both reserved and required ones
20796085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        freeUnits &= ~ReservedScoreboard[cycle + i];
20896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // FALLTHROUGH
20996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Reserved:
21096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Reserved FUs can conflict only with required ones.
21196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        freeUnits &= ~RequiredScoreboard[cycle + i];
21296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        break;
21396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      }
2141298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
215047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      // reduce to a single unit
216b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnit = 0;
217047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      do {
218047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        freeUnit = freeUnits;
219047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        freeUnits = freeUnit & (freeUnit - 1);
220047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      } while (freeUnits);
2211298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
22296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      if (IS->getReservationKind() == InstrStage::Required)
22396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        RequiredScoreboard[cycle + i] |= freeUnit;
22496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      else
22596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        ReservedScoreboard[cycle + i] |= freeUnit;
226d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
2271298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
228047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // Advance the cycle to the next stage.
229047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    cycle += IS->getNextCycles();
230d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
2311298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
23296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  DEBUG(ReservedScoreboard.dump());
23396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  DEBUG(RequiredScoreboard.dump());
234d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
2351298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
2366b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::AdvanceCycle() {
2372da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
23896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
23996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
240d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
2416b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick
2426b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::RecedeCycle() {
2432da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
2446b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
2456b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ReservedScoreboard.recede();
2466b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
2476b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  RequiredScoreboard.recede();
2486b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick}
249