Path: blob/main/contrib/llvm-project/llvm/lib/MCA/HardwareUnits/RegisterFile.cpp
96360 views
//===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file defines a register mapping file class. This class is responsible10/// for managing hardware register files and the tracking of data dependencies11/// between registers.12///13//===----------------------------------------------------------------------===//1415#include "llvm/MCA/HardwareUnits/RegisterFile.h"16#include "llvm/MCA/Instruction.h"17#include "llvm/Support/Debug.h"1819#define DEBUG_TYPE "llvm-mca"2021namespace llvm {22namespace mca {2324const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();2526WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)27: IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),28Write(WS) {}2930void WriteRef::commit() {31assert(Write && Write->isExecuted() && "Cannot commit before write back!");32RegisterID = Write->getRegisterID();33WriteResID = Write->getWriteResourceID();34Write = nullptr;35}3637void WriteRef::notifyExecuted(unsigned Cycle) {38assert(Write && Write->isExecuted() && "Not executed!");39WriteBackCycle = Cycle;40}4142bool WriteRef::hasKnownWriteBackCycle() const {43return isValid() && (!Write || Write->isExecuted());44}4546bool WriteRef::isWriteZero() const {47assert(isValid() && "Invalid null WriteState found!");48return getWriteState()->isWriteZero();49}5051unsigned WriteRef::getWriteResourceID() const {52if (Write)53return Write->getWriteResourceID();54return WriteResID;55}5657MCPhysReg WriteRef::getRegisterID() const {58if (Write)59return Write->getRegisterID();60return RegisterID;61}6263RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,64unsigned NumRegs)65: MRI(mri),66RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),67ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {68initialize(SM, NumRegs);69}7071void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {72// Create a default register file that "sees" all the machine registers73// declared by the target. The number of physical registers in the default74// register file is set equal to `NumRegs`. A value of zero for `NumRegs`75// means: this register file has an unbounded number of physical registers.76RegisterFiles.emplace_back(NumRegs);77if (!SM.hasExtraProcessorInfo())78return;7980// For each user defined register file, allocate a RegisterMappingTracker81// object. The size of every register file, as well as the mapping between82// register files and register classes is specified via tablegen.83const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();8485// Skip invalid register file at index 0.86for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {87const MCRegisterFileDesc &RF = Info.RegisterFiles[I];88assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");8990// The cost of a register definition is equivalent to the number of91// physical registers that are allocated at register renaming stage.92unsigned Length = RF.NumRegisterCostEntries;93const MCRegisterCostEntry *FirstElt =94&Info.RegisterCostTable[RF.RegisterCostEntryIdx];95addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));96}97}9899void RegisterFile::cycleStart() {100for (RegisterMappingTracker &RMT : RegisterFiles)101RMT.NumMoveEliminated = 0;102}103104void RegisterFile::onInstructionExecuted(Instruction *IS) {105assert(IS && IS->isExecuted() && "Unexpected internal state found!");106for (WriteState &WS : IS->getDefs()) {107if (WS.isEliminated())108return;109110MCPhysReg RegID = WS.getRegisterID();111112// This allows InstrPostProcess to remove register Defs113// by setting their RegisterID to 0.114if (!RegID)115continue;116117assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&118"The number of cycles should be known at this point!");119assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");120121MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;122if (RenameAs && RenameAs != RegID)123RegID = RenameAs;124125WriteRef &WR = RegisterMappings[RegID].first;126if (WR.getWriteState() == &WS)127WR.notifyExecuted(CurrentCycle);128129for (MCPhysReg I : MRI.subregs(RegID)) {130WriteRef &OtherWR = RegisterMappings[I].first;131if (OtherWR.getWriteState() == &WS)132OtherWR.notifyExecuted(CurrentCycle);133}134135if (!WS.clearsSuperRegisters())136continue;137138for (MCPhysReg I : MRI.superregs(RegID)) {139WriteRef &OtherWR = RegisterMappings[I].first;140if (OtherWR.getWriteState() == &WS)141OtherWR.notifyExecuted(CurrentCycle);142}143}144}145146void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,147ArrayRef<MCRegisterCostEntry> Entries) {148// A default register file is always allocated at index #0. That register file149// is mainly used to count the total number of mappings created by all150// register files at runtime. Users can limit the number of available physical151// registers in register file #0 through the command line flag152// `-register-file-size`.153unsigned RegisterFileIndex = RegisterFiles.size();154RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,155RF.AllowZeroMoveEliminationOnly);156157// Special case where there is no register class identifier in the set.158// An empty set of register classes means: this register file contains all159// the physical registers specified by the target.160// We optimistically assume that a register can be renamed at the cost of a161// single physical register. The constructor of RegisterFile ensures that162// a RegisterMapping exists for each logical register defined by the Target.163if (Entries.empty())164return;165166// Now update the cost of individual registers.167for (const MCRegisterCostEntry &RCE : Entries) {168const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);169for (const MCPhysReg Reg : RC) {170RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;171IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;172if (IPC.first && IPC.first != RegisterFileIndex) {173// The only register file that is allowed to overlap is the default174// register file at index #0. The analysis is inaccurate if register175// files overlap.176errs() << "warning: register " << MRI.getName(Reg)177<< " defined in multiple register files.";178}179IPC = std::make_pair(RegisterFileIndex, RCE.Cost);180Entry.RenameAs = Reg;181Entry.AllowMoveElimination = RCE.AllowMoveElimination;182183// Assume the same cost for each sub-register.184for (MCPhysReg I : MRI.subregs(Reg)) {185RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second;186if (!OtherEntry.IndexPlusCost.first &&187(!OtherEntry.RenameAs ||188MRI.isSuperRegister(I, OtherEntry.RenameAs))) {189OtherEntry.IndexPlusCost = IPC;190OtherEntry.RenameAs = Reg;191}192}193}194}195}196197void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,198MutableArrayRef<unsigned> UsedPhysRegs) {199unsigned RegisterFileIndex = Entry.IndexPlusCost.first;200unsigned Cost = Entry.IndexPlusCost.second;201if (RegisterFileIndex) {202RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];203RMT.NumUsedPhysRegs += Cost;204UsedPhysRegs[RegisterFileIndex] += Cost;205}206207// Now update the default register mapping tracker.208RegisterFiles[0].NumUsedPhysRegs += Cost;209UsedPhysRegs[0] += Cost;210}211212void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,213MutableArrayRef<unsigned> FreedPhysRegs) {214unsigned RegisterFileIndex = Entry.IndexPlusCost.first;215unsigned Cost = Entry.IndexPlusCost.second;216if (RegisterFileIndex) {217RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];218RMT.NumUsedPhysRegs -= Cost;219FreedPhysRegs[RegisterFileIndex] += Cost;220}221222// Now update the default register mapping tracker.223RegisterFiles[0].NumUsedPhysRegs -= Cost;224FreedPhysRegs[0] += Cost;225}226227void RegisterFile::addRegisterWrite(WriteRef Write,228MutableArrayRef<unsigned> UsedPhysRegs) {229WriteState &WS = *Write.getWriteState();230MCPhysReg RegID = WS.getRegisterID();231232// This allows InstrPostProcess to remove register Defs233// by setting their RegisterID to 0.234if (!RegID)235return;236237LLVM_DEBUG({238dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "239<< MRI.getName(RegID) << "]\n";240});241242// If RenameAs is equal to RegID, then RegID is subject to register renaming243// and false dependencies on RegID are all eliminated.244245// If RenameAs references the invalid register, then we optimistically assume246// that it can be renamed. In the absence of tablegen descriptors for register247// files, RenameAs is always set to the invalid register ID. In all other248// cases, RenameAs must be either equal to RegID, or it must reference a249// super-register of RegID.250251// If RenameAs is a super-register of RegID, then a write to RegID has always252// a false dependency on RenameAs. The only exception is for when the write253// implicitly clears the upper portion of the underlying register.254// If a write clears its super-registers, then it is renamed as `RenameAs`.255bool IsWriteZero = WS.isWriteZero();256bool IsEliminated = WS.isEliminated();257bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;258const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;259WS.setPRF(RRI.IndexPlusCost.first);260261if (RRI.RenameAs && RRI.RenameAs != RegID) {262RegID = RRI.RenameAs;263WriteRef &OtherWrite = RegisterMappings[RegID].first;264265if (!WS.clearsSuperRegisters()) {266// The processor keeps the definition of `RegID` together with register267// `RenameAs`. Since this partial write is not renamed, no physical268// register is allocated.269ShouldAllocatePhysRegs = false;270271WriteState *OtherWS = OtherWrite.getWriteState();272if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {273// This partial write has a false dependency on RenameAs.274assert(!IsEliminated && "Unexpected partial update!");275OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);276}277}278}279280// Update zero registers.281MCPhysReg ZeroRegisterID =282WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();283ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);284for (MCPhysReg I : MRI.subregs(ZeroRegisterID))285ZeroRegisters.setBitVal(I, IsWriteZero);286287// If this move has been eliminated, then method tryEliminateMoveOrSwap should288// have already updated all the register mappings.289if (!IsEliminated) {290// Check if this is one of multiple writes performed by this291// instruction to register RegID.292const WriteRef &OtherWrite = RegisterMappings[RegID].first;293const WriteState *OtherWS = OtherWrite.getWriteState();294if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {295if (OtherWS->getLatency() > WS.getLatency()) {296// Conservatively keep the slowest write on RegID.297if (ShouldAllocatePhysRegs)298allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);299return;300}301}302303// Update the mapping for register RegID including its sub-registers.304RegisterMappings[RegID].first = Write;305RegisterMappings[RegID].second.AliasRegID = 0U;306for (MCPhysReg I : MRI.subregs(RegID)) {307RegisterMappings[I].first = Write;308RegisterMappings[I].second.AliasRegID = 0U;309}310311// No physical registers are allocated for instructions that are optimized312// in hardware. For example, zero-latency data-dependency breaking313// instructions don't consume physical registers.314if (ShouldAllocatePhysRegs)315allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);316}317318if (!WS.clearsSuperRegisters())319return;320321for (MCPhysReg I : MRI.superregs(RegID)) {322if (!IsEliminated) {323RegisterMappings[I].first = Write;324RegisterMappings[I].second.AliasRegID = 0U;325}326327ZeroRegisters.setBitVal(I, IsWriteZero);328}329}330331void RegisterFile::removeRegisterWrite(332const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {333// Early exit if this write was eliminated. A write eliminated at register334// renaming stage generates an alias, and it is not added to the PRF.335if (WS.isEliminated())336return;337338MCPhysReg RegID = WS.getRegisterID();339340// This allows InstrPostProcess to remove register Defs341// by setting their RegisterID to 0.342if (!RegID)343return;344345assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&346"Invalidating a write of unknown cycles!");347assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");348349bool ShouldFreePhysRegs = !WS.isWriteZero();350MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;351if (RenameAs && RenameAs != RegID) {352RegID = RenameAs;353354if (!WS.clearsSuperRegisters()) {355// Keep the definition of `RegID` together with register `RenameAs`.356ShouldFreePhysRegs = false;357}358}359360if (ShouldFreePhysRegs)361freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);362363WriteRef &WR = RegisterMappings[RegID].first;364if (WR.getWriteState() == &WS)365WR.commit();366367for (MCPhysReg I : MRI.subregs(RegID)) {368WriteRef &OtherWR = RegisterMappings[I].first;369if (OtherWR.getWriteState() == &WS)370OtherWR.commit();371}372373if (!WS.clearsSuperRegisters())374return;375376for (MCPhysReg I : MRI.superregs(RegID)) {377WriteRef &OtherWR = RegisterMappings[I].first;378if (OtherWR.getWriteState() == &WS)379OtherWR.commit();380}381}382383bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,384unsigned RegisterFileIndex) const {385const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];386const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];387const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];388389// From and To must be owned by the PRF at index `RegisterFileIndex`.390const RegisterRenamingInfo &RRIFrom = RMFrom.second;391if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)392return false;393394const RegisterRenamingInfo &RRITo = RMTo.second;395if (RRITo.IndexPlusCost.first != RegisterFileIndex)396return false;397398// Early exit if the destination register is from a register class that399// doesn't allow move elimination.400if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)401return false;402403// We only allow move elimination for writes that update a full physical404// register. On X86, move elimination is possible with 32-bit general purpose405// registers because writes to those registers are not partial writes. If a406// register move is a partial write, then we conservatively assume that move407// elimination fails, since it would either trigger a partial update, or the408// issue of a merge opcode.409//410// Note that this constraint may be lifted in future. For example, we could411// make this model more flexible, and let users customize the set of registers412// (i.e. register classes) that allow move elimination.413//414// For now, we assume that there is a strong correlation between registers415// that allow move elimination, and how those same registers are renamed in416// hardware.417if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())418if (!WS.clearsSuperRegisters())419return false;420421bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];422return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);423}424425bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,426MutableArrayRef<ReadState> Reads) {427if (Writes.size() != Reads.size())428return false;429430// This logic assumes that writes and reads are contributed by a register move431// or a register swap operation. In particular, it assumes a simple register432// move if there is only one write. It assumes a swap operation if there are433// exactly two writes.434if (Writes.empty() || Writes.size() > 2)435return false;436437// All registers must be owned by the same PRF.438const RegisterRenamingInfo &RRInfo =439RegisterMappings[Writes[0].getRegisterID()].second;440unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;441RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];442443// Early exit if the PRF cannot eliminate more moves/xchg in this cycle.444if (RMT.MaxMoveEliminatedPerCycle &&445(RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)446return false;447448for (size_t I = 0, E = Writes.size(); I < E; ++I) {449const ReadState &RS = Reads[I];450const WriteState &WS = Writes[E - (I + 1)];451if (!canEliminateMove(WS, RS, RegisterFileIndex))452return false;453}454455for (size_t I = 0, E = Writes.size(); I < E; ++I) {456ReadState &RS = Reads[I];457WriteState &WS = Writes[E - (I + 1)];458459const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];460const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];461const RegisterRenamingInfo &RRIFrom = RMFrom.second;462const RegisterRenamingInfo &RRITo = RMTo.second;463464// Construct an alias.465MCPhysReg AliasedReg =466RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();467MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();468469const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;470if (RMAlias.AliasRegID)471AliasedReg = RMAlias.AliasRegID;472473RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;474for (MCPhysReg I : MRI.subregs(AliasReg))475RegisterMappings[I].second.AliasRegID = AliasedReg;476477if (ZeroRegisters[RS.getRegisterID()]) {478WS.setWriteZero();479RS.setReadZero();480}481482WS.setEliminated();483RMT.NumMoveEliminated++;484}485486return true;487}488489unsigned WriteRef::getWriteBackCycle() const {490assert(hasKnownWriteBackCycle() && "Instruction not executed!");491assert((!Write || Write->getCyclesLeft() <= 0) &&492"Inconsistent state found!");493return WriteBackCycle;494}495496unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {497assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");498return CurrentCycle - WR.getWriteBackCycle();499}500501void RegisterFile::collectWrites(502const MCSubtargetInfo &STI, const ReadState &RS,503SmallVectorImpl<WriteRef> &Writes,504SmallVectorImpl<WriteRef> &CommittedWrites) const {505const ReadDescriptor &RD = RS.getDescriptor();506const MCSchedModel &SM = STI.getSchedModel();507const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);508MCPhysReg RegID = RS.getRegisterID();509assert(RegID && RegID < RegisterMappings.size());510LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "511<< MRI.getName(RegID) << '\n');512513// Check if this is an alias.514const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;515if (RRI.AliasRegID)516RegID = RRI.AliasRegID;517518const WriteRef &WR = RegisterMappings[RegID].first;519if (WR.getWriteState()) {520Writes.push_back(WR);521} else if (WR.hasKnownWriteBackCycle()) {522unsigned WriteResID = WR.getWriteResourceID();523int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);524if (ReadAdvance < 0) {525unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);526if (Elapsed < static_cast<unsigned>(-ReadAdvance))527CommittedWrites.push_back(WR);528}529}530531// Handle potential partial register updates.532for (MCPhysReg I : MRI.subregs(RegID)) {533const WriteRef &WR = RegisterMappings[I].first;534if (WR.getWriteState()) {535Writes.push_back(WR);536} else if (WR.hasKnownWriteBackCycle()) {537unsigned WriteResID = WR.getWriteResourceID();538int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);539if (ReadAdvance < 0) {540unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);541if (Elapsed < static_cast<unsigned>(-ReadAdvance))542CommittedWrites.push_back(WR);543}544}545}546547// Remove duplicate entries and resize the input vector.548if (Writes.size() > 1) {549sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {550return Lhs.getWriteState() < Rhs.getWriteState();551});552auto It = llvm::unique(Writes);553Writes.resize(std::distance(Writes.begin(), It));554}555556LLVM_DEBUG({557for (const WriteRef &WR : Writes) {558const WriteState &WS = *WR.getWriteState();559dbgs() << "[PRF] Found a dependent use of Register "560<< MRI.getName(WS.getRegisterID()) << " (defined by instruction #"561<< WR.getSourceIndex() << ")\n";562}563});564}565566RegisterFile::RAWHazard567RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,568const ReadState &RS) const {569RAWHazard Hazard;570SmallVector<WriteRef, 4> Writes;571SmallVector<WriteRef, 4> CommittedWrites;572573const MCSchedModel &SM = STI.getSchedModel();574const ReadDescriptor &RD = RS.getDescriptor();575const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);576577collectWrites(STI, RS, Writes, CommittedWrites);578for (const WriteRef &WR : Writes) {579const WriteState *WS = WR.getWriteState();580unsigned WriteResID = WS->getWriteResourceID();581int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);582583if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {584if (Hazard.isValid())585continue;586587Hazard.RegisterID = WR.getRegisterID();588Hazard.CyclesLeft = UNKNOWN_CYCLES;589continue;590}591592int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;593if (CyclesLeft > 0) {594if (Hazard.CyclesLeft < CyclesLeft) {595Hazard.RegisterID = WR.getRegisterID();596Hazard.CyclesLeft = CyclesLeft;597}598}599}600Writes.clear();601602for (const WriteRef &WR : CommittedWrites) {603unsigned WriteResID = WR.getWriteResourceID();604int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);605int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));606int CyclesLeft = NegReadAdvance - Elapsed;607assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");608if (Hazard.CyclesLeft < CyclesLeft) {609Hazard.RegisterID = WR.getRegisterID();610Hazard.CyclesLeft = CyclesLeft;611}612}613614return Hazard;615}616617void RegisterFile::addRegisterRead(ReadState &RS,618const MCSubtargetInfo &STI) const {619MCPhysReg RegID = RS.getRegisterID();620const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;621RS.setPRF(RRI.IndexPlusCost.first);622if (RS.isIndependentFromDef())623return;624625if (ZeroRegisters[RS.getRegisterID()])626RS.setReadZero();627628SmallVector<WriteRef, 4> DependentWrites;629SmallVector<WriteRef, 4> CompletedWrites;630collectWrites(STI, RS, DependentWrites, CompletedWrites);631RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());632633// We know that this read depends on all the writes in DependentWrites.634// For each write, check if we have ReadAdvance information, and use it635// to figure out in how many cycles this read will be available.636const ReadDescriptor &RD = RS.getDescriptor();637const MCSchedModel &SM = STI.getSchedModel();638const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);639for (WriteRef &WR : DependentWrites) {640unsigned WriteResID = WR.getWriteResourceID();641WriteState &WS = *WR.getWriteState();642int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);643WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);644}645646for (WriteRef &WR : CompletedWrites) {647unsigned WriteResID = WR.getWriteResourceID();648assert(WR.hasKnownWriteBackCycle() && "Invalid write!");649assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);650unsigned ReadAdvance = static_cast<unsigned>(651-STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));652unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);653assert(Elapsed < ReadAdvance && "Should not have been added to the set!");654RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),655ReadAdvance - Elapsed);656}657}658659unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {660SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());661662// Find how many new mappings must be created for each register file.663for (const MCPhysReg RegID : Regs) {664const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;665const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;666if (Entry.first)667NumPhysRegs[Entry.first] += Entry.second;668NumPhysRegs[0] += Entry.second;669}670671unsigned Response = 0;672for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {673unsigned NumRegs = NumPhysRegs[I];674if (!NumRegs)675continue;676677const RegisterMappingTracker &RMT = RegisterFiles[I];678if (!RMT.NumPhysRegs) {679// The register file has an unbounded number of microarchitectural680// registers.681continue;682}683684if (RMT.NumPhysRegs < NumRegs) {685// The current register file is too small. This may occur if the number of686// microarchitectural registers in register file #0 was changed by the687// users via flag -reg-file-size. Alternatively, the scheduling model688// specified a too small number of registers for this register file.689LLVM_DEBUG(690dbgs() << "[PRF] Not enough registers in the register file.\n");691692// FIXME: Normalize the instruction register count to match the693// NumPhysRegs value. This is a highly unusual case, and is not expected694// to occur. This normalization is hiding an inconsistency in either the695// scheduling model or in the value that the user might have specified696// for NumPhysRegs.697NumRegs = RMT.NumPhysRegs;698}699700if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))701Response |= (1U << I);702}703704return Response;705}706707#ifndef NDEBUG708void WriteRef::dump() const {709dbgs() << "IID=" << getSourceIndex() << ' ';710if (isValid())711getWriteState()->dump();712else713dbgs() << "(null)";714}715716void RegisterFile::dump() const {717for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {718const RegisterMapping &RM = RegisterMappings[I];719const RegisterRenamingInfo &RRI = RM.second;720if (ZeroRegisters[I]) {721dbgs() << MRI.getName(I) << ", " << I722<< ", PRF=" << RRI.IndexPlusCost.first723<< ", Cost=" << RRI.IndexPlusCost.second724<< ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]725<< ",";726RM.first.dump();727dbgs() << '\n';728}729}730731for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {732dbgs() << "Register File #" << I;733const RegisterMappingTracker &RMT = RegisterFiles[I];734dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs735<< "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';736}737}738#endif739740} // namespace mca741} // namespace llvm742743744