[llvm-mca] Move the RegisterFile class into its own translation unit. NFC
Summary: This change will help us turn the DispatchUnit into its own stage.
Reviewers: andreadb, RKSimon, courbet
Reviewed By: andreadb, courbet
Subscribers: mgorny, tschuett, gbedwell, llvm-commits
Differential Revision: https://reviews.llvm.org/D46916
llvm-svn: 332493
diff --git a/llvm/tools/llvm-mca/Dispatch.cpp b/llvm/tools/llvm-mca/Dispatch.cpp
index 4153173..9f61034 100644
--- a/llvm/tools/llvm-mca/Dispatch.cpp
+++ b/llvm/tools/llvm-mca/Dispatch.cpp
@@ -8,8 +8,7 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// This file implements methods declared by class RegisterFile and
-/// DispatchUnit.
+/// This file implements methods declared by the DispatchUnit class.
///
//===----------------------------------------------------------------------===//
@@ -25,240 +24,6 @@
namespace mca {
-void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
- // Create a default register file that "sees" all the machine registers
- // declared by the target. The number of physical registers in the default
- // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
- // means: this register file has an unbounded number of physical registers.
- addRegisterFile({} /* all registers */, NumRegs);
- if (!SM.hasExtraProcessorInfo())
- return;
-
- // For each user defined register file, allocate a RegisterMappingTracker
- // object. The size of every register file, as well as the mapping between
- // register files and register classes is specified via tablegen.
- const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
- for (unsigned I = 0, E = Info.NumRegisterFiles; I < E; ++I) {
- const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
- // Skip invalid register files with zero physical registers.
- unsigned Length = RF.NumRegisterCostEntries;
- if (!RF.NumPhysRegs)
- continue;
- // The cost of a register definition is equivalent to the number of
- // physical registers that are allocated at register renaming stage.
- const MCRegisterCostEntry *FirstElt =
- &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
- addRegisterFile(ArrayRef<MCRegisterCostEntry>(FirstElt, Length),
- RF.NumPhysRegs);
- }
-}
-
-void RegisterFile::addRegisterFile(ArrayRef<MCRegisterCostEntry> Entries,
- unsigned NumPhysRegs) {
- // A default register file is always allocated at index #0. That register file
- // is mainly used to count the total number of mappings created by all
- // register files at runtime. Users can limit the number of available physical
- // registers in register file #0 through the command line flag
- // `-register-file-size`.
- unsigned RegisterFileIndex = RegisterFiles.size();
- RegisterFiles.emplace_back(NumPhysRegs);
-
- // Special case where there is no register class identifier in the set.
- // An empty set of register classes means: this register file contains all
- // the physical registers specified by the target.
- if (Entries.empty()) {
- for (std::pair<WriteState *, IndexPlusCostPairTy> &Mapping :
- RegisterMappings)
- Mapping.second = std::make_pair(RegisterFileIndex, 1U);
- return;
- }
-
- // Now update the cost of individual registers.
- for (const MCRegisterCostEntry &RCE : Entries) {
- const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
- for (const MCPhysReg Reg : RC) {
- IndexPlusCostPairTy &Entry = RegisterMappings[Reg].second;
- if (Entry.first) {
- // The only register file that is allowed to overlap is the default
- // register file at index #0. The analysis is inaccurate if register
- // files overlap.
- errs() << "warning: register " << MRI.getName(Reg)
- << " defined in multiple register files.";
- }
- Entry.first = RegisterFileIndex;
- Entry.second = RCE.Cost;
- }
- }
-}
-
-void RegisterFile::allocatePhysRegs(IndexPlusCostPairTy Entry,
- MutableArrayRef<unsigned> UsedPhysRegs) {
- unsigned RegisterFileIndex = Entry.first;
- unsigned Cost = Entry.second;
- if (RegisterFileIndex) {
- RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- RMT.NumUsedMappings += Cost;
- UsedPhysRegs[RegisterFileIndex] += Cost;
- }
-
- // Now update the default register mapping tracker.
- RegisterFiles[0].NumUsedMappings += Cost;
- UsedPhysRegs[0] += Cost;
-}
-
-void RegisterFile::freePhysRegs(IndexPlusCostPairTy Entry,
- MutableArrayRef<unsigned> FreedPhysRegs) {
- unsigned RegisterFileIndex = Entry.first;
- unsigned Cost = Entry.second;
- if (RegisterFileIndex) {
- RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- RMT.NumUsedMappings -= Cost;
- FreedPhysRegs[RegisterFileIndex] += Cost;
- }
-
- // Now update the default register mapping tracker.
- RegisterFiles[0].NumUsedMappings -= Cost;
- FreedPhysRegs[0] += Cost;
-}
-
-void RegisterFile::addRegisterWrite(WriteState &WS,
- MutableArrayRef<unsigned> UsedPhysRegs,
- bool ShouldAllocatePhysRegs) {
- unsigned RegID = WS.getRegisterID();
- assert(RegID && "Adding an invalid register definition?");
-
- RegisterMapping &Mapping = RegisterMappings[RegID];
- Mapping.first = &WS;
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].first = &WS;
-
- // No physical registers are allocated for instructions that are optimized in
- // hardware. For example, zero-latency data-dependency breaking instructions
- // don't consume physical registers.
- if (ShouldAllocatePhysRegs)
- allocatePhysRegs(Mapping.second, UsedPhysRegs);
-
- // If this is a partial update, then we are done.
- if (!WS.fullyUpdatesSuperRegs())
- return;
-
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].first = &WS;
-}
-
-void RegisterFile::removeRegisterWrite(const WriteState &WS,
- MutableArrayRef<unsigned> FreedPhysRegs,
- bool ShouldFreePhysRegs) {
- unsigned RegID = WS.getRegisterID();
- bool ShouldInvalidateSuperRegs = WS.fullyUpdatesSuperRegs();
-
- assert(RegID != 0 && "Invalidating an already invalid register?");
- assert(WS.getCyclesLeft() != -512 &&
- "Invalidating a write of unknown cycles!");
- assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
- RegisterMapping &Mapping = RegisterMappings[RegID];
- if (!Mapping.first)
- return;
-
- if (ShouldFreePhysRegs)
- freePhysRegs(Mapping.second, FreedPhysRegs);
-
- if (Mapping.first == &WS)
- Mapping.first = nullptr;
-
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
- if (RegisterMappings[*I].first == &WS)
- RegisterMappings[*I].first = nullptr;
-
- if (!ShouldInvalidateSuperRegs)
- return;
-
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
- if (RegisterMappings[*I].first == &WS)
- RegisterMappings[*I].first = nullptr;
-}
-
-void RegisterFile::collectWrites(SmallVectorImpl<WriteState *> &Writes,
- unsigned RegID) const {
- assert(RegID && RegID < RegisterMappings.size());
- WriteState *WS = RegisterMappings[RegID].first;
- if (WS) {
- LLVM_DEBUG(dbgs() << "Found a dependent use of RegID=" << RegID << '\n');
- Writes.push_back(WS);
- }
-
- // Handle potential partial register updates.
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WS = RegisterMappings[*I].first;
- if (WS && std::find(Writes.begin(), Writes.end(), WS) == Writes.end()) {
- LLVM_DEBUG(dbgs() << "Found a dependent use of subReg " << *I
- << " (part of " << RegID << ")\n");
- Writes.push_back(WS);
- }
- }
-}
-
-unsigned RegisterFile::isAvailable(ArrayRef<unsigned> Regs) const {
- SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
-
- // Find how many new mappings must be created for each register file.
- for (const unsigned RegID : Regs) {
- const IndexPlusCostPairTy &Entry = RegisterMappings[RegID].second;
- if (Entry.first)
- NumPhysRegs[Entry.first] += Entry.second;
- NumPhysRegs[0] += Entry.second;
- }
-
- unsigned Response = 0;
- for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
- unsigned NumRegs = NumPhysRegs[I];
- if (!NumRegs)
- continue;
-
- const RegisterMappingTracker &RMT = RegisterFiles[I];
- if (!RMT.TotalMappings) {
- // The register file has an unbounded number of microarchitectural
- // registers.
- continue;
- }
-
- if (RMT.TotalMappings < NumRegs) {
- // The current register file is too small. This may occur if the number of
- // microarchitectural registers in register file #0 was changed by the
- // users via flag -reg-file-size. Alternatively, the scheduling model
- // specified a too small number of registers for this register file.
- report_fatal_error(
- "Not enough microarchitectural registers in the register file");
- }
-
- if (RMT.TotalMappings < (RMT.NumUsedMappings + NumRegs))
- Response |= (1U << I);
- }
-
- return Response;
-}
-
-#ifndef NDEBUG
-void RegisterFile::dump() const {
- for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
- const RegisterMapping &RM = RegisterMappings[I];
- dbgs() << MRI.getName(I) << ", " << I << ", Map=" << RM.second.first
- << ", ";
- if (RM.first)
- RM.first->dump();
- else
- dbgs() << "(null)\n";
- }
-
- for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
- dbgs() << "Register File #" << I;
- const RegisterMappingTracker &RMT = RegisterFiles[I];
- dbgs() << "\n TotalMappings: " << RMT.TotalMappings
- << "\n NumUsedMappings: " << RMT.NumUsedMappings << '\n';
- }
-}
-#endif
-
void DispatchUnit::notifyInstructionDispatched(const InstRef &IR,
ArrayRef<unsigned> UsedRegs) {
LLVM_DEBUG(dbgs() << "[E] Instruction Dispatched: " << IR << '\n');