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
166b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick#include "llvm/CodeGen/ScoreboardHazardRecognizer.h"
17774bc882fdb3bbb0558075360c6e5bc510a0bdadEvan Cheng#include "llvm/CodeGen/ScheduleDAG.h"
18ab8be96fd30ca9396e6b84fdddf1ac6208984cadEvan Cheng#include "llvm/MC/MCInstrItineraries.h"
19d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin#include "llvm/Support/Debug.h"
20d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin#include "llvm/Support/ErrorHandling.h"
213a5f0d444cf21e2b90d5eb965bb677c7ce098546David Goodwin#include "llvm/Support/raw_ostream.h"
22c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick#include "llvm/Target/TargetInstrInfo.h"
23d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
24fb98a43b311dec66188b3669a0da017829833617Bill Wendlingusing namespace llvm;
25d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
26dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE ::llvm::ScoreboardHazardRecognizer::DebugType
27dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
282da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#ifndef NDEBUG
292da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trickconst char *ScoreboardHazardRecognizer::DebugType = "";
302da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#endif
312da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
326b1207267f01877ff9b351786c902cb2ecd354c0Andrew TrickScoreboardHazardRecognizer::
332da8bc8a5f7705ac131184cd247f48500da0d74eAndrew TrickScoreboardHazardRecognizer(const InstrItineraryData *II,
342da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick                           const ScheduleDAG *SchedDAG,
352da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick                           const char *ParentDebugType) :
362da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  ScheduleHazardRecognizer(), ItinData(II), DAG(SchedDAG), IssueWidth(0),
372da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount(0) {
382da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
392da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#ifndef NDEBUG
402da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  DebugType = ParentDebugType;
412da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick#endif
422da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
43d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // Determine the maximum depth of any itinerary. This determines the depth of
44d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // the scoreboard. We always make the scoreboard at least 1 cycle deep to
45d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick  // avoid dealing with the boundary condition.
461298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  unsigned ScoreboardDepth = 1;
473ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (ItinData && !ItinData->isEmpty()) {
48d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    for (unsigned idx = 0; ; ++idx) {
493ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      if (ItinData->isEndMarker(idx))
50d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin        break;
51d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
523ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      const InstrStage *IS = ItinData->beginStage(idx);
533ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng      const InstrStage *E = ItinData->endStage(idx);
542da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      unsigned CurCycle = 0;
55d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin      unsigned ItinDepth = 0;
562da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      for (; IS != E; ++IS) {
572da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        unsigned StageDepth = CurCycle + IS->getCycles();
582da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        if (ItinDepth < StageDepth) ItinDepth = StageDepth;
592da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        CurCycle += IS->getNextCycles();
602da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      }
61d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
626b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      // Find the next power-of-2 >= ItinDepth
636b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      while (ItinDepth > ScoreboardDepth) {
646b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick        ScoreboardDepth *= 2;
65d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // Don't set MaxLookAhead until we find at least one nonzero stage.
66d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // This way, an itinerary with no stages has MaxLookAhead==0, which
67d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        // completely bypasses the scoreboard hazard logic.
68d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick        MaxLookAhead = ScoreboardDepth;
696b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick      }
70d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
71d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
72d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
7396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard.reset(ScoreboardDepth);
7496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard.reset(ScoreboardDepth);
75d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // If MaxLookAhead is not set above, then we are not enabled.
77fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  if (!isEnabled())
78d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick    DEBUG(dbgs() << "Disabled scoreboard hazard recognizer\n");
79fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  else {
802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // A nonempty itinerary must have a SchedModel.
812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    IssueWidth = ItinData->SchedModel->IssueWidth;
82d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick    DEBUG(dbgs() << "Using scoreboard hazard recognizer: Depth = "
83d327d3ddddaf23fe920a01bf6304f6a8f4986e89Andrew Trick          << ScoreboardDepth << '\n');
84fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick  }
85d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
86d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
876b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::Reset() {
882da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
8996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard.reset();
9096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard.reset();
91d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
92d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
93b720be6a50f4e1b3280d2b029ee38dda14577525Manman Ren#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
946b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::Scoreboard::dump() const {
9573242dd692c0226073c367c2fe573287a3d63fc1David Greene  dbgs() << "Scoreboard:\n";
961298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
971298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  unsigned last = Depth - 1;
981298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov  while ((last > 0) && ((*this)[last] == 0))
99d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    last--;
100d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
101d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  for (unsigned i = 0; i <= last; i++) {
102b460a3382961c5be9952a75d46228f624edbd39fHal Finkel    unsigned FUs = (*this)[i];
10373242dd692c0226073c367c2fe573287a3d63fc1David Greene    dbgs() << "\t";
104b460a3382961c5be9952a75d46228f624edbd39fHal Finkel    for (int j = 31; j >= 0; j--)
105b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      dbgs() << ((FUs & (1 << j)) ? '1' : '0');
10673242dd692c0226073c367c2fe573287a3d63fc1David Greene    dbgs() << '\n';
107d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
108d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
10977e300e8f0b8db8eec448cae9c87d7c5bfad9757Manman Ren#endif
110d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
1112da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trickbool ScoreboardHazardRecognizer::atIssueLimit() const {
1122da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  if (IssueWidth == 0)
1132da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    return false;
1142da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
1152da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  return IssueCount == IssueWidth;
1162da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick}
1172da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
11846df4eb46e784036cf895db271fe29e1cf2a975aEvan ChengScheduleHazardRecognizer::HazardType
1192da8bc8a5f7705ac131184cd247f48500da0d74eAndrew TrickScoreboardHazardRecognizer::getHazardType(SUnit *SU, int Stalls) {
1203ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (!ItinData || ItinData->isEmpty())
121047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    return NoHazard;
122047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
1232da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  // Note that stalls will be negative for bottom-up scheduling.
1242da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  int cycle = Stalls;
125047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
126047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // Use the itinerary for the underlying instruction to check for
127047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // free FU's in the scoreboard at the appropriate future cycles.
1282da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
129e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
130dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  if (!MCID) {
1312da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    // Don't check hazards for non-machineinstr Nodes.
1322da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick    return NoHazard;
1332da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  }
134e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned idx = MCID->getSchedClass();
1353ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  for (const InstrStage *IS = ItinData->beginStage(idx),
1363ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng         *E = ItinData->endStage(idx); IS != E; ++IS) {
137047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // We must find one of the stage's units free for every cycle the
138047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // stage is occupied. FIXME it would be more accurate to find the
139047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // same unit free in all the cycles.
140047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
1412da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      int StageCycle = cycle + (int)i;
1422da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      if (StageCycle < 0)
1432da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        continue;
1442da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick
1452da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      if (StageCycle >= (int)RequiredScoreboard.getDepth()) {
1462da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        assert((StageCycle - Stalls) < (int)RequiredScoreboard.getDepth() &&
1472da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick               "Scoreboard depth exceeded!");
1482da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        // This stage was stalled beyond pipeline depth, so cannot conflict.
1492da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        break;
1502da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick      }
1511298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
152b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnits = IS->getUnits();
15396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      switch (IS->getReservationKind()) {
15496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Required:
15596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Required FUs conflict with both reserved and required ones
1562da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        freeUnits &= ~ReservedScoreboard[StageCycle];
15796085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // FALLTHROUGH
15896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Reserved:
15996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Reserved FUs can conflict only with required ones.
1602da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        freeUnits &= ~RequiredScoreboard[StageCycle];
16196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        break;
16296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      }
16396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov
164047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      if (!freeUnits) {
1659632f77f8dde9d2c9c9cb9d022b846a82c918cbdBenjamin Kramer        DEBUG(dbgs() << "*** Hazard in cycle +" << StageCycle << ", ");
16673242dd692c0226073c367c2fe573287a3d63fc1David Greene        DEBUG(dbgs() << "SU(" << SU->NodeNum << "): ");
1672da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick        DEBUG(DAG->dumpNode(SU));
168047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        return Hazard;
169047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      }
170d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
1711298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
172047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // Advance the cycle to the next stage.
173047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    cycle += IS->getNextCycles();
174d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
175d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin
176d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  return NoHazard;
177d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
1781298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
1796b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::EmitInstruction(SUnit *SU) {
1803ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  if (!ItinData || ItinData->isEmpty())
181047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    return;
182047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin
183047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // Use the itinerary for the underlying instruction to reserve FU's
184047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin  // in the scoreboard at the appropriate future cycles.
185e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  const MCInstrDesc *MCID = DAG->getInstrDesc(SU);
186e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  assert(MCID && "The scheduler must filter non-machineinstrs");
187e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  if (DAG->TII->isZeroCost(MCID->Opcode))
188c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick    return;
189c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
190c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick  ++IssueCount;
191c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
192c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick  unsigned cycle = 0;
193c8bfd1d78ff9a307d1d4cb57cce4549b538e60f4Andrew Trick
194e837dead3c8dc3445ef6a0e2322179c57e264a13Evan Cheng  unsigned idx = MCID->getSchedClass();
1953ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng  for (const InstrStage *IS = ItinData->beginStage(idx),
1963ef1c8759a20167457eb7fd82ebcaffe7ccaa1d1Evan Cheng         *E = ItinData->endStage(idx); IS != E; ++IS) {
197047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // We must reserve one of the stage's units for every cycle the
198047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // stage is occupied. FIXME it would be more accurate to reserve
199047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // the same unit free in all the cycles.
200047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    for (unsigned int i = 0; i < IS->getCycles(); ++i) {
20196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      assert(((cycle + i) < RequiredScoreboard.getDepth()) &&
202047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin             "Scoreboard depth exceeded!");
2031298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
204b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnits = IS->getUnits();
20596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      switch (IS->getReservationKind()) {
20696085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Required:
20796085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Required FUs conflict with both reserved and required ones
20896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        freeUnits &= ~ReservedScoreboard[cycle + i];
20996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // FALLTHROUGH
21096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      case InstrStage::Reserved:
21196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        // Reserved FUs can conflict only with required ones.
21296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        freeUnits &= ~RequiredScoreboard[cycle + i];
21396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        break;
21496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      }
2151298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
216047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      // reduce to a single unit
217b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      unsigned freeUnit = 0;
218047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      do {
219047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        freeUnit = freeUnits;
220047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin        freeUnits = freeUnit & (freeUnit - 1);
221047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin      } while (freeUnits);
2221298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
22396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      if (IS->getReservationKind() == InstrStage::Required)
22496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        RequiredScoreboard[cycle + i] |= freeUnit;
22596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov      else
22696085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov        ReservedScoreboard[cycle + i] |= freeUnit;
227d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin    }
2281298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
229047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    // Advance the cycle to the next stage.
230047ae2f2ad2161d37996c26a5e5ac2b79f09eee5David Goodwin    cycle += IS->getNextCycles();
231d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin  }
2321298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
23396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  DEBUG(ReservedScoreboard.dump());
23496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  DEBUG(RequiredScoreboard.dump());
235d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
2361298948c5c36e6e88cbde0abe73f7f37c3a038a6Anton Korobeynikov
2376b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::AdvanceCycle() {
2382da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
23996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  ReservedScoreboard[0] = 0; ReservedScoreboard.advance();
24096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  RequiredScoreboard[0] = 0; RequiredScoreboard.advance();
241d94a4e5d8de1145be200ff7223f98b0928462b94David Goodwin}
2426b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick
2436b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trickvoid ScoreboardHazardRecognizer::RecedeCycle() {
2442da8bc8a5f7705ac131184cd247f48500da0d74eAndrew Trick  IssueCount = 0;
2456b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ReservedScoreboard[ReservedScoreboard.getDepth()-1] = 0;
2466b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  ReservedScoreboard.recede();
2476b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  RequiredScoreboard[RequiredScoreboard.getDepth()-1] = 0;
2486b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick  RequiredScoreboard.recede();
2496b1207267f01877ff9b351786c902cb2ecd354c0Andrew Trick}
250