1311116Sdim//=-- SystemZHazardRecognizer.h - SystemZ Hazard Recognizer -----*- C++ -*-===//
2311116Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6311116Sdim//
7311116Sdim//===----------------------------------------------------------------------===//
8311116Sdim//
9311116Sdim// This file defines a hazard recognizer for the SystemZ scheduler.
10311116Sdim//
11311116Sdim// This class is used by the SystemZ scheduling strategy to maintain
12311116Sdim// the state during scheduling, and provide cost functions for
13311116Sdim// scheduling candidates. This includes:
14311116Sdim//
15311116Sdim// * Decoder grouping. A decoder group can maximally hold 3 uops, and
16311116Sdim// instructions that always begin a new group should be scheduled when
17311116Sdim// the current decoder group is empty.
18311116Sdim// * Processor resources usage. It is beneficial to balance the use of
19311116Sdim// resources.
20311116Sdim//
21327952Sdim// A goal is to consider all instructions, also those outside of any
22327952Sdim// scheduling region. Such instructions are "advanced" past and include
23327952Sdim// single instructions before a scheduling region, branches etc.
24327952Sdim//
25327952Sdim// A block that has only one predecessor continues scheduling with the state
26327952Sdim// of it (which may be updated by emitting branches).
27327952Sdim//
28311116Sdim// ===---------------------------------------------------------------------===//
29311116Sdim
30311116Sdim#include "SystemZHazardRecognizer.h"
31311116Sdim#include "llvm/ADT/Statistic.h"
32311116Sdim
33311116Sdimusing namespace llvm;
34311116Sdim
35321369Sdim#define DEBUG_TYPE "machine-scheduler"
36311116Sdim
37311116Sdim// This is the limit of processor resource usage at which the
38311116Sdim// scheduler should try to look for other instructions (not using the
39311116Sdim// critical resource).
40311116Sdimstatic cl::opt<int> ProcResCostLim("procres-cost-lim", cl::Hidden,
41311116Sdim                                   cl::desc("The OOO window for processor "
42311116Sdim                                            "resources during scheduling."),
43311116Sdim                                   cl::init(8));
44311116Sdim
45311116Sdimunsigned SystemZHazardRecognizer::
46311116SdimgetNumDecoderSlots(SUnit *SU) const {
47327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
48311116Sdim  if (!SC->isValid())
49311116Sdim    return 0; // IMPLICIT_DEF / KILL -- will not make impact in output.
50311116Sdim
51344779Sdim  assert((SC->NumMicroOps != 2 || (SC->BeginGroup && !SC->EndGroup)) &&
52344779Sdim         "Only cracked instruction can have 2 uops.");
53344779Sdim  assert((SC->NumMicroOps < 3 || (SC->BeginGroup && SC->EndGroup)) &&
54344779Sdim         "Expanded instructions always group alone.");
55344779Sdim  assert((SC->NumMicroOps < 3 || (SC->NumMicroOps % 3 == 0)) &&
56344779Sdim         "Expanded instructions fill the group(s).");
57341825Sdim
58344779Sdim  return SC->NumMicroOps;
59311116Sdim}
60311116Sdim
61341825Sdimunsigned SystemZHazardRecognizer::getCurrCycleIdx(SUnit *SU) const {
62311116Sdim  unsigned Idx = CurrGroupSize;
63311116Sdim  if (GrpCount % 2)
64311116Sdim    Idx += 3;
65341825Sdim
66341825Sdim  if (SU != nullptr && !fitsIntoCurrentGroup(SU)) {
67341825Sdim    if (Idx == 1 || Idx == 2)
68341825Sdim      Idx = 3;
69341825Sdim    else if (Idx == 4 || Idx == 5)
70341825Sdim      Idx = 0;
71341825Sdim  }
72341825Sdim
73311116Sdim  return Idx;
74311116Sdim}
75311116Sdim
76311116SdimScheduleHazardRecognizer::HazardType SystemZHazardRecognizer::
77311116SdimgetHazardType(SUnit *m, int Stalls) {
78311116Sdim  return (fitsIntoCurrentGroup(m) ? NoHazard : Hazard);
79311116Sdim}
80311116Sdim
81311116Sdimvoid SystemZHazardRecognizer::Reset() {
82311116Sdim  CurrGroupSize = 0;
83341825Sdim  CurrGroupHas4RegOps = false;
84311116Sdim  clearProcResCounters();
85311116Sdim  GrpCount = 0;
86311116Sdim  LastFPdOpCycleIdx = UINT_MAX;
87327952Sdim  LastEmittedMI = nullptr;
88341825Sdim  LLVM_DEBUG(CurGroupDbg = "";);
89311116Sdim}
90311116Sdim
91311116Sdimbool
92311116SdimSystemZHazardRecognizer::fitsIntoCurrentGroup(SUnit *SU) const {
93327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
94311116Sdim  if (!SC->isValid())
95311116Sdim    return true;
96311116Sdim
97311116Sdim  // A cracked instruction only fits into schedule if the current
98311116Sdim  // group is empty.
99311116Sdim  if (SC->BeginGroup)
100311116Sdim    return (CurrGroupSize == 0);
101311116Sdim
102341825Sdim  // An instruction with 4 register operands will not fit in last slot.
103341825Sdim  assert ((CurrGroupSize < 2 || !CurrGroupHas4RegOps) &&
104341825Sdim          "Current decoder group is already full!");
105341825Sdim  if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
106341825Sdim    return false;
107341825Sdim
108311116Sdim  // Since a full group is handled immediately in EmitInstruction(),
109311116Sdim  // SU should fit into current group. NumSlots should be 1 or 0,
110311116Sdim  // since it is not a cracked or expanded instruction.
111311116Sdim  assert ((getNumDecoderSlots(SU) <= 1) && (CurrGroupSize < 3) &&
112311116Sdim          "Expected normal instruction to fit in non-full group!");
113311116Sdim
114311116Sdim  return true;
115311116Sdim}
116311116Sdim
117341825Sdimbool SystemZHazardRecognizer::has4RegOps(const MachineInstr *MI) const {
118341825Sdim  const MachineFunction &MF = *MI->getParent()->getParent();
119341825Sdim  const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
120341825Sdim  const MCInstrDesc &MID = MI->getDesc();
121341825Sdim  unsigned Count = 0;
122341825Sdim  for (unsigned OpIdx = 0; OpIdx < MID.getNumOperands(); OpIdx++) {
123341825Sdim    const TargetRegisterClass *RC = TII->getRegClass(MID, OpIdx, TRI, MF);
124341825Sdim    if (RC == nullptr)
125341825Sdim      continue;
126341825Sdim    if (OpIdx >= MID.getNumDefs() &&
127341825Sdim        MID.getOperandConstraint(OpIdx, MCOI::TIED_TO) != -1)
128341825Sdim      continue;
129341825Sdim    Count++;
130341825Sdim  }
131341825Sdim  return Count >= 4;
132341825Sdim}
133311116Sdim
134341825Sdimvoid SystemZHazardRecognizer::nextGroup() {
135341825Sdim  if (CurrGroupSize == 0)
136341825Sdim    return;
137311116Sdim
138341825Sdim  LLVM_DEBUG(dumpCurrGroup("Completed decode group"));
139341825Sdim  LLVM_DEBUG(CurGroupDbg = "";);
140311116Sdim
141344779Sdim  int NumGroups = ((CurrGroupSize > 3) ? (CurrGroupSize / 3) : 1);
142344779Sdim  assert((CurrGroupSize <= 3 || CurrGroupSize % 3 == 0) &&
143344779Sdim         "Current decoder group bad.");
144311116Sdim
145341825Sdim  // Reset counter for next group.
146341825Sdim  CurrGroupSize = 0;
147341825Sdim  CurrGroupHas4RegOps = false;
148311116Sdim
149344779Sdim  GrpCount += ((unsigned) NumGroups);
150344779Sdim
151344779Sdim  // Decrease counters for execution units.
152341825Sdim  for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
153344779Sdim    ProcResourceCounters[i] = ((ProcResourceCounters[i] > NumGroups)
154344779Sdim                                   ? (ProcResourceCounters[i] - NumGroups)
155344779Sdim                                   : 0);
156341825Sdim
157341825Sdim  // Clear CriticalResourceIdx if it is now below the threshold.
158341825Sdim  if (CriticalResourceIdx != UINT_MAX &&
159341825Sdim      (ProcResourceCounters[CriticalResourceIdx] <=
160341825Sdim       ProcResCostLim))
161341825Sdim    CriticalResourceIdx = UINT_MAX;
162341825Sdim
163341825Sdim  LLVM_DEBUG(dumpState(););
164311116Sdim}
165311116Sdim
166311116Sdim#ifndef NDEBUG // Debug output
167311116Sdimvoid SystemZHazardRecognizer::dumpSU(SUnit *SU, raw_ostream &OS) const {
168311116Sdim  OS << "SU(" << SU->NodeNum << "):";
169327952Sdim  OS << TII->getName(SU->getInstr()->getOpcode());
170311116Sdim
171327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
172311116Sdim  if (!SC->isValid())
173311116Sdim    return;
174341825Sdim
175311116Sdim  for (TargetSchedModel::ProcResIter
176311116Sdim         PI = SchedModel->getWriteProcResBegin(SC),
177311116Sdim         PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
178311116Sdim    const MCProcResourceDesc &PRD =
179311116Sdim      *SchedModel->getProcResource(PI->ProcResourceIdx);
180311116Sdim    std::string FU(PRD.Name);
181311116Sdim    // trim e.g. Z13_FXaUnit -> FXa
182311116Sdim    FU = FU.substr(FU.find("_") + 1);
183341825Sdim    size_t Pos = FU.find("Unit");
184341825Sdim    if (Pos != std::string::npos)
185341825Sdim      FU.resize(Pos);
186341825Sdim    if (FU == "LS") // LSUnit -> LSU
187341825Sdim      FU = "LSU";
188311116Sdim    OS << "/" << FU;
189311116Sdim
190311116Sdim    if (PI->Cycles > 1)
191311116Sdim      OS << "(" << PI->Cycles << "cyc)";
192311116Sdim  }
193311116Sdim
194311116Sdim  if (SC->NumMicroOps > 1)
195311116Sdim    OS << "/" << SC->NumMicroOps << "uops";
196311116Sdim  if (SC->BeginGroup && SC->EndGroup)
197311116Sdim    OS << "/GroupsAlone";
198311116Sdim  else if (SC->BeginGroup)
199311116Sdim    OS << "/BeginsGroup";
200311116Sdim  else if (SC->EndGroup)
201311116Sdim    OS << "/EndsGroup";
202311116Sdim  if (SU->isUnbuffered)
203311116Sdim    OS << "/Unbuffered";
204341825Sdim  if (has4RegOps(SU->getInstr()))
205341825Sdim    OS << "/4RegOps";
206311116Sdim}
207311116Sdim
208311116Sdimvoid SystemZHazardRecognizer::dumpCurrGroup(std::string Msg) const {
209341825Sdim  dbgs() << "++ " << Msg;
210311116Sdim  dbgs() << ": ";
211311116Sdim
212311116Sdim  if (CurGroupDbg.empty())
213311116Sdim    dbgs() << " <empty>\n";
214311116Sdim  else {
215311116Sdim    dbgs() << "{ " << CurGroupDbg << " }";
216311116Sdim    dbgs() << " (" << CurrGroupSize << " decoder slot"
217311116Sdim           << (CurrGroupSize > 1 ? "s":"")
218341825Sdim           << (CurrGroupHas4RegOps ? ", 4RegOps" : "")
219311116Sdim           << ")\n";
220311116Sdim  }
221311116Sdim}
222311116Sdim
223311116Sdimvoid SystemZHazardRecognizer::dumpProcResourceCounters() const {
224311116Sdim  bool any = false;
225311116Sdim
226311116Sdim  for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
227311116Sdim    if (ProcResourceCounters[i] > 0) {
228311116Sdim      any = true;
229311116Sdim      break;
230311116Sdim    }
231311116Sdim
232311116Sdim  if (!any)
233311116Sdim    return;
234311116Sdim
235341825Sdim  dbgs() << "++ | Resource counters: ";
236311116Sdim  for (unsigned i = 0; i < SchedModel->getNumProcResourceKinds(); ++i)
237341825Sdim    if (ProcResourceCounters[i] > 0)
238341825Sdim      dbgs() << SchedModel->getProcResource(i)->Name
239341825Sdim             << ":" << ProcResourceCounters[i] << " ";
240341825Sdim  dbgs() << "\n";
241341825Sdim
242341825Sdim  if (CriticalResourceIdx != UINT_MAX)
243341825Sdim    dbgs() << "++ | Critical resource: "
244341825Sdim           << SchedModel->getProcResource(CriticalResourceIdx)->Name
245341825Sdim           << "\n";
246311116Sdim}
247341825Sdim
248341825Sdimvoid SystemZHazardRecognizer::dumpState() const {
249341825Sdim  dumpCurrGroup("| Current decoder group");
250341825Sdim  dbgs() << "++ | Current cycle index: "
251341825Sdim         << getCurrCycleIdx() << "\n";
252341825Sdim  dumpProcResourceCounters();
253341825Sdim  if (LastFPdOpCycleIdx != UINT_MAX)
254341825Sdim    dbgs() << "++ | Last FPd cycle index: " << LastFPdOpCycleIdx << "\n";
255341825Sdim}
256341825Sdim
257311116Sdim#endif //NDEBUG
258311116Sdim
259311116Sdimvoid SystemZHazardRecognizer::clearProcResCounters() {
260311116Sdim  ProcResourceCounters.assign(SchedModel->getNumProcResourceKinds(), 0);
261311116Sdim  CriticalResourceIdx = UINT_MAX;
262311116Sdim}
263311116Sdim
264327952Sdimstatic inline bool isBranchRetTrap(MachineInstr *MI) {
265327952Sdim  return (MI->isBranch() || MI->isReturn() ||
266327952Sdim          MI->getOpcode() == SystemZ::CondTrap);
267327952Sdim}
268327952Sdim
269311116Sdim// Update state with SU as the next scheduled unit.
270311116Sdimvoid SystemZHazardRecognizer::
271311116SdimEmitInstruction(SUnit *SU) {
272327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
273341825Sdim  LLVM_DEBUG(dbgs() << "++ HazardRecognizer emitting "; dumpSU(SU, dbgs());
274341825Sdim             dbgs() << "\n";);
275341825Sdim  LLVM_DEBUG(dumpCurrGroup("Decode group before emission"););
276311116Sdim
277311116Sdim  // If scheduling an SU that must begin a new decoder group, move on
278311116Sdim  // to next group.
279311116Sdim  if (!fitsIntoCurrentGroup(SU))
280311116Sdim    nextGroup();
281311116Sdim
282341825Sdim  LLVM_DEBUG(raw_string_ostream cgd(CurGroupDbg);
283341825Sdim             if (CurGroupDbg.length()) cgd << ", "; dumpSU(SU, cgd););
284311116Sdim
285327952Sdim  LastEmittedMI = SU->getInstr();
286327952Sdim
287311116Sdim  // After returning from a call, we don't know much about the state.
288327952Sdim  if (SU->isCall) {
289341825Sdim    LLVM_DEBUG(dbgs() << "++ Clearing state after call.\n";);
290341825Sdim    Reset();
291341825Sdim    LastEmittedMI = SU->getInstr();
292311116Sdim    return;
293311116Sdim  }
294311116Sdim
295311116Sdim  // Increase counter for execution unit(s).
296311116Sdim  for (TargetSchedModel::ProcResIter
297311116Sdim         PI = SchedModel->getWriteProcResBegin(SC),
298311116Sdim         PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI) {
299311116Sdim    // Don't handle FPd together with the other resources.
300311116Sdim    if (SchedModel->getProcResource(PI->ProcResourceIdx)->BufferSize == 1)
301311116Sdim      continue;
302311116Sdim    int &CurrCounter =
303311116Sdim      ProcResourceCounters[PI->ProcResourceIdx];
304311116Sdim    CurrCounter += PI->Cycles;
305311116Sdim    // Check if this is now the new critical resource.
306311116Sdim    if ((CurrCounter > ProcResCostLim) &&
307311116Sdim        (CriticalResourceIdx == UINT_MAX ||
308311116Sdim         (PI->ProcResourceIdx != CriticalResourceIdx &&
309311116Sdim          CurrCounter >
310311116Sdim          ProcResourceCounters[CriticalResourceIdx]))) {
311341825Sdim      LLVM_DEBUG(
312341825Sdim          dbgs() << "++ New critical resource: "
313341825Sdim                 << SchedModel->getProcResource(PI->ProcResourceIdx)->Name
314341825Sdim                 << "\n";);
315311116Sdim      CriticalResourceIdx = PI->ProcResourceIdx;
316311116Sdim    }
317311116Sdim  }
318311116Sdim
319311116Sdim  // Make note of an instruction that uses a blocking resource (FPd).
320311116Sdim  if (SU->isUnbuffered) {
321341825Sdim    LastFPdOpCycleIdx = getCurrCycleIdx(SU);
322341825Sdim    LLVM_DEBUG(dbgs() << "++ Last FPd cycle index: " << LastFPdOpCycleIdx
323341825Sdim                      << "\n";);
324311116Sdim  }
325311116Sdim
326311116Sdim  // Insert SU into current group by increasing number of slots used
327311116Sdim  // in current group.
328311116Sdim  CurrGroupSize += getNumDecoderSlots(SU);
329341825Sdim  CurrGroupHas4RegOps |= has4RegOps(SU->getInstr());
330344779Sdim  unsigned GroupLim = (CurrGroupHas4RegOps ? 2 : 3);
331344779Sdim  assert((CurrGroupSize <= GroupLim || CurrGroupSize == getNumDecoderSlots(SU))
332344779Sdim         && "SU does not fit into decoder group!");
333311116Sdim
334311116Sdim  // Check if current group is now full/ended. If so, move on to next
335311116Sdim  // group to be ready to evaluate more candidates.
336344779Sdim  if (CurrGroupSize >= GroupLim || SC->EndGroup)
337311116Sdim    nextGroup();
338311116Sdim}
339311116Sdim
340311116Sdimint SystemZHazardRecognizer::groupingCost(SUnit *SU) const {
341327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
342311116Sdim  if (!SC->isValid())
343311116Sdim    return 0;
344341825Sdim
345311116Sdim  // If SU begins new group, it can either break a current group early
346311116Sdim  // or fit naturally if current group is empty (negative cost).
347311116Sdim  if (SC->BeginGroup) {
348311116Sdim    if (CurrGroupSize)
349311116Sdim      return 3 - CurrGroupSize;
350311116Sdim    return -1;
351311116Sdim  }
352311116Sdim
353311116Sdim  // Similarly, a group-ending SU may either fit well (last in group), or
354311116Sdim  // end the group prematurely.
355311116Sdim  if (SC->EndGroup) {
356311116Sdim    unsigned resultingGroupSize =
357311116Sdim      (CurrGroupSize + getNumDecoderSlots(SU));
358311116Sdim    if (resultingGroupSize < 3)
359311116Sdim      return (3 - resultingGroupSize);
360311116Sdim    return -1;
361311116Sdim  }
362311116Sdim
363341825Sdim  // An instruction with 4 register operands will not fit in last slot.
364341825Sdim  if (CurrGroupSize == 2 && has4RegOps(SU->getInstr()))
365341825Sdim    return 1;
366341825Sdim
367311116Sdim  // Most instructions can be placed in any decoder slot.
368311116Sdim  return 0;
369311116Sdim}
370311116Sdim
371341825Sdimbool SystemZHazardRecognizer::isFPdOpPreferred_distance(SUnit *SU) const {
372311116Sdim  assert (SU->isUnbuffered);
373311116Sdim  // If this is the first FPd op, it should be scheduled high.
374311116Sdim  if (LastFPdOpCycleIdx == UINT_MAX)
375311116Sdim    return true;
376311116Sdim  // If this is not the first PFd op, it should go into the other side
377311116Sdim  // of the processor to use the other FPd unit there. This should
378311116Sdim  // generally happen if two FPd ops are placed with 2 other
379311116Sdim  // instructions between them (modulo 6).
380341825Sdim  unsigned SUCycleIdx = getCurrCycleIdx(SU);
381341825Sdim  if (LastFPdOpCycleIdx > SUCycleIdx)
382341825Sdim    return ((LastFPdOpCycleIdx - SUCycleIdx) == 3);
383341825Sdim  return ((SUCycleIdx - LastFPdOpCycleIdx) == 3);
384311116Sdim}
385311116Sdim
386311116Sdimint SystemZHazardRecognizer::
387311116SdimresourcesCost(SUnit *SU) {
388311116Sdim  int Cost = 0;
389311116Sdim
390327952Sdim  const MCSchedClassDesc *SC = getSchedClass(SU);
391311116Sdim  if (!SC->isValid())
392311116Sdim    return 0;
393311116Sdim
394311116Sdim  // For a FPd op, either return min or max value as indicated by the
395311116Sdim  // distance to any prior FPd op.
396311116Sdim  if (SU->isUnbuffered)
397311116Sdim    Cost = (isFPdOpPreferred_distance(SU) ? INT_MIN : INT_MAX);
398311116Sdim  // For other instructions, give a cost to the use of the critical resource.
399311116Sdim  else if (CriticalResourceIdx != UINT_MAX) {
400311116Sdim    for (TargetSchedModel::ProcResIter
401311116Sdim           PI = SchedModel->getWriteProcResBegin(SC),
402311116Sdim           PE = SchedModel->getWriteProcResEnd(SC); PI != PE; ++PI)
403311116Sdim      if (PI->ProcResourceIdx == CriticalResourceIdx)
404311116Sdim        Cost = PI->Cycles;
405311116Sdim  }
406311116Sdim
407311116Sdim  return Cost;
408311116Sdim}
409311116Sdim
410327952Sdimvoid SystemZHazardRecognizer::emitInstruction(MachineInstr *MI,
411327952Sdim                                              bool TakenBranch) {
412327952Sdim  // Make a temporary SUnit.
413327952Sdim  SUnit SU(MI, 0);
414327952Sdim
415327952Sdim  // Set interesting flags.
416327952Sdim  SU.isCall = MI->isCall();
417327952Sdim
418327952Sdim  const MCSchedClassDesc *SC = SchedModel->resolveSchedClass(MI);
419327952Sdim  for (const MCWriteProcResEntry &PRE :
420327952Sdim         make_range(SchedModel->getWriteProcResBegin(SC),
421327952Sdim                    SchedModel->getWriteProcResEnd(SC))) {
422327952Sdim    switch (SchedModel->getProcResource(PRE.ProcResourceIdx)->BufferSize) {
423327952Sdim    case 0:
424327952Sdim      SU.hasReservedResource = true;
425327952Sdim      break;
426327952Sdim    case 1:
427327952Sdim      SU.isUnbuffered = true;
428327952Sdim      break;
429327952Sdim    default:
430327952Sdim      break;
431327952Sdim    }
432327952Sdim  }
433327952Sdim
434341825Sdim  unsigned GroupSizeBeforeEmit = CurrGroupSize;
435327952Sdim  EmitInstruction(&SU);
436327952Sdim
437341825Sdim  if (!TakenBranch && isBranchRetTrap(MI)) {
438341825Sdim    // NT Branch on second slot ends group.
439341825Sdim    if (GroupSizeBeforeEmit == 1)
440341825Sdim      nextGroup();
441341825Sdim  }
442341825Sdim
443327952Sdim  if (TakenBranch && CurrGroupSize > 0)
444341825Sdim    nextGroup();
445327952Sdim
446327952Sdim  assert ((!MI->isTerminator() || isBranchRetTrap(MI)) &&
447327952Sdim          "Scheduler: unhandled terminator!");
448327952Sdim}
449327952Sdim
450327952Sdimvoid SystemZHazardRecognizer::
451327952SdimcopyState(SystemZHazardRecognizer *Incoming) {
452327952Sdim  // Current decoder group
453327952Sdim  CurrGroupSize = Incoming->CurrGroupSize;
454341825Sdim  LLVM_DEBUG(CurGroupDbg = Incoming->CurGroupDbg;);
455327952Sdim
456327952Sdim  // Processor resources
457327952Sdim  ProcResourceCounters = Incoming->ProcResourceCounters;
458327952Sdim  CriticalResourceIdx = Incoming->CriticalResourceIdx;
459327952Sdim
460327952Sdim  // FPd
461327952Sdim  LastFPdOpCycleIdx = Incoming->LastFPdOpCycleIdx;
462327952Sdim  GrpCount = Incoming->GrpCount;
463327952Sdim}
464