[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