summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-09-28 09:42:06 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-09-28 09:42:06 +0000
commit28ed7674e36a654bd6ed2be47e5504bcfc82e38a (patch)
treee711fab61f2957702aad8e33ce3723b55f9fbe79
parent2d3fd448c5cf5df520ad19479f2616ed2abcbb0d (diff)
[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.
-rw-r--r--llvm/tools/llvm-mca/include/HardwareUnits/RegisterFile.h34
-rw-r--r--llvm/tools/llvm-mca/include/Instruction.h25
-rw-r--r--llvm/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp45
3 files changed, 78 insertions, 26 deletions
diff --git a/llvm/tools/llvm-mca/include/HardwareUnits/RegisterFile.h b/llvm/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
index bae8840438f..7829b42c307 100644
--- a/llvm/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
+++ b/llvm/tools/llvm-mca/include/HardwareUnits/RegisterFile.h
@@ -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.
diff --git a/llvm/tools/llvm-mca/include/Instruction.h b/llvm/tools/llvm-mca/include/Instruction.h
index b6c0f9b8637..cd9a0d69c02 100644
--- a/llvm/tools/llvm-mca/include/Instruction.h
+++ b/llvm/tools/llvm-mca/include/Instruction.h
@@ -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
diff --git a/llvm/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp b/llvm/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
index 47b5153b966..20db2b83036 100644
--- a/llvm/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
+++ b/llvm/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp
@@ -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(WriteRef Write,
// 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(WriteRef Write,
}
}
+ // 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(WriteRef Write,
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(ArrayRef<unsigned> Regs) const {
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) {