[llvm-mca] Move the logic that computes the register file usage to the BackendStatist...
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Wed, 21 Mar 2018 18:11:05 +0000 (18:11 +0000)
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>
Wed, 21 Mar 2018 18:11:05 +0000 (18:11 +0000)
With this patch, the "instruction dispatched" event now provides information
related to the number of microarchitectural registers used in each register
file. Similarly, the "instruction retired" event is now able to tell how may
registers are freed in each register file.

Currently, the BackendStatistics view is the only consumer of register
usage/pressure information. BackendStatistics uses that info to print out a few
general statistics (i.e. max number of mappings used; total mapping created).
Before this patch, the BackendStatistics was forced to query the Backend to
obtain the register pressure information.

This helps removes that dependency. Now views are completely independent from
the Backend.  As a consequence, it should be easier to address PR36663 and
further modularize the pipeline.

Added a couple of test cases in the BtVer2 specific directory.

llvm-svn: 328129

llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s [new file with mode: 0644]
llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s [new file with mode: 0644]
llvm/tools/llvm-mca/Backend.h
llvm/tools/llvm-mca/BackendStatistics.cpp
llvm/tools/llvm-mca/BackendStatistics.h
llvm/tools/llvm-mca/Dispatch.cpp
llvm/tools/llvm-mca/Dispatch.h
llvm/tools/llvm-mca/HWEventListener.h
llvm/tools/llvm-mca/llvm-mca.cpp

diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-1.s
new file mode 100644 (file)
index 0000000..390201e
--- /dev/null
@@ -0,0 +1,29 @@
+# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=5 -verbose -timeline < %s | FileCheck %s
+
+vaddps %xmm0, %xmm0, %xmm0
+vmulps %xmm0, %xmm0, %xmm0
+
+# CHECK: Iterations:     5
+# CHECK-NEXT: Instructions:   10
+
+# CHECK:      Dynamic Dispatch Stall Cycles:
+# CHECK-NEXT: RAT     - Register unavailable:                      0
+
+# CHECK:      Register File statistics.
+# CHECK-NEXT: Register File #0
+# CHECK-NEXT:   Total number of mappings created: 10
+# CHECK-NEXT:   Max number of mappings used:      10
+
+# CHECK: Timeline view:
+# CHECK-NEXT:                    0123456789        
+# CHECK-NEXT: Index    0123456789          01234567
+# CHECK:      [0,0]    DeeeER    .    .    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [0,1]    D===eeER  .    .    .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [1,0]    .D====eeeER    .    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [1,1]    .D=======eeER  .    .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [2,0]    . D========eeeER    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [2,1]    . D===========eeER  .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [3,0]    .  D============eeeER    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [3,1]    .  D===============eeER  . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [4,0]    .   D================eeeER .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [4,1]    .   D===================eeER    vmulps  %xmm0, %xmm0, %xmm0
diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s b/llvm/test/tools/llvm-mca/X86/BtVer2/register-files-2.s
new file mode 100644 (file)
index 0000000..d5c3fd7
--- /dev/null
@@ -0,0 +1,29 @@
+# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -register-file-size=5 -iterations=5 -verbose -timeline < %s | FileCheck %s
+
+vaddps %xmm0, %xmm0, %xmm0
+vmulps %xmm0, %xmm0, %xmm0
+
+# CHECK: Iterations:     5
+# CHECK-NEXT: Instructions:   10
+
+# CHECK:      Dynamic Dispatch Stall Cycles:
+# CHECK-NEXT: RAT     - Register unavailable:                      13
+
+# CHECK:      Register File statistics.
+# CHECK-NEXT: Register File #0
+# CHECK-NEXT:   Total number of mappings created: 10
+# CHECK-NEXT:   Max number of mappings used:      5
+
+# CHECK:      Timeline view:
+# CHECK-NEXT:                    0123456789        
+# CHECK-NEXT: Index    0123456789          01234567
+# CHECK:      [0,0]    DeeeER    .    .    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [0,1]    D===eeER  .    .    .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [1,0]    .D====eeeER    .    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [1,1]    .D=======eeER  .    .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [2,0]    . D========eeeER    .    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [2,1]    .    D========eeER  .    . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [3,0]    .    . D========eeeER    . .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [3,1]    .    .    D========eeER  . .    vmulps  %xmm0, %xmm0, %xmm0
+# CHECK:      [4,0]    .    .    . D========eeeER .    vaddps  %xmm0, %xmm0, %xmm0
+# CHECK-NEXT: [4,1]    .    .    .    D========eeER    vmulps  %xmm0, %xmm0, %xmm0
index 513904bf6c648ba2d0f0ba94e1b11e7cd0b88b3a..027850ecba5406e1517dab3d0c7888a31fc631f7 100644 (file)
@@ -88,12 +88,6 @@ public:
     return *It->second;
   }
   void eraseInstruction(unsigned Index) { Instructions.erase(Index); }
-  unsigned getTotalRegisterMappingsCreated() const {
-    return DU->getTotalRegisterMappingsCreated();
-  }
-  unsigned getMaxUsedRegisterMappings() const {
-    return DU->getMaxUsedRegisterMappings();
-  }
 
   void addEventListener(HWEventListener *Listener);
   void notifyCycleBegin(unsigned Cycle);
index 64b8be11e4d6d3f4e3ce27f4c7501085385ba061..c5425509064efe3cc87af246ab55145affa7fa5d 100644 (file)
@@ -22,17 +22,32 @@ namespace mca {
 
 void BackendStatistics::onInstructionEvent(const HWInstructionEvent &Event) {
   switch (Event.Type) {
-  case HWInstructionEvent::Retired:
+  default:
+    break;
+  case HWInstructionEvent::Retired: {
+    const auto &RE = static_cast<const HWInstructionRetiredEvent &>(Event);
+    for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I)
+      RegisterFiles[I].CurrentlyUsedMappings -= RE.FreedPhysRegs[I];
+
     ++NumRetired;
     break;
+  }
   case HWInstructionEvent::Issued:
     ++NumIssued;
     break;
-  case HWInstructionEvent::Dispatched:
+  case HWInstructionEvent::Dispatched: {
+    const auto &DE = static_cast<const HWInstructionDispatchedEvent &>(Event);
+    for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) {
+      RegisterFileUsage &RFU = RegisterFiles[I];
+      unsigned NumUsedPhysRegs = DE.UsedPhysRegs[I];
+      RFU.CurrentlyUsedMappings += NumUsedPhysRegs;
+      RFU.TotalMappings += NumUsedPhysRegs;
+      RFU.MaxUsedMappings =
+          std::max(RFU.MaxUsedMappings, RFU.CurrentlyUsedMappings);
+    }
+
     ++NumDispatched;
-    break;
-  default:
-    break;
+  }
   }
 }
 
@@ -115,15 +130,19 @@ void BackendStatistics::printSchedulerStatistics(llvm::raw_ostream &OS) const {
   OS << Buffer;
 }
 
-void BackendStatistics::printRATStatistics(raw_ostream &OS,
-                                           unsigned TotalMappings,
-                                           unsigned MaxUsedMappings) const {
+void BackendStatistics::printRATStatistics(raw_ostream &OS) const {
   std::string Buffer;
   raw_string_ostream TempStream(Buffer);
-  TempStream << "\n\nRegister Alias Table:";
-  TempStream << "\nTotal number of mappings created: " << TotalMappings;
-  TempStream << "\nMax number of mappings used:      " << MaxUsedMappings
-             << '\n';
+
+  TempStream << "\n\nRegister File statistics.";
+  for (unsigned I = 0, E = RegisterFiles.size(); I < E; ++I) {
+    const RegisterFileUsage &RFU = RegisterFiles[I];
+    TempStream << "\nRegister File #" << I;
+    TempStream << "\n  Total number of mappings created: " << RFU.TotalMappings;
+    TempStream << "\n  Max number of mappings used:      "
+               << RFU.MaxUsedMappings;
+  }
+
   TempStream.flush();
   OS << Buffer;
 }
index 77bd089196c1f1da850dc9f5e1c38d9083604519..aff3bdeb736bb493ebf890bd40701c41f07df1da 100644 (file)
@@ -67,8 +67,6 @@
 namespace mca {
 
 class BackendStatistics : public View {
-  // TODO: remove the dependency from Backend.
-  const Backend &B;
   const llvm::MCSubtargetInfo &STI;
 
   using Histogram = std::map<unsigned, unsigned>;
@@ -105,13 +103,22 @@ class BackendStatistics : public View {
     NumRetired = 0;
   }
 
+  // Used to track the number of physical registers used in a register file.
+  struct RegisterFileUsage {
+    unsigned TotalMappings;
+    unsigned MaxUsedMappings;
+    unsigned CurrentlyUsedMappings;
+  };
+
+  // There is one entry for each register file implemented by the processor.
+  llvm::SmallVector<RegisterFileUsage, 4> RegisterFiles;
+
   void printRetireUnitStatistics(llvm::raw_ostream &OS) const;
   void printDispatchUnitStatistics(llvm::raw_ostream &OS) const;
   void printSchedulerStatistics(llvm::raw_ostream &OS) const;
 
   void printDispatchStalls(llvm::raw_ostream &OS) const;
-  void printRATStatistics(llvm::raw_ostream &OS, unsigned Mappings,
-                          unsigned MaxUsedMappings) const;
+  void printRATStatistics(llvm::raw_ostream &OS) const;
   void printRCUStatistics(llvm::raw_ostream &OS, const Histogram &Histogram,
                           unsigned Cycles) const;
   void printDispatchUnitUsage(llvm::raw_ostream &OS, const Histogram &Stats,
@@ -122,9 +129,12 @@ class BackendStatistics : public View {
                            const llvm::MCSchedModel &SM) const;
 
 public:
-  BackendStatistics(const Backend &backend, const llvm::MCSubtargetInfo &sti)
-      : B(backend), STI(sti), NumDispatched(0), NumIssued(0), NumRetired(0),
-        NumCycles(0), HWStalls(HWStallEvent::LastGenericEvent) {}
+  BackendStatistics(const llvm::MCSubtargetInfo &sti)
+      : STI(sti), NumDispatched(0), NumIssued(0), NumRetired(0),
+        NumCycles(0), HWStalls(HWStallEvent::LastGenericEvent),
+        // TODO: The view currently assumes a single register file. This will
+        // change in future.
+        RegisterFiles(1) {}
 
   void onInstructionEvent(const HWInstructionEvent &Event) override;
 
@@ -147,12 +157,10 @@ public:
 
   void printView(llvm::raw_ostream &OS) const override {
     printDispatchStalls(OS);
-    printRATStatistics(OS, B.getTotalRegisterMappingsCreated(),
-                       B.getMaxUsedRegisterMappings());
+    printRATStatistics(OS);
     printDispatchUnitStatistics(OS);
     printSchedulerStatistics(OS);
     printRetireUnitStatistics(OS);
-
     printSchedulerUsage(OS, STI.getSchedModel());
   }
 };
index 3614d4d0972f4bc81c693c40cf2de47dacd1f08a..36f1bc3b716dfff80c4846ebfcf8e0fc7a92278d 100644 (file)
@@ -45,7 +45,8 @@ void RegisterFile::addRegisterFile(ArrayRef<unsigned> RegisterClasses,
   }
 }
 
-void RegisterFile::createNewMappings(unsigned RegisterFileMask) {
+void RegisterFile::createNewMappings(unsigned RegisterFileMask,
+                                     MutableArrayRef<unsigned> UsedPhysRegs) {
   assert(RegisterFileMask && "RegisterFileMask cannot be zero!");
   // Notify each register file that contains RegID.
   do {
@@ -53,13 +54,13 @@ void RegisterFile::createNewMappings(unsigned RegisterFileMask) {
     unsigned RegisterFileIndex = llvm::countTrailingZeros(NextRegisterFile);
     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
     RMT.NumUsedMappings++;
-    RMT.MaxUsedMappings = std::max(RMT.MaxUsedMappings, RMT.NumUsedMappings);
-    RMT.TotalMappingsCreated++;
+    UsedPhysRegs[RegisterFileIndex]++;
     RegisterFileMask ^= NextRegisterFile;
   } while (RegisterFileMask);
 }
 
-void RegisterFile::removeMappings(unsigned RegisterFileMask) {
+void RegisterFile::removeMappings(unsigned RegisterFileMask,
+                                  MutableArrayRef<unsigned> FreedPhysRegs) {
   assert(RegisterFileMask && "RegisterFileMask cannot be zero!");
   // Notify each register file that contains RegID.
   do {
@@ -68,11 +69,13 @@ void RegisterFile::removeMappings(unsigned RegisterFileMask) {
     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
     assert(RMT.NumUsedMappings);
     RMT.NumUsedMappings--;
+    FreedPhysRegs[RegisterFileIndex]++;
     RegisterFileMask ^= NextRegisterFile;
   } while (RegisterFileMask);
 }
 
-void RegisterFile::addRegisterMapping(WriteState &WS) {
+void RegisterFile::addRegisterMapping(WriteState &WS,
+                                      MutableArrayRef<unsigned> UsedPhysRegs) {
   unsigned RegID = WS.getRegisterID();
   assert(RegID && "Adding an invalid register definition?");
 
@@ -81,7 +84,8 @@ void RegisterFile::addRegisterMapping(WriteState &WS) {
   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
     RegisterMappings[*I].first = &WS;
 
-  createNewMappings(Mapping.second);
+  createNewMappings(Mapping.second, UsedPhysRegs);
+
   // If this is a partial update, then we are done.
   if (!WS.fullyUpdatesSuperRegs())
     return;
@@ -90,7 +94,8 @@ void RegisterFile::addRegisterMapping(WriteState &WS) {
     RegisterMappings[*I].first = &WS;
 }
 
-void RegisterFile::invalidateRegisterMapping(const WriteState &WS) {
+void RegisterFile::invalidateRegisterMapping(
+    const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
   unsigned RegID = WS.getRegisterID();
   bool ShouldInvalidateSuperRegs = WS.fullyUpdatesSuperRegs();
 
@@ -102,7 +107,7 @@ void RegisterFile::invalidateRegisterMapping(const WriteState &WS) {
   if (!Mapping.first)
     return;
 
-  removeMappings(Mapping.second);
+  removeMappings(Mapping.second, FreedPhysRegs);
 
   if (Mapping.first == &WS)
     Mapping.first = nullptr;
@@ -196,8 +201,6 @@ void RegisterFile::dump() const {
     dbgs() << "Register File #" << I;
     const RegisterMappingTracker &RMT = RegisterFiles[I];
     dbgs() << "\n  TotalMappings:        " << RMT.TotalMappings
-           << "\n  TotalMappingsCreated: " << RMT.TotalMappingsCreated
-           << "\n  MaxUsedMappings:      " << RMT.MaxUsedMappings
            << "\n  NumUsedMappings:      " << RMT.NumUsedMappings << '\n';
   }
 }
@@ -220,21 +223,20 @@ unsigned RetireControlUnit::reserveSlot(unsigned Index, unsigned NumMicroOps) {
   return TokenID;
 }
 
-void DispatchUnit::notifyInstructionDispatched(unsigned Index) {
+void DispatchUnit::notifyInstructionDispatched(
+    unsigned Index, ArrayRef<unsigned> UsedRegs) {
   DEBUG(dbgs() << "[E] Instruction Dispatched: " << Index << '\n');
-  Owner->notifyInstructionEvent(
-      HWInstructionEvent(HWInstructionEvent::Dispatched, Index));
+  Owner->notifyInstructionEvent(HWInstructionDispatchedEvent(Index, UsedRegs));
 }
 
 void DispatchUnit::notifyInstructionRetired(unsigned Index) {
   DEBUG(dbgs() << "[E] Instruction Retired: " << Index << '\n');
-  Owner->notifyInstructionEvent(
-      HWInstructionEvent(HWInstructionEvent::Retired, Index));
-
   const Instruction &IS = Owner->getInstruction(Index);
+  SmallVector<unsigned, 4> FreedRegs(RAT->getNumRegisterFiles());
   for (const std::unique_ptr<WriteState> &WS : IS.getDefs())
-    RAT->invalidateRegisterMapping(*WS.get());
+    RAT->invalidateRegisterMapping(*WS.get(), FreedRegs);
 
+  Owner->notifyInstructionEvent(HWInstructionRetiredEvent(Index, FreedRegs));
   Owner->eraseInstruction(Index);
 }
 
@@ -364,8 +366,9 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
     updateRAWDependencies(*RS, STI);
 
   // Allocate new mappings.
+  SmallVector<unsigned, 4> RegisterFiles(RAT->getNumRegisterFiles());
   for (std::unique_ptr<WriteState> &WS : NewInst->getDefs())
-    RAT->addRegisterMapping(*WS);
+    RAT->addRegisterMapping(*WS, RegisterFiles);
 
   // Set the cycles left before the write-back stage.
   const InstrDesc &D = NewInst->getDesc();
@@ -374,7 +377,7 @@ unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
   // Reserve slots in the RCU.
   unsigned RCUTokenID = RCU->reserveSlot(IID, NumMicroOps);
   NewInst->setRCUTokenID(RCUTokenID);
-  notifyInstructionDispatched(IID);
+  notifyInstructionDispatched(IID, RegisterFiles);
 
   SC->scheduleInstruction(IID, *NewInst);
   return RCUTokenID;
index ceb36138114359698e979820785e9f98c1ac3cc6..c1093fa73ba9cd769afedf65f26eb9b446d1a1cb 100644 (file)
@@ -43,14 +43,9 @@ class RegisterFile {
     const unsigned TotalMappings;
     // Number of mappings that are currently in use.
     unsigned NumUsedMappings;
-    // Maximum number of register mappings used.
-    unsigned MaxUsedMappings;
-    // Total number of mappings allocated during the entire execution.
-    unsigned TotalMappingsCreated;
 
     RegisterMappingTracker(unsigned NumMappings)
-        : TotalMappings(NumMappings), NumUsedMappings(0), MaxUsedMappings(0),
-          TotalMappingsCreated(0) {}
+        : TotalMappings(NumMappings), NumUsedMappings(0) {}
   };
 
   // This is where information related to the various register files is kept.
@@ -105,11 +100,13 @@ class RegisterFile {
 
   // Allocates a new register mapping in every register file specified by the
   // register file mask. This method is called from addRegisterMapping.
-  void createNewMappings(unsigned RegisterFileMask);
+  void createNewMappings(unsigned RegisterFileMask,
+                         llvm::MutableArrayRef<unsigned> UsedPhysRegs);
 
   // Removes a previously allocated mapping from each register file in the
   // RegisterFileMask set. This method is called from invalidateRegisterMapping.
-  void removeMappings(unsigned RegisterFileMask);
+  void removeMappings(unsigned RegisterFileMask,
+                      llvm::MutableArrayRef<unsigned> FreedPhysRegs);
 
 public:
   RegisterFile(const llvm::MCRegisterInfo &mri, unsigned TempRegs = 0)
@@ -121,12 +118,14 @@ public:
   // Creates a new register mapping for RegID.
   // This reserves a microarchitectural register in every register file that
   // contains RegID.
-  void addRegisterMapping(WriteState &WS);
+  void addRegisterMapping(WriteState &WS,
+                          llvm::MutableArrayRef<unsigned> UsedPhysRegs);
 
   // Invalidates register mappings associated to the input WriteState object.
   // This releases previously allocated mappings for the physical register
   // associated to the WriteState.
-  void invalidateRegisterMapping(const WriteState &WS);
+  void invalidateRegisterMapping(const WriteState &WS,
+                                 llvm::MutableArrayRef<unsigned> FreedPhysRegs);
 
   // Checks if there are enough microarchitectural registers in the register
   // files.  Returns a "response mask" where each bit is the response from a
@@ -138,16 +137,7 @@ public:
   void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes,
                      unsigned RegID) const;
   void updateOnRead(ReadState &RS, unsigned RegID);
-  unsigned getMaxUsedRegisterMappings(unsigned RegisterFileIndex) const {
-    assert(RegisterFileIndex < getNumRegisterFiles() &&
-           "Invalid register file index!");
-    return RegisterFiles[RegisterFileIndex].MaxUsedMappings;
-  }
-  unsigned getTotalRegisterMappingsCreated(unsigned RegisterFileIndex) const {
-    assert(RegisterFileIndex < getNumRegisterFiles() &&
-           "Invalid register file index!");
-    return RegisterFiles[RegisterFileIndex].TotalMappingsCreated;
-  }
+
   unsigned getNumRegisterFiles() const { return RegisterFiles.size(); }
 
 #ifndef NDEBUG
@@ -260,7 +250,7 @@ class DispatchUnit {
   bool checkScheduler(unsigned Index, const InstrDesc &Desc);
 
   void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
-  void notifyInstructionDispatched(unsigned IID);
+  void notifyInstructionDispatched(unsigned IID, llvm::ArrayRef<unsigned> UsedPhysRegs);
 
 public:
   DispatchUnit(Backend *B, const llvm::MCRegisterInfo &MRI,
@@ -296,12 +286,6 @@ public:
                      unsigned RegID) const {
     return RAT->collectWrites(Vec, RegID);
   }
-  unsigned getMaxUsedRegisterMappings(unsigned RegFileIndex = 0) const {
-    return RAT->getMaxUsedRegisterMappings(RegFileIndex);
-  }
-  unsigned getTotalRegisterMappingsCreated(unsigned RegFileIndex = 0) const {
-    return RAT->getTotalRegisterMappingsCreated(RegFileIndex);
-  }
 
   void cycleEvent(unsigned Cycle) {
     RCU->cycleEvent();
index 220c3ffed75d6a422a9658126cafa66baee63044..2c3f7f31c7a7dcbd98cc669c523bce26473f2792 100644 (file)
@@ -68,6 +68,26 @@ public:
   llvm::ArrayRef<std::pair<ResourceRef, unsigned>> UsedResources;
 };
 
+class HWInstructionDispatchedEvent : public HWInstructionEvent {
+public:
+  HWInstructionDispatchedEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs)
+      : HWInstructionEvent(HWInstructionEvent::Dispatched, Index),
+        UsedPhysRegs(Regs) {}
+  // Number of physical register allocated for this instruction. There is one
+  // entry per register file.
+  llvm::ArrayRef<unsigned> UsedPhysRegs;
+};
+
+class HWInstructionRetiredEvent : public HWInstructionEvent {
+public:
+  HWInstructionRetiredEvent(unsigned Index, llvm::ArrayRef<unsigned> Regs)
+      : HWInstructionEvent(HWInstructionEvent::Retired, Index),
+        FreedPhysRegs(Regs) {}
+  // Number of register writes that have been architecturally committed. There
+  // is one entry per register file.
+  llvm::ArrayRef<unsigned> FreedPhysRegs;
+};
+
 // A HWStallEvent represents a pipeline stall caused by the lack of hardware
 // resources.
 class HWStallEvent {
index baba4056061f94a05a81d75eef812dcabd2b0c9a..88d33facd2b8401b618f778d57c68750f578c20e 100644 (file)
@@ -330,7 +330,7 @@ int main(int argc, char **argv) {
 
   if (PrintModeVerbose) {
     std::unique_ptr<mca::BackendStatistics> BS =
-        llvm::make_unique<mca::BackendStatistics>(*B, *STI);
+        llvm::make_unique<mca::BackendStatistics>(*STI);
     Printer->addView(std::move(BS));
   }