summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/MCA/Instruction.h43
-rw-r--r--llvm/lib/MCA/Instruction.cpp34
2 files changed, 63 insertions, 14 deletions
diff --git a/llvm/include/llvm/MCA/Instruction.h b/llvm/include/llvm/MCA/Instruction.h
index a7a47fd3645..c4d0f6aace3 100644
--- a/llvm/include/llvm/MCA/Instruction.h
+++ b/llvm/include/llvm/MCA/Instruction.h
@@ -80,6 +80,16 @@ struct ReadDescriptor {
class ReadState;
+/// Longest register dependency.
+///
+/// Used internally by WriteState/ReadState/InstructionBase to help with the
+/// computation of the longest register dependency for an instruction.
+struct CriticalRegDep {
+ unsigned IID;
+ unsigned RegID;
+ unsigned Cycles;
+};
+
/// Tracks uses of a register definition (e.g. register write).
///
/// Each implicit/explicit register write is associated with an instance of
@@ -123,9 +133,11 @@ class WriteState {
// A partial write that is in a false dependency with this write.
WriteState *PartialWrite;
-
unsigned DependentWriteCyclesLeft;
+ // Critical register dependency for this write.
+ CriticalRegDep CRD;
+
// A list of dependent reads. Users is a set of dependent
// reads. A dependent read is added to the set only if CyclesLeft
// is "unknown". As soon as CyclesLeft is 'known', each user in the set
@@ -140,7 +152,7 @@ public:
: WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
- DependentWriteCyclesLeft(0) {}
+ DependentWriteCyclesLeft(0), CRD() {}
WriteState(const WriteState &Other) = default;
WriteState &operator=(const WriteState &Other) = default;
@@ -150,7 +162,11 @@ public:
unsigned getRegisterID() const { return RegisterID; }
unsigned getRegisterFileID() const { return PRFID; }
unsigned getLatency() const { return WD->Latency; }
+ unsigned getDependentWriteCyclesLeft() const {
+ return DependentWriteCyclesLeft;
+ }
const WriteState *getDependentWrite() const { return DependentWrite; }
+ const CriticalRegDep &getCriticalRegDep() const { return CRD; }
// This method adds Use to the set of data dependent reads. IID is the
// instruction identifier associated with this write. ReadAdvance is the
@@ -162,10 +178,6 @@ public:
// write. IID is the instruction identifier associated with this write.
void addUser(unsigned IID, WriteState *Use);
- unsigned getDependentWriteCyclesLeft() const {
- return DependentWriteCyclesLeft;
- }
-
unsigned getNumUsers() const {
unsigned NumUsers = Users.size();
if (PartialWrite)
@@ -189,11 +201,7 @@ public:
}
void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
- void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) {
- DependentWriteCyclesLeft = Cycles;
- DependentWrite = nullptr;
- }
-
+ void writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles);
void setWriteZero() { WritesZero = true; }
void setEliminated() {
assert(Users.empty() && "Write is in an inconsistent state.");
@@ -235,6 +243,8 @@ class ReadState {
// dependent writes (i.e. field DependentWrite) is zero, this value is
// propagated to field CyclesLeft.
unsigned TotalCycles;
+ // Longest register dependency.
+ CriticalRegDep CRD;
// This field is set to true only if there are no dependent writes, and
// there are no `CyclesLeft' to wait.
bool IsReady;
@@ -246,13 +256,14 @@ class ReadState {
public:
ReadState(const ReadDescriptor &Desc, unsigned RegID)
: RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
- CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true),
- IsZero(false), IndependentFromDef(false) {}
+ CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(),
+ IsReady(true), IsZero(false), IndependentFromDef(false) {}
const ReadDescriptor &getDescriptor() const { return *RD; }
unsigned getSchedClass() const { return RD->SchedClassID; }
unsigned getRegisterID() const { return RegisterID; }
unsigned getRegisterFileID() const { return PRFID; }
+ const CriticalRegDep &getCriticalRegDep() const { return CRD; }
bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
bool isReady() const { return IsReady; }
@@ -394,6 +405,9 @@ class InstructionBase {
// One entry per each implicit and explicit register use.
SmallVector<ReadState, 4> Uses;
+ // Critical register dependency.
+ CriticalRegDep CRD;
+
public:
InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {}
@@ -405,6 +419,9 @@ public:
unsigned getLatency() const { return Desc.MaxLatency; }
+ const CriticalRegDep &getCriticalRegDep() const { return CRD; }
+ const CriticalRegDep &computeCriticalRegDep();
+
bool hasDependentUsers() const {
return any_of(Defs,
[](const WriteState &Def) { return Def.getNumUsers() > 0; });
diff --git a/llvm/lib/MCA/Instruction.cpp b/llvm/lib/MCA/Instruction.cpp
index 58f02503137..5e2fb771e4f 100644
--- a/llvm/lib/MCA/Instruction.cpp
+++ b/llvm/lib/MCA/Instruction.cpp
@@ -18,6 +18,14 @@
namespace llvm {
namespace mca {
+void WriteState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) {
+ CRD.IID = IID;
+ CRD.RegID = RegID;
+ CRD.Cycles = Cycles;
+ DependentWriteCyclesLeft = Cycles;
+ DependentWrite = nullptr;
+}
+
void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) {
assert(DependentWrites);
assert(CyclesLeft == UNKNOWN_CYCLES);
@@ -28,7 +36,12 @@ void ReadState::writeStartEvent(unsigned IID, unsigned RegID, unsigned Cycles) {
// The HW is forced to do some extra bookkeeping to track of all the
// dependent writes, and implement a merging scheme for the partial writes.
--DependentWrites;
- TotalCycles = std::max(TotalCycles, Cycles);
+ if (TotalCycles < Cycles) {
+ CRD.IID = IID;
+ CRD.RegID = RegID;
+ CRD.Cycles = Cycles;
+ TotalCycles = Cycles;
+ }
if (!DependentWrites) {
CyclesLeft = TotalCycles;
@@ -121,6 +134,25 @@ void WriteRef::dump() const {
}
#endif
+const CriticalRegDep &InstructionBase::computeCriticalRegDep() {
+ if (CRD.Cycles || (Defs.empty() && Uses.empty()))
+ return CRD;
+ unsigned MaxLatency = 0;
+ for (const WriteState &WS : Defs) {
+ const CriticalRegDep &WriteCRD = WS.getCriticalRegDep();
+ if (WriteCRD.Cycles > MaxLatency)
+ CRD = WriteCRD;
+ }
+
+ for (const ReadState &RS : Uses) {
+ const CriticalRegDep &ReadCRD = RS.getCriticalRegDep();
+ if (ReadCRD.Cycles > MaxLatency)
+ CRD = ReadCRD;
+ }
+
+ return CRD;
+}
+
void Instruction::dispatch(unsigned RCUToken) {
assert(Stage == IS_INVALID);
Stage = IS_DISPATCHED;
OpenPOWER on IntegriCloud