mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[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. llvm-svn: 343307
This commit is contained in:
parent
f7ab544ae0
commit
5d291cb05b
@ -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.
|
||||
|
@ -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); }
|
||||
|
||||
bool isValid() const {
|
||||
return Data.first != INVALID_IID && Data.second != nullptr;
|
||||
void invalidate() { Data.second = nullptr; }
|
||||
bool isWriteZero() const {
|
||||
assert(isValid() && "Invalid null WriteState found!");
|
||||
return getWriteState()->isWriteZero();
|
||||
}
|
||||
|
||||
/// 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
|
||||
|
@ -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,15 +348,17 @@ 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
|
||||
if (ZeroRegisters[I]) {
|
||||
dbgs() << MRI.getName(I) << ", " << I
|
||||
<< ", PRF=" << RRI.IndexPlusCost.first
|
||||
<< ", Cost=" << RRI.IndexPlusCost.second
|
||||
<< ", RenameAs=" << RRI.RenameAs << ", ";
|
||||
<< ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
|
||||
<< ",";
|
||||
RM.first.dump();
|
||||
dbgs() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
|
||||
dbgs() << "Register File #" << I;
|
||||
|
Loading…
Reference in New Issue
Block a user