[llvm] r343307 - [llvm-mca] Teach how to track zero registers in class RegisterFile.

Andrea Di Biagio via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 28 02:42:07 PDT 2018


Author: adibiagio
Date: Fri Sep 28 02:42:06 2018
New Revision: 343307

URL: http://llvm.org/viewvc/llvm-project?rev=343307&view=rev
Log:
[llvm-mca] Teach how to track zero registers in class RegisterFile.

This change is in preparation for a future work on improving support for
optimizable register moves.  We already know if a write is from a zero-idiom, so
we can propagate that bit of information to the PRF.  We use an APInt mask to
identify registers that are set to zero.

Modified:
    llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
    llvm/trunk/tools/llvm-mca/include/Instruction.h
    llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp

Modified: llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h?rev=343307&r1=343306&r2=343307&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h Fri Sep 28 02:42:06 2018
@@ -19,6 +19,7 @@
 
 #include "HardwareUnits/HardwareUnit.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/APInt.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSchedule.h"
 #include "llvm/Support/Error.h"
@@ -71,20 +72,31 @@ class RegisterFile : public HardwareUnit
   // registers. So, the cost of allocating a YMM register in BtVer2 is 2.
   using IndexPlusCostPairTy = std::pair<unsigned, unsigned>;
 
-  // Struct RegisterRenamingInfo maps registers to register files.
-  // There is a RegisterRenamingInfo object for every register defined by
-  // the target. RegisteRenamingInfo objects are stored into vector
-  // RegisterMappings, and register IDs can be used to reference them.
+  // Struct RegisterRenamingInfo is used to map logical registers to register
+  // files.
+  //
+  // There is a RegisterRenamingInfo object for every logical register defined
+  // by the target. RegisteRenamingInfo objects are stored into vector
+  // `RegisterMappings`, and llvm::MCPhysReg IDs can be used to reference
+  // elements in that vector.
+  //
+  // Each RegisterRenamingInfo is owned by a PRF, and field `IndexPlusCost`
+  // specifies both the owning PRF, as well as the number of physical registers
+  // consumed at register renaming stage.
   struct RegisterRenamingInfo {
     IndexPlusCostPairTy IndexPlusCost;
     llvm::MCPhysReg RenameAs;
+    RegisterRenamingInfo()
+        : IndexPlusCost(std::make_pair(0U, 1U)), RenameAs(0U) {}
   };
 
   // RegisterMapping objects are mainly used to track physical register
-  // definitions. There is a RegisterMapping for every register defined by the
-  // Target. For each register, a RegisterMapping pair contains a descriptor of
-  // the last register write (in the form of a WriteRef object), as well as a
-  // RegisterRenamingInfo to quickly identify owning register files.
+  // definitions and resolve data dependencies.
+  //
+  // Every register declared by the Target is associated with an instance of
+  // RegisterMapping. RegisterMapping objects keep track of writes to a logical
+  // register.  That information is used by class RegisterFile to resolve data
+  // dependencies, and correctly set latencies for register uses.
   //
   // This implementation does not allow overlapping register files. The only
   // register file that is allowed to overlap with other register files is
@@ -92,9 +104,13 @@ class RegisterFile : public HardwareUnit
   // at most one register file.
   using RegisterMapping = std::pair<WriteRef, RegisterRenamingInfo>;
 
-  // This map contains one entry for each register defined by the target.
+  // There is one entry per each register defined by the target.
   std::vector<RegisterMapping> RegisterMappings;
 
+  // Used to track zero registers. There is one bit for each register defined by
+  // the target. Bits are set for registers that are known to be zero.
+  llvm::APInt ZeroRegisters;
+
   // This method creates a new register file descriptor.
   // The new register file owns all of the registers declared by register
   // classes in the 'RegisterClasses' set.

Modified: llvm/trunk/tools/llvm-mca/include/Instruction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/include/Instruction.h?rev=343307&r1=343306&r2=343307&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Instruction.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Instruction.h Fri Sep 28 02:42:06 2018
@@ -141,6 +141,9 @@ public:
   unsigned getNumUsers() const { return Users.size() + NumWriteUsers; }
   bool clearsSuperRegisters() const { return ClearsSuperRegs; }
   bool isWriteZero() const { return WritesZero; }
+  bool isExecuted() const {
+    return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
+  }
 
   const WriteState *getDependentWrite() const { return DependentWrite; }
   void setDependentWrite(WriteState *Other) {
@@ -351,9 +354,8 @@ public:
   int getCyclesLeft() const { return CyclesLeft; }
 
   bool hasDependentUsers() const {
-    return llvm::any_of(Defs, [](const UniqueDef &Def) {
-      return Def->getNumUsers() > 0;
-    });
+    return llvm::any_of(
+        Defs, [](const UniqueDef &Def) { return Def->getNumUsers() > 0; });
   }
 
   unsigned getNumUsers() const {
@@ -444,11 +446,22 @@ public:
   unsigned getSourceIndex() const { return Data.first; }
   const WriteState *getWriteState() const { return Data.second; }
   WriteState *getWriteState() { return Data.second; }
-  void invalidate() { Data = std::make_pair(INVALID_IID, nullptr); }
+  void invalidate() { Data.second = nullptr; }
+  bool isWriteZero() const {
+    assert(isValid() && "Invalid null WriteState found!");
+    return getWriteState()->isWriteZero();
+  }
 
-  bool isValid() const {
-    return Data.first != INVALID_IID && Data.second != nullptr;
+  /// Returns true if this register write has been executed, and the new
+  /// register value is therefore available to users.
+  bool isAvailable() const {
+    if (getSourceIndex() == INVALID_IID)
+      return false;
+    const WriteState *WS = getWriteState();
+    return !WS || WS->isExecuted();
   }
+
+  bool isValid() const { return Data.first != INVALID_IID && Data.second; }
   bool operator==(const WriteRef &Other) const { return Data == Other.Data; }
 
 #ifndef NDEBUG

Modified: llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp?rev=343307&r1=343306&r2=343307&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp Fri Sep 28 02:42:06 2018
@@ -26,8 +26,9 @@ namespace mca {
 
 RegisterFile::RegisterFile(const llvm::MCSchedModel &SM,
                            const llvm::MCRegisterInfo &mri, unsigned NumRegs)
-    : MRI(mri), RegisterMappings(mri.getNumRegs(),
-                                 {WriteRef(), {IndexPlusCostPairTy(0, 1), 0}}) {
+    : MRI(mri),
+      RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
+      ZeroRegisters(mri.getNumRegs(), false) {
   initialize(SM, NumRegs);
 }
 
@@ -162,8 +163,10 @@ void RegisterFile::addRegisterWrite(Writ
   // a false dependency on RenameAs. The only exception is for when the write
   // implicitly clears the upper portion of the underlying register.
   // If a write clears its super-registers, then it is renamed as `RenameAs`.
-  bool ShouldAllocatePhysRegs = !WS.isWriteZero();
+  bool IsWriteZero = WS.isWriteZero();
+  bool ShouldAllocatePhysRegs = !IsWriteZero;
   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
+
   if (RRI.RenameAs && RRI.RenameAs != RegID) {
     RegID = RRI.RenameAs;
     WriteRef &OtherWrite = RegisterMappings[RegID].first;
@@ -182,6 +185,19 @@ void RegisterFile::addRegisterWrite(Writ
     }
   }
 
+  // Update zero registers.
+  unsigned ZeroRegisterID =
+      WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
+  if (IsWriteZero) {
+    ZeroRegisters.setBit(ZeroRegisterID);
+    for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
+      ZeroRegisters.setBit(*I);
+  } else {
+    ZeroRegisters.clearBit(ZeroRegisterID);
+    for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
+      ZeroRegisters.clearBit(*I);
+  }
+
   // Update the mapping for register RegID including its sub-registers.
   RegisterMappings[RegID].first = Write;
   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
@@ -196,8 +212,13 @@ void RegisterFile::addRegisterWrite(Writ
   if (!WS.clearsSuperRegisters())
     return;
 
-  for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
+  for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
     RegisterMappings[*I].first = Write;
+    if (IsWriteZero)
+      ZeroRegisters.setBit(*I);
+    else
+      ZeroRegisters.clearBit(*I);
+  }
 }
 
 void RegisterFile::removeRegisterWrite(
@@ -327,14 +348,16 @@ unsigned RegisterFile::isAvailable(Array
 void RegisterFile::dump() const {
   for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
     const RegisterMapping &RM = RegisterMappings[I];
-    if (!RM.first.getWriteState())
-      continue;
     const RegisterRenamingInfo &RRI = RM.second;
-    dbgs() << MRI.getName(I) << ", " << I << ", PRF=" << RRI.IndexPlusCost.first
-           << ", Cost=" << RRI.IndexPlusCost.second
-           << ", RenameAs=" << RRI.RenameAs << ", ";
-    RM.first.dump();
-    dbgs() << '\n';
+    if (ZeroRegisters[I]) {
+      dbgs() << MRI.getName(I) << ", " << I
+             << ", PRF=" << RRI.IndexPlusCost.first
+             << ", Cost=" << RRI.IndexPlusCost.second
+             << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
+             << ",";
+      RM.first.dump();
+      dbgs() << '\n';
+    }
   }
 
   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {




More information about the llvm-commits mailing list