]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-mca/RetireControlUnit.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / 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 simulates the hardware responsible for retiring instructions.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "RetireControlUnit.h"
16 #include "llvm/Support/Debug.h"
17
18 using namespace llvm;
19
20 #define DEBUG_TYPE "llvm-mca"
21
22 namespace mca {
23
24 RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM)
25     : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
26       AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0) {
27   // Check if the scheduling model provides extra information about the machine
28   // processor. If so, then use that information to set the reorder buffer size
29   // and the maximum number of instructions retired per cycle.
30   if (SM.hasExtraProcessorInfo()) {
31     const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
32     if (EPI.ReorderBufferSize)
33       AvailableSlots = EPI.ReorderBufferSize;
34     MaxRetirePerCycle = EPI.MaxRetirePerCycle;
35   }
36
37   assert(AvailableSlots && "Invalid reorder buffer size!");
38   Queue.resize(AvailableSlots);
39 }
40
41 // Reserves a number of slots, and returns a new token.
42 unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
43                                         unsigned NumMicroOps) {
44   assert(isAvailable(NumMicroOps));
45   unsigned NormalizedQuantity =
46       std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
47   // Zero latency instructions may have zero mOps. Artificially bump this
48   // value to 1. Although zero latency instructions don't consume scheduler
49   // resources, they still consume one slot in the retire queue.
50   NormalizedQuantity = std::max(NormalizedQuantity, 1U);
51   unsigned TokenID = NextAvailableSlotIdx;
52   Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
53   NextAvailableSlotIdx += NormalizedQuantity;
54   NextAvailableSlotIdx %= Queue.size();
55   AvailableSlots -= NormalizedQuantity;
56   return TokenID;
57 }
58
59 const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
60   return Queue[CurrentInstructionSlotIdx];
61 }
62
63 void RetireControlUnit::consumeCurrentToken() {
64   const RetireControlUnit::RUToken &Current = peekCurrentToken();
65   assert(Current.NumSlots && "Reserved zero slots?");
66   assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
67
68   // Update the slot index to be the next item in the circular queue.
69   CurrentInstructionSlotIdx += Current.NumSlots;
70   CurrentInstructionSlotIdx %= Queue.size();
71   AvailableSlots += Current.NumSlots;
72 }
73
74 void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
75   assert(Queue.size() > TokenID);
76   assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
77   Queue[TokenID].Executed = true;
78 }
79
80 #ifndef NDEBUG
81 void RetireControlUnit::dump() const {
82   dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
83          << ", Available Slots=" << AvailableSlots << " }\n";
84 }
85 #endif
86
87 } // namespace mca