[llvm] r332493 - [llvm-mca] Move the RegisterFile class into its own translation unit. NFC
Matt Davis via llvm-commits
llvm-commits at lists.llvm.org
Wed May 16 10:07:08 PDT 2018
Author: mattd
Date: Wed May 16 10:07:08 2018
New Revision: 332493
URL: http://llvm.org/viewvc/llvm-project?rev=332493&view=rev
Log:
[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
Added:
llvm/trunk/tools/llvm-mca/RegisterFile.cpp
llvm/trunk/tools/llvm-mca/RegisterFile.h
Modified:
llvm/trunk/tools/llvm-mca/CMakeLists.txt
llvm/trunk/tools/llvm-mca/Dispatch.cpp
llvm/trunk/tools/llvm-mca/Dispatch.h
Modified: llvm/trunk/tools/llvm-mca/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/CMakeLists.txt?rev=332493&r1=332492&r2=332493&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/CMakeLists.txt (original)
+++ llvm/trunk/tools/llvm-mca/CMakeLists.txt Wed May 16 10:07:08 2018
@@ -23,6 +23,7 @@ add_llvm_tool(llvm-mca
InstructionTables.cpp
LSUnit.cpp
llvm-mca.cpp
+ RegisterFile.cpp
RegisterFileStatistics.cpp
ResourcePressureView.cpp
RetireControlUnit.cpp
Modified: llvm/trunk/tools/llvm-mca/Dispatch.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Dispatch.cpp?rev=332493&r1=332492&r2=332493&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Dispatch.cpp (original)
+++ llvm/trunk/tools/llvm-mca/Dispatch.cpp Wed May 16 10:07:08 2018
@@ -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 @@ using namespace llvm;
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');
Modified: llvm/trunk/tools/llvm-mca/Dispatch.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Dispatch.h?rev=332493&r1=332492&r2=332493&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Dispatch.h (original)
+++ llvm/trunk/tools/llvm-mca/Dispatch.h Wed May 16 10:07:08 2018
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
/// \file
///
-/// This file implements classes that are used to model register files,
-/// reorder buffers and the hardware dispatch logic.
+/// This file implements classes that are used to model reorder buffers and
+/// the hardware dispatch logic.
///
//===----------------------------------------------------------------------===//
@@ -17,149 +17,17 @@
#define LLVM_TOOLS_LLVM_MCA_DISPATCH_H
#include "Instruction.h"
+#include "RegisterFile.h"
#include "RetireControlUnit.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include <map>
namespace mca {
class WriteState;
-class DispatchUnit;
class Scheduler;
class Backend;
-/// Manages hardware register files, and tracks data dependencies
-/// between registers.
-class RegisterFile {
- const llvm::MCRegisterInfo &MRI;
-
- // Each register file is described by an instance of RegisterMappingTracker.
- // RegisterMappingTracker tracks the number of register mappings dynamically
- // allocated during the execution.
- struct RegisterMappingTracker {
- // Total number of register mappings that are available for register
- // renaming. A value of zero for this field means: this register file has
- // an unbounded number of registers.
- const unsigned TotalMappings;
- // Number of mappings that are currently in use.
- unsigned NumUsedMappings;
-
- RegisterMappingTracker(unsigned NumMappings)
- : TotalMappings(NumMappings), NumUsedMappings(0) {}
- };
-
- // This is where information related to the various register files is kept.
- // This set always contains at least one register file at index #0. That
- // register file "sees" all the physical registers declared by the target, and
- // (by default) it allows an unbounded number of mappings.
- // Users can limit the number of mappings that can be created by register file
- // #0 through the command line flag `-register-file-size`.
- llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles;
-
- // This pair is used to identify the owner of a physical register, as well as
- // the cost of using that register file.
- using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
-
- // RegisterMapping objects are mainly used to track physical register
- // definitions. A WriteState object describes a register definition, and it is
- // used to track RAW dependencies (see Instruction.h). A RegisterMapping
- // object also specifies the set of register files. The mapping between
- // physreg and register files is done using a "register file mask".
- //
- // A register file index identifies a user defined register file.
- // There is one index per RegisterMappingTracker, and index #0 is reserved to
- // the default unified register file.
- //
- // This implementation does not allow overlapping register files. The only
- // register file that is allowed to overlap with other register files is
- // register file #0.
- using RegisterMapping = std::pair<WriteState *, IndexPlusCostPairTy>;
-
- // This map contains one entry for each physical register defined by the
- // processor scheduling model.
- std::vector<RegisterMapping> RegisterMappings;
-
- // This method creates a new RegisterMappingTracker for a register file that
- // contains all the physical registers specified by the register classes in
- // the 'RegisterClasses' set.
- //
- // The long term goal is to let scheduling models optionally describe register
- // files via tablegen definitions. This is still a work in progress.
- // For example, here is how a tablegen definition for a x86 FP register file
- // that features AVX might look like:
- //
- // def FPRegisterFile : RegisterFile<[VR128RegClass, VR256RegClass], 60>
- //
- // Here FPRegisterFile contains all the registers defined by register class
- // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
- // registers which can be used for register renaming purpose.
- //
- // The list of register classes is then converted by the tablegen backend into
- // a list of register class indices. That list, along with the number of
- // available mappings, is then used to create a new RegisterMappingTracker.
- void
- addRegisterFile(llvm::ArrayRef<llvm::MCRegisterCostEntry> RegisterClasses,
- unsigned NumPhysRegs);
-
- // Allocates register mappings in register file specified by the
- // IndexPlusCostPairTy object. This method is called from addRegisterMapping.
- void allocatePhysRegs(IndexPlusCostPairTy IPC,
- llvm::MutableArrayRef<unsigned> UsedPhysRegs);
-
- // Removes a previously allocated mapping from the register file referenced
- // by the IndexPlusCostPairTy object. This method is called from
- // invalidateRegisterMapping.
- void freePhysRegs(IndexPlusCostPairTy IPC,
- llvm::MutableArrayRef<unsigned> FreedPhysRegs);
-
- // Create an instance of RegisterMappingTracker for every register file
- // specified by the processor model.
- // If no register file is specified, then this method creates a single
- // register file with an unbounded number of registers.
- void initialize(const llvm::MCSchedModel &SM, unsigned NumRegs);
-
-public:
- RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri,
- unsigned NumRegs = 0)
- : MRI(mri), RegisterMappings(mri.getNumRegs(), {nullptr, {0, 0}}) {
- initialize(SM, NumRegs);
- }
-
- // This method updates the data dependency graph by inserting a new register
- // definition. This method is also responsible for updating the number of used
- // physical registers in the register file(s). The number of physical
- // registers is updated only if flag ShouldAllocatePhysRegs is set.
- void addRegisterWrite(WriteState &WS,
- llvm::MutableArrayRef<unsigned> UsedPhysRegs,
- bool ShouldAllocatePhysRegs = true);
-
- // Updates the data dependency graph by removing a write. It also updates the
- // internal state of the register file(s) by freeing physical registers.
- // The number of physical registers is updated only if flag ShouldFreePhysRegs
- // is set.
- void removeRegisterWrite(const WriteState &WS,
- llvm::MutableArrayRef<unsigned> FreedPhysRegs,
- bool ShouldFreePhysRegs = true);
-
- // Checks if there are enough microarchitectural registers in the register
- // files. Returns a "response mask" where each bit is the response from a
- // RegisterMappingTracker.
- // For example: if all register files are available, then the response mask
- // is a bitmask of all zeroes. If Instead register file #1 is not available,
- // then the response mask is 0b10.
- unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const;
- void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes,
- unsigned RegID) const;
- void updateOnRead(ReadState &RS, unsigned RegID);
-
- unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
-
-#ifndef NDEBUG
- void dump() const;
-#endif
-};
-
// Implements the hardware dispatch logic.
//
// This class is responsible for the dispatch stage, in which instructions are
Added: llvm/trunk/tools/llvm-mca/RegisterFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/RegisterFile.cpp?rev=332493&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-mca/RegisterFile.cpp (added)
+++ llvm/trunk/tools/llvm-mca/RegisterFile.cpp Wed May 16 10:07:08 2018
@@ -0,0 +1,261 @@
+//===--------------------- RegisterFile.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 defines a register mapping file class. This class is responsible
+/// for managing hardware register files and the tracking of data dependencies
+/// between registers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "RegisterFile.h"
+#include "Instruction.h"
+#include "llvm/Support/Debug.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "llvm-mca"
+
+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
+
+} // namespace mca
Added: llvm/trunk/tools/llvm-mca/RegisterFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/RegisterFile.h?rev=332493&view=auto
==============================================================================
--- llvm/trunk/tools/llvm-mca/RegisterFile.h (added)
+++ llvm/trunk/tools/llvm-mca/RegisterFile.h Wed May 16 10:07:08 2018
@@ -0,0 +1,162 @@
+//===--------------------- RegisterFile.h -----------------------*- 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 defines a register mapping file class. This class is responsible
+/// for managing hardware register files and the tracking of data dependencies
+/// between registers.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
+#define LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSchedule.h"
+
+namespace mca {
+
+class ReadState;
+class WriteState;
+
+/// Manages hardware register files, and tracks data dependencies
+/// between registers.
+class RegisterFile {
+ const llvm::MCRegisterInfo &MRI;
+
+ // Each register file is described by an instance of RegisterMappingTracker.
+ // RegisterMappingTracker tracks the number of register mappings dynamically
+ // allocated during the execution.
+ struct RegisterMappingTracker {
+ // Total number of register mappings that are available for register
+ // renaming. A value of zero for this field means: this register file has
+ // an unbounded number of registers.
+ const unsigned TotalMappings;
+ // Number of mappings that are currently in use.
+ unsigned NumUsedMappings;
+
+ RegisterMappingTracker(unsigned NumMappings)
+ : TotalMappings(NumMappings), NumUsedMappings(0) {}
+ };
+
+ // This is where information related to the various register files is kept.
+ // This set always contains at least one register file at index #0. That
+ // register file "sees" all the physical registers declared by the target, and
+ // (by default) it allows an unbounded number of mappings.
+ // Users can limit the number of mappings that can be created by register file
+ // #0 through the command line flag `-register-file-size`.
+ llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles;
+
+ // This pair is used to identify the owner of a physical register, as well as
+ // the cost of using that register file.
+ using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
+
+ // RegisterMapping objects are mainly used to track physical register
+ // definitions. A WriteState object describes a register definition, and it is
+ // used to track RAW dependencies (see Instruction.h). A RegisterMapping
+ // object also specifies the set of register files. The mapping between
+ // physreg and register files is done using a "register file mask".
+ //
+ // A register file index identifies a user defined register file.
+ // There is one index per RegisterMappingTracker, and index #0 is reserved to
+ // the default unified register file.
+ //
+ // This implementation does not allow overlapping register files. The only
+ // register file that is allowed to overlap with other register files is
+ // register file #0.
+ using RegisterMapping = std::pair<WriteState *, IndexPlusCostPairTy>;
+
+ // This map contains one entry for each physical register defined by the
+ // processor scheduling model.
+ std::vector<RegisterMapping> RegisterMappings;
+
+ // This method creates a new RegisterMappingTracker for a register file that
+ // contains all the physical registers specified by the register classes in
+ // the 'RegisterClasses' set.
+ //
+ // The long term goal is to let scheduling models optionally describe register
+ // files via tablegen definitions. This is still a work in progress.
+ // For example, here is how a tablegen definition for a x86 FP register file
+ // that features AVX might look like:
+ //
+ // def FPRegisterFile : RegisterFile<[VR128RegClass, VR256RegClass], 60>
+ //
+ // Here FPRegisterFile contains all the registers defined by register class
+ // VR128RegClass and VR256RegClass. FPRegisterFile implements 60
+ // registers which can be used for register renaming purpose.
+ //
+ // The list of register classes is then converted by the tablegen backend into
+ // a list of register class indices. That list, along with the number of
+ // available mappings, is then used to create a new RegisterMappingTracker.
+ void
+ addRegisterFile(llvm::ArrayRef<llvm::MCRegisterCostEntry> RegisterClasses,
+ unsigned NumPhysRegs);
+
+ // Allocates register mappings in register file specified by the
+ // IndexPlusCostPairTy object. This method is called from addRegisterMapping.
+ void allocatePhysRegs(IndexPlusCostPairTy IPC,
+ llvm::MutableArrayRef<unsigned> UsedPhysRegs);
+
+ // Removes a previously allocated mapping from the register file referenced
+ // by the IndexPlusCostPairTy object. This method is called from
+ // invalidateRegisterMapping.
+ void freePhysRegs(IndexPlusCostPairTy IPC,
+ llvm::MutableArrayRef<unsigned> FreedPhysRegs);
+
+ // Create an instance of RegisterMappingTracker for every register file
+ // specified by the processor model.
+ // If no register file is specified, then this method creates a single
+ // register file with an unbounded number of registers.
+ void initialize(const llvm::MCSchedModel &SM, unsigned NumRegs);
+
+public:
+ RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri,
+ unsigned NumRegs = 0)
+ : MRI(mri), RegisterMappings(mri.getNumRegs(), {nullptr, {0, 0}}) {
+ initialize(SM, NumRegs);
+ }
+
+ // This method updates the data dependency graph by inserting a new register
+ // definition. This method is also responsible for updating the number of used
+ // physical registers in the register file(s). The number of physical
+ // registers is updated only if flag ShouldAllocatePhysRegs is set.
+ void addRegisterWrite(WriteState &WS,
+ llvm::MutableArrayRef<unsigned> UsedPhysRegs,
+ bool ShouldAllocatePhysRegs = true);
+
+ // Updates the data dependency graph by removing a write. It also updates the
+ // internal state of the register file(s) by freeing physical registers.
+ // The number of physical registers is updated only if flag ShouldFreePhysRegs
+ // is set.
+ void removeRegisterWrite(const WriteState &WS,
+ llvm::MutableArrayRef<unsigned> FreedPhysRegs,
+ bool ShouldFreePhysRegs = true);
+
+ // Checks if there are enough microarchitectural registers in the register
+ // files. Returns a "response mask" where each bit is the response from a
+ // RegisterMappingTracker.
+ // For example: if all register files are available, then the response mask
+ // is a bitmask of all zeroes. If Instead register file #1 is not available,
+ // then the response mask is 0b10.
+ unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const;
+ void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes,
+ unsigned RegID) const;
+ void updateOnRead(ReadState &RS, unsigned RegID);
+
+ unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+} // namespace mca
+
+#endif // LLVM_TOOLS_LLVM_MCA_REGISTER_FILE_H
More information about the llvm-commits
mailing list