[ARM] Better patterns for fp <> predicate vectors
[llvm-complete.git] / lib / MCA / HardwareUnits / RetireControlUnit.cpp
blob068c5062ccdf19f095603c14227ec5f970da334d
1 //===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file simulates the hardware responsible for retiring instructions.
11 ///
12 //===----------------------------------------------------------------------===//
14 #include "llvm/MCA/HardwareUnits/RetireControlUnit.h"
15 #include "llvm/Support/Debug.h"
17 #define DEBUG_TYPE "llvm-mca"
19 namespace llvm {
20 namespace mca {
22 RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)
23 : NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
24 AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0) {
25 // Check if the scheduling model provides extra information about the machine
26 // processor. If so, then use that information to set the reorder buffer size
27 // and the maximum number of instructions retired per cycle.
28 if (SM.hasExtraProcessorInfo()) {
29 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
30 if (EPI.ReorderBufferSize)
31 AvailableSlots = EPI.ReorderBufferSize;
32 MaxRetirePerCycle = EPI.MaxRetirePerCycle;
35 assert(AvailableSlots && "Invalid reorder buffer size!");
36 Queue.resize(AvailableSlots);
39 // Reserves a number of slots, and returns a new token.
40 unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
41 unsigned NumMicroOps) {
42 assert(isAvailable(NumMicroOps) && "Reorder Buffer unavailable!");
43 unsigned NormalizedQuantity =
44 std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
45 // Zero latency instructions may have zero uOps. Artificially bump this
46 // value to 1. Although zero latency instructions don't consume scheduler
47 // resources, they still consume one slot in the retire queue.
48 NormalizedQuantity = std::max(NormalizedQuantity, 1U);
49 unsigned TokenID = NextAvailableSlotIdx;
50 Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
51 NextAvailableSlotIdx += NormalizedQuantity;
52 NextAvailableSlotIdx %= Queue.size();
53 AvailableSlots -= NormalizedQuantity;
54 return TokenID;
57 const RetireControlUnit::RUToken &RetireControlUnit::peekCurrentToken() const {
58 return Queue[CurrentInstructionSlotIdx];
61 void RetireControlUnit::consumeCurrentToken() {
62 RetireControlUnit::RUToken &Current = Queue[CurrentInstructionSlotIdx];
63 assert(Current.NumSlots && "Reserved zero slots?");
64 assert(Current.IR && "Invalid RUToken in the RCU queue.");
65 Current.IR.getInstruction()->retire();
67 // Update the slot index to be the next item in the circular queue.
68 CurrentInstructionSlotIdx += Current.NumSlots;
69 CurrentInstructionSlotIdx %= Queue.size();
70 AvailableSlots += Current.NumSlots;
73 void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
74 assert(Queue.size() > TokenID);
75 assert(Queue[TokenID].Executed == false && Queue[TokenID].IR);
76 Queue[TokenID].Executed = true;
79 #ifndef NDEBUG
80 void RetireControlUnit::dump() const {
81 dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
82 << ", Available Slots=" << AvailableSlots << " }\n";
84 #endif
86 } // namespace mca
87 } // namespace llvm