123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- ///
- /// This file defines a register mapping file class. This class is responsible
- /// for managing hardware register files and the tracking of data dependencies
- /// between registers.
- ///
- //===----------------------------------------------------------------------===//
- #include "llvm/MCA/HardwareUnits/RegisterFile.h"
- #include "llvm/MCA/Instruction.h"
- #include "llvm/Support/Debug.h"
- #define DEBUG_TYPE "llvm-mca"
- namespace llvm {
- namespace mca {
- const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
- WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
- : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
- Write(WS) {}
- void WriteRef::commit() {
- assert(Write && Write->isExecuted() && "Cannot commit before write back!");
- RegisterID = Write->getRegisterID();
- WriteResID = Write->getWriteResourceID();
- Write = nullptr;
- }
- void WriteRef::notifyExecuted(unsigned Cycle) {
- assert(Write && Write->isExecuted() && "Not executed!");
- WriteBackCycle = Cycle;
- }
- bool WriteRef::hasKnownWriteBackCycle() const {
- return isValid() && (!Write || Write->isExecuted());
- }
- bool WriteRef::isWriteZero() const {
- assert(isValid() && "Invalid null WriteState found!");
- return getWriteState()->isWriteZero();
- }
- unsigned WriteRef::getWriteResourceID() const {
- if (Write)
- return Write->getWriteResourceID();
- return WriteResID;
- }
- MCPhysReg WriteRef::getRegisterID() const {
- if (Write)
- return Write->getRegisterID();
- return RegisterID;
- }
- RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
- unsigned NumRegs)
- : MRI(mri),
- RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
- ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
- 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
- // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
- // means: this register file has an unbounded number of physical registers.
- RegisterFiles.emplace_back(NumRegs);
- if (!SM.hasExtraProcessorInfo())
- return;
- // For each user defined register file, allocate a RegisterMappingTracker
- // object. The size of every register file, as well as the mapping between
- // register files and register classes is specified via tablegen.
- const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
- // Skip invalid register file at index 0.
- for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
- const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
- assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
- // The cost of a register definition is equivalent to the number of
- // physical registers that are allocated at register renaming stage.
- unsigned Length = RF.NumRegisterCostEntries;
- const MCRegisterCostEntry *FirstElt =
- &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
- addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
- }
- }
- void RegisterFile::cycleStart() {
- for (RegisterMappingTracker &RMT : RegisterFiles)
- RMT.NumMoveEliminated = 0;
- }
- void RegisterFile::onInstructionExecuted(Instruction *IS) {
- assert(IS && IS->isExecuted() && "Unexpected internal state found!");
- for (WriteState &WS : IS->getDefs()) {
- if (WS.isEliminated())
- return;
- MCPhysReg RegID = WS.getRegisterID();
- // This allows InstrPostProcess to remove register Defs
- // by setting their RegisterID to 0.
- if (!RegID)
- continue;
- assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
- "The number of cycles should be known at this point!");
- assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
- MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
- if (RenameAs && RenameAs != RegID)
- RegID = RenameAs;
- WriteRef &WR = RegisterMappings[RegID].first;
- if (WR.getWriteState() == &WS)
- WR.notifyExecuted(CurrentCycle);
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WriteRef &OtherWR = RegisterMappings[*I].first;
- if (OtherWR.getWriteState() == &WS)
- OtherWR.notifyExecuted(CurrentCycle);
- }
- if (!WS.clearsSuperRegisters())
- continue;
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WriteRef &OtherWR = RegisterMappings[*I].first;
- if (OtherWR.getWriteState() == &WS)
- OtherWR.notifyExecuted(CurrentCycle);
- }
- }
- }
- void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
- ArrayRef<MCRegisterCostEntry> Entries) {
- // A default register file is always allocated at index #0. That register file
- // is mainly used to count the total number of mappings created by all
- // register files at runtime. Users can limit the number of available physical
- // registers in register file #0 through the command line flag
- // `-register-file-size`.
- unsigned RegisterFileIndex = RegisterFiles.size();
- RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
- RF.AllowZeroMoveEliminationOnly);
- // Special case where there is no register class identifier in the set.
- // An empty set of register classes means: this register file contains all
- // the physical registers specified by the target.
- // We optimistically assume that a register can be renamed at the cost of a
- // single physical register. The constructor of RegisterFile ensures that
- // a RegisterMapping exists for each logical register defined by the Target.
- if (Entries.empty())
- return;
- // Now update the cost of individual registers.
- for (const MCRegisterCostEntry &RCE : Entries) {
- const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
- for (const MCPhysReg Reg : RC) {
- RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
- IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
- if (IPC.first && IPC.first != RegisterFileIndex) {
- // The only register file that is allowed to overlap is the default
- // register file at index #0. The analysis is inaccurate if register
- // files overlap.
- errs() << "warning: register " << MRI.getName(Reg)
- << " defined in multiple register files.";
- }
- IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
- Entry.RenameAs = Reg;
- Entry.AllowMoveElimination = RCE.AllowMoveElimination;
- // Assume the same cost for each sub-register.
- for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
- RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
- if (!OtherEntry.IndexPlusCost.first &&
- (!OtherEntry.RenameAs ||
- MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
- OtherEntry.IndexPlusCost = IPC;
- OtherEntry.RenameAs = Reg;
- }
- }
- }
- }
- }
- void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
- MutableArrayRef<unsigned> UsedPhysRegs) {
- unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
- unsigned Cost = Entry.IndexPlusCost.second;
- if (RegisterFileIndex) {
- RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- RMT.NumUsedPhysRegs += Cost;
- UsedPhysRegs[RegisterFileIndex] += Cost;
- }
- // Now update the default register mapping tracker.
- RegisterFiles[0].NumUsedPhysRegs += Cost;
- UsedPhysRegs[0] += Cost;
- }
- void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
- MutableArrayRef<unsigned> FreedPhysRegs) {
- unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
- unsigned Cost = Entry.IndexPlusCost.second;
- if (RegisterFileIndex) {
- RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- RMT.NumUsedPhysRegs -= Cost;
- FreedPhysRegs[RegisterFileIndex] += Cost;
- }
- // Now update the default register mapping tracker.
- RegisterFiles[0].NumUsedPhysRegs -= Cost;
- FreedPhysRegs[0] += Cost;
- }
- void RegisterFile::addRegisterWrite(WriteRef Write,
- MutableArrayRef<unsigned> UsedPhysRegs) {
- WriteState &WS = *Write.getWriteState();
- MCPhysReg RegID = WS.getRegisterID();
- // This allows InstrPostProcess to remove register Defs
- // by setting their RegisterID to 0.
- if (!RegID)
- return;
- LLVM_DEBUG({
- dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
- << MRI.getName(RegID) << "]\n";
- });
- // If RenameAs is equal to RegID, then RegID is subject to register renaming
- // and false dependencies on RegID are all eliminated.
- // If RenameAs references the invalid register, then we optimistically assume
- // that it can be renamed. In the absence of tablegen descriptors for register
- // files, RenameAs is always set to the invalid register ID. In all other
- // cases, RenameAs must be either equal to RegID, or it must reference a
- // super-register of RegID.
- // If RenameAs is a super-register of RegID, then a write to RegID has always
- // 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 IsWriteZero = WS.isWriteZero();
- bool IsEliminated = WS.isEliminated();
- bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
- const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
- WS.setPRF(RRI.IndexPlusCost.first);
- if (RRI.RenameAs && RRI.RenameAs != RegID) {
- RegID = RRI.RenameAs;
- WriteRef &OtherWrite = RegisterMappings[RegID].first;
- if (!WS.clearsSuperRegisters()) {
- // The processor keeps the definition of `RegID` together with register
- // `RenameAs`. Since this partial write is not renamed, no physical
- // register is allocated.
- ShouldAllocatePhysRegs = false;
- WriteState *OtherWS = OtherWrite.getWriteState();
- if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
- // This partial write has a false dependency on RenameAs.
- assert(!IsEliminated && "Unexpected partial update!");
- OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
- }
- }
- }
- // Update zero registers.
- MCPhysReg ZeroRegisterID =
- WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
- ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
- for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
- ZeroRegisters.setBitVal(*I, IsWriteZero);
- // If this move has been eliminated, then method tryEliminateMoveOrSwap should
- // have already updated all the register mappings.
- if (!IsEliminated) {
- // Check if this is one of multiple writes performed by this
- // instruction to register RegID.
- const WriteRef &OtherWrite = RegisterMappings[RegID].first;
- const WriteState *OtherWS = OtherWrite.getWriteState();
- if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
- if (OtherWS->getLatency() > WS.getLatency()) {
- // Conservatively keep the slowest write on RegID.
- if (ShouldAllocatePhysRegs)
- allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
- return;
- }
- }
- // Update the mapping for register RegID including its sub-registers.
- RegisterMappings[RegID].first = Write;
- RegisterMappings[RegID].second.AliasRegID = 0U;
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- RegisterMappings[*I].first = Write;
- RegisterMappings[*I].second.AliasRegID = 0U;
- }
- // No physical registers are allocated for instructions that are optimized
- // in hardware. For example, zero-latency data-dependency breaking
- // instructions don't consume physical registers.
- if (ShouldAllocatePhysRegs)
- allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
- }
- if (!WS.clearsSuperRegisters())
- return;
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- if (!IsEliminated) {
- RegisterMappings[*I].first = Write;
- RegisterMappings[*I].second.AliasRegID = 0U;
- }
- ZeroRegisters.setBitVal(*I, IsWriteZero);
- }
- }
- void RegisterFile::removeRegisterWrite(
- const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
- // Early exit if this write was eliminated. A write eliminated at register
- // renaming stage generates an alias, and it is not added to the PRF.
- if (WS.isEliminated())
- return;
- MCPhysReg RegID = WS.getRegisterID();
- // This allows InstrPostProcess to remove register Defs
- // by setting their RegisterID to 0.
- if (!RegID)
- return;
- assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
- "Invalidating a write of unknown cycles!");
- assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
- bool ShouldFreePhysRegs = !WS.isWriteZero();
- MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
- if (RenameAs && RenameAs != RegID) {
- RegID = RenameAs;
- if (!WS.clearsSuperRegisters()) {
- // Keep the definition of `RegID` together with register `RenameAs`.
- ShouldFreePhysRegs = false;
- }
- }
- if (ShouldFreePhysRegs)
- freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
- WriteRef &WR = RegisterMappings[RegID].first;
- if (WR.getWriteState() == &WS)
- WR.commit();
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WriteRef &OtherWR = RegisterMappings[*I].first;
- if (OtherWR.getWriteState() == &WS)
- OtherWR.commit();
- }
- if (!WS.clearsSuperRegisters())
- return;
- for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- WriteRef &OtherWR = RegisterMappings[*I].first;
- if (OtherWR.getWriteState() == &WS)
- OtherWR.commit();
- }
- }
- bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
- unsigned RegisterFileIndex) const {
- const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
- const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
- const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- // From and To must be owned by the PRF at index `RegisterFileIndex`.
- const RegisterRenamingInfo &RRIFrom = RMFrom.second;
- if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
- return false;
- const RegisterRenamingInfo &RRITo = RMTo.second;
- if (RRITo.IndexPlusCost.first != RegisterFileIndex)
- return false;
- // Early exit if the destination register is from a register class that
- // doesn't allow move elimination.
- if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
- return false;
- // We only allow move elimination for writes that update a full physical
- // register. On X86, move elimination is possible with 32-bit general purpose
- // registers because writes to those registers are not partial writes. If a
- // register move is a partial write, then we conservatively assume that move
- // elimination fails, since it would either trigger a partial update, or the
- // issue of a merge opcode.
- //
- // Note that this constraint may be lifted in future. For example, we could
- // make this model more flexible, and let users customize the set of registers
- // (i.e. register classes) that allow move elimination.
- //
- // For now, we assume that there is a strong correlation between registers
- // that allow move elimination, and how those same registers are renamed in
- // hardware.
- if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
- if (!WS.clearsSuperRegisters())
- return false;
- bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
- return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
- }
- bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
- MutableArrayRef<ReadState> Reads) {
- if (Writes.size() != Reads.size())
- return false;
- // This logic assumes that writes and reads are contributed by a register move
- // or a register swap operation. In particular, it assumes a simple register
- // move if there is only one write. It assumes a swap operation if there are
- // exactly two writes.
- if (Writes.empty() || Writes.size() > 2)
- return false;
- // All registers must be owned by the same PRF.
- const RegisterRenamingInfo &RRInfo =
- RegisterMappings[Writes[0].getRegisterID()].second;
- unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
- RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
- // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
- if (RMT.MaxMoveEliminatedPerCycle &&
- (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
- return false;
- for (size_t I = 0, E = Writes.size(); I < E; ++I) {
- const ReadState &RS = Reads[I];
- const WriteState &WS = Writes[E - (I + 1)];
- if (!canEliminateMove(WS, RS, RegisterFileIndex))
- return false;
- }
- for (size_t I = 0, E = Writes.size(); I < E; ++I) {
- ReadState &RS = Reads[I];
- WriteState &WS = Writes[E - (I + 1)];
- const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
- const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
- const RegisterRenamingInfo &RRIFrom = RMFrom.second;
- const RegisterRenamingInfo &RRITo = RMTo.second;
- // Construct an alias.
- MCPhysReg AliasedReg =
- RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
- MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
- const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
- if (RMAlias.AliasRegID)
- AliasedReg = RMAlias.AliasRegID;
- RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
- for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
- RegisterMappings[*I].second.AliasRegID = AliasedReg;
- if (ZeroRegisters[RS.getRegisterID()]) {
- WS.setWriteZero();
- RS.setReadZero();
- }
- WS.setEliminated();
- RMT.NumMoveEliminated++;
- }
- return true;
- }
- unsigned WriteRef::getWriteBackCycle() const {
- assert(hasKnownWriteBackCycle() && "Instruction not executed!");
- assert((!Write || Write->getCyclesLeft() <= 0) &&
- "Inconsistent state found!");
- return WriteBackCycle;
- }
- unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
- assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
- return CurrentCycle - WR.getWriteBackCycle();
- }
- void RegisterFile::collectWrites(
- const MCSubtargetInfo &STI, const ReadState &RS,
- SmallVectorImpl<WriteRef> &Writes,
- SmallVectorImpl<WriteRef> &CommittedWrites) const {
- const ReadDescriptor &RD = RS.getDescriptor();
- const MCSchedModel &SM = STI.getSchedModel();
- const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
- MCPhysReg RegID = RS.getRegisterID();
- assert(RegID && RegID < RegisterMappings.size());
- LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
- << MRI.getName(RegID) << '\n');
- // Check if this is an alias.
- const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
- if (RRI.AliasRegID)
- RegID = RRI.AliasRegID;
- const WriteRef &WR = RegisterMappings[RegID].first;
- if (WR.getWriteState()) {
- Writes.push_back(WR);
- } else if (WR.hasKnownWriteBackCycle()) {
- unsigned WriteResID = WR.getWriteResourceID();
- int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- if (ReadAdvance < 0) {
- unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
- if (Elapsed < static_cast<unsigned>(-ReadAdvance))
- CommittedWrites.push_back(WR);
- }
- }
- // Handle potential partial register updates.
- for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
- const WriteRef &WR = RegisterMappings[*I].first;
- if (WR.getWriteState()) {
- Writes.push_back(WR);
- } else if (WR.hasKnownWriteBackCycle()) {
- unsigned WriteResID = WR.getWriteResourceID();
- int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- if (ReadAdvance < 0) {
- unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
- if (Elapsed < static_cast<unsigned>(-ReadAdvance))
- CommittedWrites.push_back(WR);
- }
- }
- }
- // Remove duplicate entries and resize the input vector.
- if (Writes.size() > 1) {
- sort(Writes, [](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 WriteRef &WR : Writes) {
- const WriteState &WS = *WR.getWriteState();
- dbgs() << "[PRF] Found a dependent use of Register "
- << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
- << WR.getSourceIndex() << ")\n";
- }
- });
- }
- RegisterFile::RAWHazard
- RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
- const ReadState &RS) const {
- RAWHazard Hazard;
- SmallVector<WriteRef, 4> Writes;
- SmallVector<WriteRef, 4> CommittedWrites;
- const MCSchedModel &SM = STI.getSchedModel();
- const ReadDescriptor &RD = RS.getDescriptor();
- const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
- collectWrites(STI, RS, Writes, CommittedWrites);
- for (const WriteRef &WR : Writes) {
- const WriteState *WS = WR.getWriteState();
- unsigned WriteResID = WS->getWriteResourceID();
- int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
- if (Hazard.isValid())
- continue;
- Hazard.RegisterID = WR.getRegisterID();
- Hazard.CyclesLeft = UNKNOWN_CYCLES;
- continue;
- }
- int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
- if (CyclesLeft > 0) {
- if (Hazard.CyclesLeft < CyclesLeft) {
- Hazard.RegisterID = WR.getRegisterID();
- Hazard.CyclesLeft = CyclesLeft;
- }
- }
- }
- Writes.clear();
- for (const WriteRef &WR : CommittedWrites) {
- unsigned WriteResID = WR.getWriteResourceID();
- int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
- int CyclesLeft = NegReadAdvance - Elapsed;
- assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
- if (Hazard.CyclesLeft < CyclesLeft) {
- Hazard.RegisterID = WR.getRegisterID();
- Hazard.CyclesLeft = CyclesLeft;
- }
- }
- return Hazard;
- }
- void RegisterFile::addRegisterRead(ReadState &RS,
- const MCSubtargetInfo &STI) const {
- MCPhysReg RegID = RS.getRegisterID();
- const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
- RS.setPRF(RRI.IndexPlusCost.first);
- if (RS.isIndependentFromDef())
- return;
- if (ZeroRegisters[RS.getRegisterID()])
- RS.setReadZero();
- SmallVector<WriteRef, 4> DependentWrites;
- SmallVector<WriteRef, 4> CompletedWrites;
- collectWrites(STI, RS, DependentWrites, CompletedWrites);
- RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
- // We know that this read depends on all the writes in DependentWrites.
- // For each write, check if we have ReadAdvance information, and use it
- // to figure out in how many cycles this read will be available.
- const ReadDescriptor &RD = RS.getDescriptor();
- const MCSchedModel &SM = STI.getSchedModel();
- const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
- for (WriteRef &WR : DependentWrites) {
- unsigned WriteResID = WR.getWriteResourceID();
- WriteState &WS = *WR.getWriteState();
- int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
- WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
- }
- for (WriteRef &WR : CompletedWrites) {
- unsigned WriteResID = WR.getWriteResourceID();
- assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
- assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
- unsigned ReadAdvance = static_cast<unsigned>(
- -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
- unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
- assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
- RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
- ReadAdvance - Elapsed);
- }
- }
- unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
- SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
- // Find how many new mappings must be created for each register file.
- for (const MCPhysReg RegID : Regs) {
- const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
- const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
- if (Entry.first)
- NumPhysRegs[Entry.first] += Entry.second;
- NumPhysRegs[0] += Entry.second;
- }
- unsigned Response = 0;
- for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
- unsigned NumRegs = NumPhysRegs[I];
- if (!NumRegs)
- continue;
- const RegisterMappingTracker &RMT = RegisterFiles[I];
- if (!RMT.NumPhysRegs) {
- // The register file has an unbounded number of microarchitectural
- // registers.
- continue;
- }
- if (RMT.NumPhysRegs < NumRegs) {
- // The current register file is too small. This may occur if the number of
- // microarchitectural registers in register file #0 was changed by the
- // users via flag -reg-file-size. Alternatively, the scheduling model
- // specified a too small number of registers for this register file.
- LLVM_DEBUG(
- dbgs() << "[PRF] Not enough registers in the register file.\n");
- // FIXME: Normalize the instruction register count to match the
- // NumPhysRegs value. This is a highly unusual case, and is not expected
- // to occur. This normalization is hiding an inconsistency in either the
- // scheduling model or in the value that the user might have specified
- // for NumPhysRegs.
- NumRegs = RMT.NumPhysRegs;
- }
- if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
- Response |= (1U << I);
- }
- return Response;
- }
- #ifndef NDEBUG
- void WriteRef::dump() const {
- dbgs() << "IID=" << getSourceIndex() << ' ';
- if (isValid())
- getWriteState()->dump();
- else
- dbgs() << "(null)";
- }
- void RegisterFile::dump() const {
- for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
- const RegisterMapping &RM = RegisterMappings[I];
- const RegisterRenamingInfo &RRI = RM.second;
- if (ZeroRegisters[I]) {
- dbgs() << MRI.getName(I) << ", " << I
- << ", PRF=" << RRI.IndexPlusCost.first
- << ", Cost=" << RRI.IndexPlusCost.second
- << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
- << ",";
- RM.first.dump();
- dbgs() << '\n';
- }
- }
- for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
- dbgs() << "Register File #" << I;
- const RegisterMappingTracker &RMT = RegisterFiles[I];
- dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
- << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
- }
- }
- #endif
- } // namespace mca
- } // namespace llvm
|