summaryrefslogtreecommitdiff
path: root/tools/llvm-mca
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-06-28 15:50:26 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-06-28 15:50:26 +0000
commita2237ff0e5a7dc57de894fb6ac32a1313f8d68ec (patch)
tree571ece426b7e9426b28a769c3403787075b5ad8d /tools/llvm-mca
parent8746f255cdaf65244cd85c5b2676c355a885d3d8 (diff)
[llvm-mca] Use a WriteRef to describe register writes in class RegisterFile.
This patch introduces a new class named WriteRef. A WriteRef is used by the RegisterFile to keep track of register definitions. Internally it wraps a WriteState, as well as the source index of the defining instruction. This patch allows the tool to propagate additional information to support future analysis on data dependencies. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335867 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mca')
-rw-r--r--tools/llvm-mca/DispatchStage.cpp16
-rw-r--r--tools/llvm-mca/DispatchStage.h3
-rw-r--r--tools/llvm-mca/Instruction.cpp10
-rw-r--r--tools/llvm-mca/Instruction.h30
-rw-r--r--tools/llvm-mca/RegisterFile.cpp72
-rw-r--r--tools/llvm-mca/RegisterFile.h22
6 files changed, 103 insertions, 50 deletions
diff --git a/tools/llvm-mca/DispatchStage.cpp b/tools/llvm-mca/DispatchStage.cpp
index 70cd28d843a..1bc292aae52 100644
--- a/tools/llvm-mca/DispatchStage.cpp
+++ b/tools/llvm-mca/DispatchStage.cpp
@@ -72,7 +72,7 @@ bool DispatchStage::checkScheduler(const InstRef &IR) {
void DispatchStage::updateRAWDependencies(ReadState &RS,
const MCSubtargetInfo &STI) {
- SmallVector<WriteState *, 4> DependentWrites;
+ SmallVector<WriteRef, 4> DependentWrites;
collectWrites(DependentWrites, RS.getRegisterID());
RS.setDependentWrites(DependentWrites.size());
@@ -83,17 +83,18 @@ void DispatchStage::updateRAWDependencies(ReadState &RS,
// to figure out in how many cycles this read becomes available.
const ReadDescriptor &RD = RS.getDescriptor();
if (!RD.HasReadAdvanceEntries) {
- for (WriteState *WS : DependentWrites)
- WS->addUser(&RS, /* ReadAdvance */ 0);
+ for (WriteRef &WR : DependentWrites)
+ WR.getWriteState()->addUser(&RS, /* ReadAdvance */ 0);
return;
}
const MCSchedModel &SM = STI.getSchedModel();
const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
- for (WriteState *WS : DependentWrites) {
- unsigned WriteResID = WS->getWriteResourceID();
+ for (WriteRef &WR : DependentWrites) {
+ WriteState &WS = *WR.getWriteState();
+ unsigned WriteResID = WS.getWriteResourceID();
int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- WS->addUser(&RS, ReadAdvance);
+ WS.addUser(&RS, ReadAdvance);
}
}
@@ -126,7 +127,8 @@ void DispatchStage::dispatch(InstRef IR) {
// is allocated to the instruction.
SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
for (std::unique_ptr<WriteState> &WS : IS.getDefs())
- PRF.addRegisterWrite(*WS, RegisterFiles, !Desc.isZeroLatency());
+ PRF.addRegisterWrite(WriteRef(IR.first, WS.get()), RegisterFiles,
+ !Desc.isZeroLatency());
// Reserve slots in the RCU, and notify the instruction that it has been
// dispatched to the schedulers for execution.
diff --git a/tools/llvm-mca/DispatchStage.h b/tools/llvm-mca/DispatchStage.h
index 9695c3e6854..fff9a2bb114 100644
--- a/tools/llvm-mca/DispatchStage.h
+++ b/tools/llvm-mca/DispatchStage.h
@@ -29,7 +29,6 @@
namespace mca {
-class WriteState;
class Scheduler;
// Implements the hardware dispatch logic.
@@ -78,7 +77,7 @@ class DispatchStage : public Stage {
return checkRCU(IR) && checkPRF(IR) && checkScheduler(IR);
}
- void collectWrites(llvm::SmallVectorImpl<WriteState *> &Vec,
+ void collectWrites(llvm::SmallVectorImpl<WriteRef> &Vec,
unsigned RegID) const {
return PRF.collectWrites(Vec, RegID);
}
diff --git a/tools/llvm-mca/Instruction.cpp b/tools/llvm-mca/Instruction.cpp
index f84c7811138..c8eb63feeee 100644
--- a/tools/llvm-mca/Instruction.cpp
+++ b/tools/llvm-mca/Instruction.cpp
@@ -96,6 +96,13 @@ void WriteState::dump() const {
dbgs() << "{ OpIdx=" << WD.OpIndex << ", Lat=" << WD.Latency << ", RegID "
<< getRegisterID() << ", Cycles Left=" << getCyclesLeft() << " }\n";
}
+
+void WriteRef::dump() const {
+ if (isValid())
+ getWriteState()->dump();
+ else
+ dbgs() << "(null)";
+}
#endif
void Instruction::dispatch(unsigned RCUToken) {
@@ -152,4 +159,7 @@ void Instruction::cycleEvent() {
if (!CyclesLeft)
Stage = IS_EXECUTED;
}
+
+const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
+
} // namespace mca
diff --git a/tools/llvm-mca/Instruction.h b/tools/llvm-mca/Instruction.h
index 32246cebaa5..2df6a59f38c 100644
--- a/tools/llvm-mca/Instruction.h
+++ b/tools/llvm-mca/Instruction.h
@@ -381,6 +381,36 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const InstRef &IR) {
}
#endif
+/// A reference to a register write.
+///
+/// This class is mainly used by the register file to describe register
+/// mappings. It correlates a register write to the source index of the
+/// defining instruction.
+class WriteRef {
+ std::pair<unsigned, WriteState *> Data;
+ static const unsigned INVALID_IID;
+
+public:
+ WriteRef() : Data(INVALID_IID, nullptr) {}
+ WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {}
+
+ 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;
+ }
+ bool operator==(const WriteRef &Other) const {
+ return Data == Other.Data;
+ }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
} // namespace mca
#endif
diff --git a/tools/llvm-mca/RegisterFile.cpp b/tools/llvm-mca/RegisterFile.cpp
index 5da4b5eeafd..427b32ad357 100644
--- a/tools/llvm-mca/RegisterFile.cpp
+++ b/tools/llvm-mca/RegisterFile.cpp
@@ -24,6 +24,12 @@ using namespace llvm;
namespace mca {
+RegisterFile::RegisterFile(const llvm::MCSchedModel &SM,
+ const llvm::MCRegisterInfo &mri, unsigned NumRegs)
+ : MRI(mri), RegisterMappings(mri.getNumRegs(), {WriteRef(), {0, 0}}) {
+ initialize(SM, NumRegs);
+}
+
void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
// Create a default register file that "sees" all the machine registers
// declared by the target. The number of physical registers in the default
@@ -66,8 +72,7 @@ void RegisterFile::addRegisterFile(ArrayRef<MCRegisterCostEntry> Entries,
// An empty set of register classes means: this register file contains all
// the physical registers specified by the target.
if (Entries.empty()) {
- for (std::pair<WriteState *, IndexPlusCostPairTy> &Mapping :
- RegisterMappings)
+ for (std::pair<WriteRef, IndexPlusCostPairTy> &Mapping : RegisterMappings)
Mapping.second = std::make_pair(RegisterFileIndex, 1U);
return;
}
@@ -120,16 +125,17 @@ void RegisterFile::freePhysRegs(IndexPlusCostPairTy Entry,
FreedPhysRegs[0] += Cost;
}
-void RegisterFile::addRegisterWrite(WriteState &WS,
+void RegisterFile::addRegisterWrite(WriteRef Write,
MutableArrayRef<unsigned> UsedPhysRegs,
bool ShouldAllocatePhysRegs) {
+ const WriteState &WS = *Write.getWriteState();
unsigned RegID = WS.getRegisterID();
assert(RegID && "Adding an invalid register definition?");
RegisterMapping &Mapping = RegisterMappings[RegID];
- Mapping.first = &WS;
+ Mapping.first = Write;
for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].first = &WS;
+ RegisterMappings[*I].first = Write;
// No physical registers are allocated for instructions that are optimized in
// hardware. For example, zero-latency data-dependency breaking instructions
@@ -142,7 +148,7 @@ void RegisterFile::addRegisterWrite(WriteState &WS,
return;
for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].first = &WS;
+ RegisterMappings[*I].first = Write;
}
void RegisterFile::removeRegisterWrite(const WriteState &WS,
@@ -156,50 +162,61 @@ void RegisterFile::removeRegisterWrite(const WriteState &WS,
"Invalidating a write of unknown cycles!");
assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
RegisterMapping &Mapping = RegisterMappings[RegID];
- if (!Mapping.first)
+ WriteRef &WR = Mapping.first;
+ if (!WR.isValid())
return;
if (ShouldFreePhysRegs)
freePhysRegs(Mapping.second, FreedPhysRegs);
- if (Mapping.first == &WS)
- Mapping.first = nullptr;
+ if (WR.getWriteState() == &WS)
+ WR.invalidate();
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I)
- if (RegisterMappings[*I].first == &WS)
- RegisterMappings[*I].first = nullptr;
+ for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ WR = RegisterMappings[*I].first;
+ if (WR.getWriteState() == &WS)
+ WR.invalidate();
+ }
if (!ShouldInvalidateSuperRegs)
return;
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I)
- if (RegisterMappings[*I].first == &WS)
- RegisterMappings[*I].first = nullptr;
+ for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
+ WR = RegisterMappings[*I].first;
+ if (WR.getWriteState() == &WS)
+ WR.invalidate();
+ }
}
-void RegisterFile::collectWrites(SmallVectorImpl<WriteState *> &Writes,
+void RegisterFile::collectWrites(SmallVectorImpl<WriteRef> &Writes,
unsigned RegID) const {
assert(RegID && RegID < RegisterMappings.size());
- WriteState *WS = RegisterMappings[RegID].first;
- if (WS)
- Writes.push_back(WS);
+ const WriteRef &WR = RegisterMappings[RegID].first;
+ if (WR.isValid())
+ Writes.push_back(WR);
// Handle potential partial register updates.
for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WS = RegisterMappings[*I].first;
- if (WS)
- Writes.push_back(WS);
+ const WriteRef &WR = RegisterMappings[*I].first;
+ if (WR.isValid())
+ Writes.push_back(WR);
}
// Remove duplicate entries and resize the input vector.
- llvm::sort(Writes.begin(), Writes.end());
+ llvm::sort(Writes.begin(), Writes.end(),
+ [](const WriteRef &Lhs, const WriteRef &Rhs) {
+ return Lhs.getWriteState() < Rhs.getWriteState();
+ });
auto It = std::unique(Writes.begin(), Writes.end());
Writes.resize(std::distance(Writes.begin(), It));
LLVM_DEBUG({
- for (const WriteState *WS : Writes)
+ for (const WriteRef &WR : Writes) {
+ const WriteState &WS = *WR.getWriteState();
dbgs() << "Found a dependent use of Register "
- << MRI.getName(WS->getRegisterID()) << "\n";
+ << MRI.getName(WS.getRegisterID()) << " (defined by intruction #"
+ << WR.getSourceIndex() << '\n';
+ }
});
}
@@ -249,10 +266,7 @@ void RegisterFile::dump() const {
const RegisterMapping &RM = RegisterMappings[I];
dbgs() << MRI.getName(I) << ", " << I << ", Map=" << RM.second.first
<< ", ";
- if (RM.first)
- RM.first->dump();
- else
- dbgs() << "(null)\n";
+ RM.first.dump();
}
for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
diff --git a/tools/llvm-mca/RegisterFile.h b/tools/llvm-mca/RegisterFile.h
index 7d5d22bb61d..b93bdeb2eae 100644
--- a/tools/llvm-mca/RegisterFile.h
+++ b/tools/llvm-mca/RegisterFile.h
@@ -25,15 +25,16 @@ namespace mca {
class ReadState;
class WriteState;
+class WriteRef;
/// Manages hardware register files, and tracks register definitions for
/// register renaming purposes.
class RegisterFile {
const llvm::MCRegisterInfo &MRI;
- // Each register file is associated with an instance of RegisterMappingTracker.
- // A RegisterMappingTracker keeps track of the number of physical registers
- // which have been dynamically allocated by the simulator.
+ // Each register file is associated with an instance of
+ // RegisterMappingTracker. A RegisterMappingTracker tracks the number of
+ // physical registers that are dynamically allocated by the simulator.
struct RegisterMappingTracker {
// The total number of physical registers that are available in this
// register file for register renaming purpouses. A value of zero for this
@@ -53,7 +54,7 @@ class RegisterFile {
// hardware registers declared by the target (i.e. all the register
// definitions in the target specific `XYZRegisterInfo.td` - where `XYZ` is
// the target name).
- //
+ //
// Users can limit the number of physical registers that are available in
// regsiter file #0 specifying command line flag `-register-file-size=<uint>`.
llvm::SmallVector<RegisterMappingTracker, 4> RegisterFiles;
@@ -68,14 +69,14 @@ class RegisterFile {
// 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 WriteState object), as well as a
+ // the last register write (in the form of a WriteRef object), as well as a
// IndexPlusCostPairTy to quickly identify owning register files.
//
// This implementation does not allow overlapping register files. The only
// register file that is allowed to overlap with other register files is
// register file #0. If we exclude register #0, every register is "owned" by
// at most one register file.
- using RegisterMapping = std::pair<WriteState *, IndexPlusCostPairTy>;
+ using RegisterMapping = std::pair<WriteRef, IndexPlusCostPairTy>;
// This map contains one entry for each register defined by the target.
std::vector<RegisterMapping> RegisterMappings;
@@ -117,16 +118,13 @@ class RegisterFile {
public:
RegisterFile(const llvm::MCSchedModel &SM, const llvm::MCRegisterInfo &mri,
- unsigned NumRegs = 0)
- : MRI(mri), RegisterMappings(mri.getNumRegs(), {nullptr, {0, 0}}) {
- initialize(SM, NumRegs);
- }
+ unsigned NumRegs = 0);
// 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.
- void addRegisterWrite(WriteState &WS,
+ void addRegisterWrite(WriteRef Write,
llvm::MutableArrayRef<unsigned> UsedPhysRegs,
bool ShouldAllocatePhysRegs = true);
@@ -143,7 +141,7 @@ public:
// register file was busy. This sematic allows us classify dispatch dispatch
// stalls caused by the lack of register file resources.
unsigned isAvailable(llvm::ArrayRef<unsigned> Regs) const;
- void collectWrites(llvm::SmallVectorImpl<WriteState *> &Writes,
+ void collectWrites(llvm::SmallVectorImpl<WriteRef> &Writes,
unsigned RegID) const;
void updateOnRead(ReadState &RS, unsigned RegID);