OSDN Git Service

[llvm-mca] Fix header comments. NFC.
[android-x86/external-llvm.git] / tools / llvm-mca / RetireControlUnit.cpp
1 //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 ///
11 /// This file implements methods declared by the RetireControlUnit interface.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "RetireControlUnit.h"
16 #include "DispatchStage.h"
17 #include "llvm/Support/Debug.h"
18
19 using namespace llvm;
20
21 #define DEBUG_TYPE "llvm-mca"
22
23 namespace mca {
24
25 RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM,
26                                      DispatchStage *DS)
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;
37   }
38
39   assert(AvailableSlots && "Invalid reorder buffer size!");
40   Queue.resize(AvailableSlots);
41 }
42
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;
58   return TokenID;
59 }
60
61 void RetireControlUnit::cycleEvent() {
62   if (isEmpty())
63     return;
64
65   unsigned NumRetired = 0;
66   while (!isEmpty()) {
67     if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle)
68       break;
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)
73       break;
74     Owner->notifyInstructionRetired(Current.IR);
75     CurrentInstructionSlotIdx += Current.NumSlots;
76     CurrentInstructionSlotIdx %= Queue.size();
77     AvailableSlots += Current.NumSlots;
78     NumRetired++;
79   }
80 }
81
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;
86 }
87
88 #ifndef NDEBUG
89 void RetireControlUnit::dump() const {
90   dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
91          << ", Available Slots=" << AvailableSlots << " }\n";
92 }
93 #endif
94
95 } // namespace mca