mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-20 20:36:11 +00:00

Summary: The logic of dispatch remains the same, but now DispatchUnit is a Stage (DispatchStage). This change has the benefit of simplifying the backend runCycle() code. The same logic applies, but it belongs to different components now. This is just a start, eventually we will need to remove the call to the DispatchStage in Scheduler.cpp, but that will be a separate patch. This change is mostly a renaming and moving of existing logic. This change also encouraged me to remove the Subtarget (STI) member from the Backend class. That member was used to initialize the other members of Backend and to eventually call DispatchUnit::dispatch(). Now that we have Stages, we can eliminate this by instantiating the DispatchStage with everything it needs at the time of construction (e.g., Subtarget). That change allows us to call DispatchStage::execute(IR) as we expect to call execute() for all other stages. Once we add the Stage list (D46907) we can more cleanly call preExecute() on all of the stages, DispatchStage, will probably wrap cycleEvent() in that case. Made some formatting and minor cleanups to README.txt. Some of the text was re-flowed to stay within 80 cols. Reviewers: andreadb, courbet, RKSimon Reviewed By: andreadb, courbet Subscribers: mgorny, javed.absar, tschuett, gbedwell, llvm-commits Differential Revision: https://reviews.llvm.org/D46983 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@332652 91177308-0d34-0410-b5e6-96231b3b80d8
96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
//===---------------------- RetireControlUnit.cpp ---------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
///
|
|
/// This file implements methods declared by the RetireControlUnit interface.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RetireControlUnit.h"
|
|
#include "DispatchStage.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "llvm-mca"
|
|
|
|
namespace mca {
|
|
|
|
RetireControlUnit::RetireControlUnit(const llvm::MCSchedModel &SM,
|
|
DispatchStage *DS)
|
|
: NextAvailableSlotIdx(0), CurrentInstructionSlotIdx(0),
|
|
AvailableSlots(SM.MicroOpBufferSize), MaxRetirePerCycle(0), Owner(DS) {
|
|
// Check if the scheduling model provides extra information about the machine
|
|
// processor. If so, then use that information to set the reorder buffer size
|
|
// and the maximum number of instructions retired per cycle.
|
|
if (SM.hasExtraProcessorInfo()) {
|
|
const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();
|
|
if (EPI.ReorderBufferSize)
|
|
AvailableSlots = EPI.ReorderBufferSize;
|
|
MaxRetirePerCycle = EPI.MaxRetirePerCycle;
|
|
}
|
|
|
|
assert(AvailableSlots && "Invalid reorder buffer size!");
|
|
Queue.resize(AvailableSlots);
|
|
}
|
|
|
|
// Reserves a number of slots, and returns a new token.
|
|
unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
|
|
unsigned NumMicroOps) {
|
|
assert(isAvailable(NumMicroOps));
|
|
unsigned NormalizedQuantity =
|
|
std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
|
|
// Zero latency instructions may have zero mOps. Artificially bump this
|
|
// value to 1. Although zero latency instructions don't consume scheduler
|
|
// resources, they still consume one slot in the retire queue.
|
|
NormalizedQuantity = std::max(NormalizedQuantity, 1U);
|
|
unsigned TokenID = NextAvailableSlotIdx;
|
|
Queue[NextAvailableSlotIdx] = {IR, NormalizedQuantity, false};
|
|
NextAvailableSlotIdx += NormalizedQuantity;
|
|
NextAvailableSlotIdx %= Queue.size();
|
|
AvailableSlots -= NormalizedQuantity;
|
|
return TokenID;
|
|
}
|
|
|
|
void RetireControlUnit::cycleEvent() {
|
|
if (isEmpty())
|
|
return;
|
|
|
|
unsigned NumRetired = 0;
|
|
while (!isEmpty()) {
|
|
if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle)
|
|
break;
|
|
RUToken &Current = Queue[CurrentInstructionSlotIdx];
|
|
assert(Current.NumSlots && "Reserved zero slots?");
|
|
assert(Current.IR.isValid() && "Invalid RUToken in the RCU queue.");
|
|
if (!Current.Executed)
|
|
break;
|
|
Owner->notifyInstructionRetired(Current.IR);
|
|
CurrentInstructionSlotIdx += Current.NumSlots;
|
|
CurrentInstructionSlotIdx %= Queue.size();
|
|
AvailableSlots += Current.NumSlots;
|
|
NumRetired++;
|
|
}
|
|
}
|
|
|
|
void RetireControlUnit::onInstructionExecuted(unsigned TokenID) {
|
|
assert(Queue.size() > TokenID);
|
|
assert(Queue[TokenID].Executed == false && Queue[TokenID].IR.isValid());
|
|
Queue[TokenID].Executed = true;
|
|
}
|
|
|
|
#ifndef NDEBUG
|
|
void RetireControlUnit::dump() const {
|
|
dbgs() << "Retire Unit: { Total Slots=" << Queue.size()
|
|
<< ", Available Slots=" << AvailableSlots << " }\n";
|
|
}
|
|
#endif
|
|
|
|
} // namespace mca
|