1 //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// This file implements methods declared by the RetireControlUnit interface.
13 //===----------------------------------------------------------------------===//
15 #include "RetireControlUnit.h"
16 #include "DispatchStage.h"
17 #include "llvm/Support/Debug.h"
21 #define DEBUG_TYPE "llvm-mca"
25 RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM,
27 : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
28 AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0), Owner(DS) {
29 // Check if the scheduling model provides extra information about the machine
30 // processor. If so, then use that information to set the reorder buffer size
31 // and the maximum number of instructions retired per cycle.
32 if (SM.hasExtraProcessorInfo()) {
33 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
34 if (EPI.ReorderBufferSize)
35 AvailableSlots = EPI.ReorderBufferSize;
36 MaxRetirePerCycle = EPI.MaxRetirePerCycle;
39 assert(AvailableSlots && "Invalid reorder buffer size!");
40 Queue.resize(AvailableSlots);
43 // Reserves a number of slots, and returns a new token.
44 unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
45 unsigned NumMicroOps) {
46 assert(isAvailable(NumMicroOps));
47 unsigned NormalizedQuantity =
48 std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
49 // Zero latency instructions may have zero mOps. Artificially bump this
50 // value to 1. Although zero latency instructions don't consume scheduler
51 // resources, they still consume one slot in the retire queue.
52 NormalizedQuantity = std::max(NormalizedQuantity, 1U);
53 unsigned TokenID = NextAvailableSlotIdx;
54 Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
55 NextAvailableSlotIdx += NormalizedQuantity;
56 NextAvailableSlotIdx %= Queue.size();
57 AvailableSlots -= NormalizedQuantity;
61 void RetireControlUnit::cycleEvent() {
65 unsigned NumRetired = 0;
67 if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle)
69 RUToken &Current = Queue[CurrentInstructionSlotIdx];
70 assert(Current.NumSlots && "Reserved zero slots?");
71 assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
72 if (!Current.Executed)
74 Owner->notifyInstructionRetired(Current.IR);
75 CurrentInstructionSlotIdx += Current.NumSlots;
76 CurrentInstructionSlotIdx %= Queue.size();
77 AvailableSlots += Current.NumSlots;
82 void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
83 assert(Queue.size() > TokenID);
84 assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
85 Queue[TokenID].Executed = true;
89 void RetireControlUnit::dump() const {
90 dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
91 << ", Available Slots=" << AvailableSlots << " }\n";