diff options
author | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-06-28 15:50:26 +0000 |
---|---|---|
committer | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-06-28 15:50:26 +0000 |
commit | a2237ff0e5a7dc57de894fb6ac32a1313f8d68ec (patch) | |
tree | 571ece426b7e9426b28a769c3403787075b5ad8d /tools/llvm-mca | |
parent | 8746f255cdaf65244cd85c5b2676c355a885d3d8 (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.cpp | 16 | ||||
-rw-r--r-- | tools/llvm-mca/DispatchStage.h | 3 | ||||
-rw-r--r-- | tools/llvm-mca/Instruction.cpp | 10 | ||||
-rw-r--r-- | tools/llvm-mca/Instruction.h | 30 | ||||
-rw-r--r-- | tools/llvm-mca/RegisterFile.cpp | 72 | ||||
-rw-r--r-- | tools/llvm-mca/RegisterFile.h | 22 |
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); |