[llvm] r342483 - [llvm-mca] Add the ability to mark register reads/writes associated with dep-breaking instructions. NFCI
Andrea Di Biagio via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 18 08:00:07 PDT 2018
Author: adibiagio
Date: Tue Sep 18 08:00:06 2018
New Revision: 342483
URL: http://llvm.org/viewvc/llvm-project?rev=342483&view=rev
Log:
[llvm-mca] Add the ability to mark register reads/writes associated with dep-breaking instructions. NFCI
This patch adds two new boolean fields:
- Field `ReadState::IndependentFromDef`.
- Field `WriteState::WritesZero`.
Field `IndependentFromDef` is set for ReadState objects associated with
dependency-breaking instructions. It is used by the simulator when updating data
dependencies between registers.
Field `WritesZero` is set by WriteState objects associated with dependency
breaking zero-idiom instructions. It helps the PRF identify which writes don't
consume any physical registers.
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
llvm/trunk/tools/llvm-mca/lib/InstrBuilder.cpp
llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp
llvm/trunk/tools/llvm-mca/lib/Stages/RetireStage.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=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h (original)
+++ llvm/trunk/tools/llvm-mca/include/HardwareUnits/RegisterFile.h Tue Sep 18 08:00:06 2018
@@ -136,16 +136,15 @@ public:
// This method updates the register mappings inserting a new register
// definition. This method is also responsible for updating the number of
// allocated physical registers in each register file modified by the write.
- // No physical regiser is allocated when flag ShouldAllocatePhysRegs is set.
+ // No physical regiser is allocated if this write is from a zero-idiom.
void addRegisterWrite(WriteRef Write,
- llvm::MutableArrayRef<unsigned> UsedPhysRegs,
- bool ShouldAllocatePhysRegs = true);
+ llvm::MutableArrayRef<unsigned> UsedPhysRegs);
// Removes write \param WS from the register mappings.
// Physical registers may be released to reflect this update.
+ // No registers are released if this write is from a zero-idiom.
void removeRegisterWrite(const WriteState &WS,
- llvm::MutableArrayRef<unsigned> FreedPhysRegs,
- bool ShouldFreePhysRegs = true);
+ llvm::MutableArrayRef<unsigned> FreedPhysRegs);
// Checks if there are enough physical registers in the register files.
// Returns a "response mask" where each bit represents the response from a
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=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/include/Instruction.h (original)
+++ llvm/trunk/tools/llvm-mca/include/Instruction.h Tue Sep 18 08:00:06 2018
@@ -102,6 +102,9 @@ class WriteState {
// super-registers.
bool ClearsSuperRegs;
+ // True if this write is from a dependency breaking zero-idiom instruction.
+ bool WritesZero;
+
// This field is set if this is a partial register write, and it has a false
// dependency on any previous write of the same register (or a portion of it).
// DependentWrite must be able to complete before this write completes, so
@@ -121,10 +124,10 @@ class WriteState {
public:
WriteState(const WriteDescriptor &Desc, unsigned RegID,
- bool clearsSuperRegs = false)
+ bool clearsSuperRegs = false, bool writesZero = false)
: WD(Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID),
- ClearsSuperRegs(clearsSuperRegs), DependentWrite(nullptr),
- NumWriteUsers(0U) {}
+ ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
+ DependentWrite(nullptr), NumWriteUsers(0U) {}
WriteState(const WriteState &Other) = delete;
WriteState &operator=(const WriteState &Other) = delete;
@@ -137,6 +140,7 @@ public:
unsigned getNumUsers() const { return Users.size() + NumWriteUsers; }
bool clearsSuperRegisters() const { return ClearsSuperRegs; }
+ bool isWriteZero() const { return WritesZero; }
const WriteState *getDependentWrite() const { return DependentWrite; }
void setDependentWrite(WriteState *Other) {
@@ -177,11 +181,14 @@ class ReadState {
// This field is set to true only if there are no dependent writes, and
// there are no `CyclesLeft' to wait.
bool IsReady;
+ // True if this register read is from a dependency-breaking instruction.
+ bool IndependentFromDef;
public:
ReadState(const ReadDescriptor &Desc, unsigned RegID)
: RD(Desc), RegisterID(RegID), DependentWrites(0),
- CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true) {}
+ CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true),
+ IndependentFromDef(false) {}
ReadState(const ReadState &Other) = delete;
ReadState &operator=(const ReadState &Other) = delete;
@@ -192,6 +199,9 @@ public:
bool isReady() const { return IsReady; }
bool isImplicitRead() const { return RD.isImplicitRead(); }
+ bool isIndependentFromDef() const { return IndependentFromDef; }
+ void setIndependentFromDef() { IndependentFromDef = true; }
+
void cycleEvent();
void writeStartEvent(unsigned Cycles);
void setDependentWrites(unsigned Writes) {
@@ -281,6 +291,10 @@ struct InstrDesc {
// A zero latency instruction doesn't consume any scheduler resources.
bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
+
+ InstrDesc() = default;
+ InstrDesc(const InstrDesc &Other) = delete;
+ InstrDesc &operator=(const InstrDesc &Other) = delete;
};
/// An instruction propagated through the simulated instruction pipeline.
@@ -309,8 +323,6 @@ class Instruction {
// Retire Unit token ID for this instruction.
unsigned RCUTokenID;
- bool IsDepBreaking;
-
using UniqueDef = std::unique_ptr<WriteState>;
using UniqueUse = std::unique_ptr<ReadState>;
using VecDefs = std::vector<UniqueDef>;
@@ -326,8 +338,7 @@ class Instruction {
public:
Instruction(const InstrDesc &D)
- : Desc(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0),
- IsDepBreaking(false) {}
+ : Desc(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0) {}
Instruction(const Instruction &Other) = delete;
Instruction &operator=(const Instruction &Other) = delete;
@@ -345,9 +356,6 @@ public:
});
}
- bool isDependencyBreaking() const { return IsDepBreaking; }
- void setDependencyBreaking() { IsDepBreaking = true; }
-
unsigned getNumUsers() const {
unsigned NumUsers = 0;
for (const UniqueDef &Def : Defs)
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=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/HardwareUnits/RegisterFile.cpp Tue Sep 18 08:00:06 2018
@@ -139,8 +139,7 @@ void RegisterFile::freePhysRegs(const Re
}
void RegisterFile::addRegisterWrite(WriteRef Write,
- MutableArrayRef<unsigned> UsedPhysRegs,
- bool ShouldAllocatePhysRegs) {
+ MutableArrayRef<unsigned> UsedPhysRegs) {
WriteState &WS = *Write.getWriteState();
unsigned RegID = WS.getRegisterID();
assert(RegID && "Adding an invalid register definition?");
@@ -163,6 +162,7 @@ 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();
const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
if (RRI.RenameAs && RRI.RenameAs != RegID) {
RegID = RRI.RenameAs;
@@ -200,9 +200,8 @@ void RegisterFile::addRegisterWrite(Writ
RegisterMappings[*I].first = Write;
}
-void RegisterFile::removeRegisterWrite(const WriteState &WS,
- MutableArrayRef<unsigned> FreedPhysRegs,
- bool ShouldFreePhysRegs) {
+void RegisterFile::removeRegisterWrite(
+ const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
unsigned RegID = WS.getRegisterID();
assert(RegID != 0 && "Invalidating an already invalid register?");
@@ -210,6 +209,7 @@ void RegisterFile::removeRegisterWrite(c
"Invalidating a write of unknown cycles!");
assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
+ bool ShouldFreePhysRegs = !WS.isWriteZero();
unsigned RenameAs = RegisterMappings[RegID].second.RenameAs;
if (RenameAs && RenameAs != RegID) {
RegID = RenameAs;
Modified: llvm/trunk/tools/llvm-mca/lib/InstrBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/InstrBuilder.cpp?rev=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/InstrBuilder.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/InstrBuilder.cpp Tue Sep 18 08:00:06 2018
@@ -423,6 +423,11 @@ InstrBuilder::createInstruction(const MC
const InstrDesc &D = *DescOrErr;
std::unique_ptr<Instruction> NewIS = llvm::make_unique<Instruction>(D);
+ // Check if this is a dependency breaking instruction.
+ bool IsDepBreaking = MCIA.isDependencyBreaking(STI, MCI);
+ // FIXME: this is a temporary hack to identify zero-idioms.
+ bool IsZeroIdiom = D.isZeroLatency() && IsDepBreaking;
+
// Initialize Reads first.
for (const ReadDescriptor &RD : D.Reads) {
int RegID = -1;
@@ -444,7 +449,11 @@ InstrBuilder::createInstruction(const MC
// Okay, this is a register operand. Create a ReadState for it.
assert(RegID > 0 && "Invalid register ID found!");
- NewIS->getUses().emplace_back(llvm::make_unique<ReadState>(RD, RegID));
+ auto RS = llvm::make_unique<ReadState>(RD, RegID);
+
+ if (IsDepBreaking && !RD.isImplicitRead())
+ RS->setIndependentFromDef();
+ NewIS->getUses().emplace_back(std::move(RS));
}
// Early exit if there are no writes.
@@ -459,10 +468,6 @@ InstrBuilder::createInstruction(const MC
// register writes implicitly clear the upper portion of a super-register.
MCIA.clearsSuperRegisters(MRI, MCI, WriteMask);
- // Check if this is a dependency breaking instruction.
- if (MCIA.isDependencyBreaking(STI, MCI))
- NewIS->setDependencyBreaking();
-
// Initialize writes.
unsigned WriteIndex = 0;
for (const WriteDescriptor &WD : D.Writes) {
@@ -476,7 +481,8 @@ InstrBuilder::createInstruction(const MC
assert(RegID && "Expected a valid register ID!");
NewIS->getDefs().emplace_back(llvm::make_unique<WriteState>(
- WD, RegID, /* ClearsSuperRegs */ WriteMask[WriteIndex]));
+ WD, RegID, /* ClearsSuperRegs */ WriteMask[WriteIndex],
+ /* WritesZero */ IsZeroIdiom));
++WriteIndex;
}
Modified: llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp?rev=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/DispatchStage.cpp Tue Sep 18 08:00:06 2018
@@ -106,21 +106,16 @@ llvm::Error DispatchStage::dispatch(Inst
// instruction. A dependency-breaking instruction is a zero-latency
// instruction that doesn't consume hardware resources.
// An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
- bool IsDependencyBreaking = IS.isDependencyBreaking();
for (std::unique_ptr<ReadState> &RS : IS.getUses())
- if (RS->isImplicitRead() || !IsDependencyBreaking)
+ if (!RS->isIndependentFromDef())
updateRAWDependencies(*RS, STI);
- // By default, a dependency-breaking zero-latency instruction is expected to
- // be optimized at register renaming stage. That means, no physical register
- // is allocated to the instruction.
- bool ShouldAllocateRegisters =
- !(Desc.isZeroLatency() && IsDependencyBreaking);
+ // By default, a dependency-breaking zero-idiom is expected to be optimized
+ // at register renaming stage. That means, no physical register is allocated
+ // to the instruction.
SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
- for (std::unique_ptr<WriteState> &WS : IS.getDefs()) {
- PRF.addRegisterWrite(WriteRef(IR.getSourceIndex(), WS.get()), RegisterFiles,
- ShouldAllocateRegisters);
- }
+ for (std::unique_ptr<WriteState> &WS : IS.getDefs())
+ PRF.addRegisterWrite(WriteRef(IR.getSourceIndex(), WS.get()), RegisterFiles);
// Reserve slots in the RCU, and notify the instruction that it has been
// dispatched to the schedulers for execution.
Modified: llvm/trunk/tools/llvm-mca/lib/Stages/RetireStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/lib/Stages/RetireStage.cpp?rev=342483&r1=342482&r2=342483&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/lib/Stages/RetireStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/lib/Stages/RetireStage.cpp Tue Sep 18 08:00:06 2018
@@ -51,11 +51,9 @@ void RetireStage::notifyInstructionRetir
LLVM_DEBUG(llvm::dbgs() << "[E] Instruction Retired: #" << IR << '\n');
llvm::SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles());
const Instruction &Inst = *IR.getInstruction();
- const InstrDesc &Desc = Inst.getDesc();
- bool ShouldFreeRegs = !(Desc.isZeroLatency() && Inst.isDependencyBreaking());
for (const std::unique_ptr<WriteState> &WS : Inst.getDefs())
- PRF.removeRegisterWrite(*WS.get(), FreedRegs, ShouldFreeRegs);
+ PRF.removeRegisterWrite(*WS.get(), FreedRegs);
notifyEvent<HWInstructionEvent>(HWInstructionRetiredEvent(IR, FreedRegs));
}
More information about the llvm-commits
mailing list