751 lines · cpp
1//===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file defines a register mapping file class. This class is responsible11/// for managing hardware register files and the tracking of data dependencies12/// between registers.13///14//===----------------------------------------------------------------------===//15 16#include "llvm/MCA/HardwareUnits/RegisterFile.h"17#include "llvm/MCA/Instruction.h"18#include "llvm/Support/Debug.h"19 20#define DEBUG_TYPE "llvm-mca"21 22namespace llvm {23namespace mca {24 25const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();26 27static std::function<bool(MCPhysReg)>28isNonArtificial(const MCRegisterInfo &MRI) {29 return [&MRI](MCPhysReg R) { return !MRI.isArtificial(R); };30}31 32WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)33 : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),34 Write(WS) {}35 36void WriteRef::commit() {37 assert(Write && Write->isExecuted() && "Cannot commit before write back!");38 RegisterID = Write->getRegisterID();39 WriteResID = Write->getWriteResourceID();40 Write = nullptr;41}42 43void WriteRef::notifyExecuted(unsigned Cycle) {44 assert(Write && Write->isExecuted() && "Not executed!");45 WriteBackCycle = Cycle;46}47 48bool WriteRef::hasKnownWriteBackCycle() const {49 return isValid() && (!Write || Write->isExecuted());50}51 52bool WriteRef::isWriteZero() const {53 assert(isValid() && "Invalid null WriteState found!");54 return getWriteState()->isWriteZero();55}56 57unsigned WriteRef::getWriteResourceID() const {58 if (Write)59 return Write->getWriteResourceID();60 return WriteResID;61}62 63MCPhysReg WriteRef::getRegisterID() const {64 if (Write)65 return Write->getRegisterID();66 return RegisterID;67}68 69RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,70 unsigned NumRegs)71 : MRI(mri),72 RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),73 ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {74 initialize(SM, NumRegs);75}76 77void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {78 // Create a default register file that "sees" all the machine registers79 // declared by the target. The number of physical registers in the default80 // register file is set equal to `NumRegs`. A value of zero for `NumRegs`81 // means: this register file has an unbounded number of physical registers.82 RegisterFiles.emplace_back(NumRegs);83 if (!SM.hasExtraProcessorInfo())84 return;85 86 // For each user defined register file, allocate a RegisterMappingTracker87 // object. The size of every register file, as well as the mapping between88 // register files and register classes is specified via tablegen.89 const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();90 91 // Skip invalid register file at index 0.92 for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {93 const MCRegisterFileDesc &RF = Info.RegisterFiles[I];94 assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");95 96 // The cost of a register definition is equivalent to the number of97 // physical registers that are allocated at register renaming stage.98 unsigned Length = RF.NumRegisterCostEntries;99 const MCRegisterCostEntry *FirstElt =100 &Info.RegisterCostTable[RF.RegisterCostEntryIdx];101 addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));102 }103}104 105void RegisterFile::cycleStart() {106 for (RegisterMappingTracker &RMT : RegisterFiles)107 RMT.NumMoveEliminated = 0;108}109 110void RegisterFile::onInstructionExecuted(Instruction *IS) {111 assert(IS && IS->isExecuted() && "Unexpected internal state found!");112 for (WriteState &WS : IS->getDefs()) {113 if (WS.isEliminated())114 return;115 116 MCPhysReg RegID = WS.getRegisterID();117 118 // This allows InstrPostProcess to remove register Defs119 // by setting their RegisterID to 0.120 if (!RegID)121 continue;122 123 assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&124 "The number of cycles should be known at this point!");125 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");126 127 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;128 if (RenameAs && RenameAs != RegID)129 RegID = RenameAs;130 131 WriteRef &WR = RegisterMappings[RegID].first;132 if (WR.getWriteState() == &WS)133 WR.notifyExecuted(CurrentCycle);134 135 for (MCPhysReg I : MRI.subregs(RegID)) {136 WriteRef &OtherWR = RegisterMappings[I].first;137 if (OtherWR.getWriteState() == &WS)138 OtherWR.notifyExecuted(CurrentCycle);139 }140 141 if (!WS.clearsSuperRegisters())142 continue;143 144 for (MCPhysReg I : MRI.superregs(RegID)) {145 WriteRef &OtherWR = RegisterMappings[I].first;146 if (OtherWR.getWriteState() == &WS)147 OtherWR.notifyExecuted(CurrentCycle);148 }149 }150}151 152void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,153 ArrayRef<MCRegisterCostEntry> Entries) {154 // A default register file is always allocated at index #0. That register file155 // is mainly used to count the total number of mappings created by all156 // register files at runtime. Users can limit the number of available physical157 // registers in register file #0 through the command line flag158 // `-register-file-size`.159 unsigned RegisterFileIndex = RegisterFiles.size();160 RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,161 RF.AllowZeroMoveEliminationOnly);162 163 // Special case where there is no register class identifier in the set.164 // An empty set of register classes means: this register file contains all165 // the physical registers specified by the target.166 // We optimistically assume that a register can be renamed at the cost of a167 // single physical register. The constructor of RegisterFile ensures that168 // a RegisterMapping exists for each logical register defined by the Target.169 if (Entries.empty())170 return;171 172 // Now update the cost of individual registers.173 for (const MCRegisterCostEntry &RCE : Entries) {174 const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);175 for (const MCPhysReg Reg : RC) {176 RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;177 IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;178 if (IPC.first && IPC.first != RegisterFileIndex) {179 // The only register file that is allowed to overlap is the default180 // register file at index #0. The analysis is inaccurate if register181 // files overlap.182 errs() << "warning: register " << MRI.getName(Reg)183 << " defined in multiple register files.";184 }185 IPC = std::make_pair(RegisterFileIndex, RCE.Cost);186 Entry.RenameAs = Reg;187 Entry.AllowMoveElimination = RCE.AllowMoveElimination;188 189 // Assume the same cost for each sub-register.190 for (MCPhysReg I : MRI.subregs(Reg)) {191 RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second;192 if (!OtherEntry.IndexPlusCost.first &&193 (!OtherEntry.RenameAs ||194 MRI.isSuperRegister(I, OtherEntry.RenameAs))) {195 OtherEntry.IndexPlusCost = IPC;196 OtherEntry.RenameAs = Reg;197 }198 }199 }200 }201}202 203void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,204 MutableArrayRef<unsigned> UsedPhysRegs) {205 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;206 unsigned Cost = Entry.IndexPlusCost.second;207 if (RegisterFileIndex) {208 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];209 RMT.NumUsedPhysRegs += Cost;210 UsedPhysRegs[RegisterFileIndex] += Cost;211 }212 213 // Now update the default register mapping tracker.214 RegisterFiles[0].NumUsedPhysRegs += Cost;215 UsedPhysRegs[0] += Cost;216}217 218void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,219 MutableArrayRef<unsigned> FreedPhysRegs) {220 unsigned RegisterFileIndex = Entry.IndexPlusCost.first;221 unsigned Cost = Entry.IndexPlusCost.second;222 if (RegisterFileIndex) {223 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];224 RMT.NumUsedPhysRegs -= Cost;225 FreedPhysRegs[RegisterFileIndex] += Cost;226 }227 228 // Now update the default register mapping tracker.229 RegisterFiles[0].NumUsedPhysRegs -= Cost;230 FreedPhysRegs[0] += Cost;231}232 233void RegisterFile::addRegisterWrite(WriteRef Write,234 MutableArrayRef<unsigned> UsedPhysRegs) {235 WriteState &WS = *Write.getWriteState();236 MCPhysReg RegID = WS.getRegisterID();237 238 // This allows InstrPostProcess to remove register Defs239 // by setting their RegisterID to 0.240 if (!RegID)241 return;242 243 LLVM_DEBUG({244 dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "245 << MRI.getName(RegID) << "]\n";246 });247 248 // If RenameAs is equal to RegID, then RegID is subject to register renaming249 // and false dependencies on RegID are all eliminated.250 251 // If RenameAs references the invalid register, then we optimistically assume252 // that it can be renamed. In the absence of tablegen descriptors for register253 // files, RenameAs is always set to the invalid register ID. In all other254 // cases, RenameAs must be either equal to RegID, or it must reference a255 // super-register of RegID.256 257 // If RenameAs is a super-register of RegID, then a write to RegID has always258 // a false dependency on RenameAs. The only exception is for when the write259 // implicitly clears the upper portion of the underlying register.260 // If a write clears its super-registers, then it is renamed as `RenameAs`.261 bool IsWriteZero = WS.isWriteZero();262 bool IsEliminated = WS.isEliminated();263 bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;264 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;265 WS.setPRF(RRI.IndexPlusCost.first);266 267 if (RRI.RenameAs && RRI.RenameAs != RegID) {268 RegID = RRI.RenameAs;269 WriteRef &OtherWrite = RegisterMappings[RegID].first;270 271 if (!WS.clearsSuperRegisters()) {272 // The processor keeps the definition of `RegID` together with register273 // `RenameAs`. Since this partial write is not renamed, no physical274 // register is allocated.275 ShouldAllocatePhysRegs = false;276 277 WriteState *OtherWS = OtherWrite.getWriteState();278 if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {279 // This partial write has a false dependency on RenameAs.280 assert(!IsEliminated && "Unexpected partial update!");281 OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);282 }283 }284 }285 286 // Update zero registers.287 MCPhysReg ZeroRegisterID =288 WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();289 ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);290 for (MCPhysReg I :291 make_filter_range(MRI.subregs(ZeroRegisterID), isNonArtificial(MRI)))292 ZeroRegisters.setBitVal(I, IsWriteZero);293 294 // If this move has been eliminated, then method tryEliminateMoveOrSwap should295 // have already updated all the register mappings.296 if (!IsEliminated) {297 // Check if this is one of multiple writes performed by this298 // instruction to register RegID.299 const WriteRef &OtherWrite = RegisterMappings[RegID].first;300 const WriteState *OtherWS = OtherWrite.getWriteState();301 if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {302 if (OtherWS->getLatency() > WS.getLatency()) {303 // Conservatively keep the slowest write on RegID.304 if (ShouldAllocatePhysRegs)305 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);306 return;307 }308 }309 310 // Update the mapping for register RegID including its sub-registers.311 RegisterMappings[RegID].first = Write;312 RegisterMappings[RegID].second.AliasRegID = 0U;313 for (MCPhysReg I :314 make_filter_range(MRI.subregs(RegID), isNonArtificial(MRI))) {315 RegisterMappings[I].first = Write;316 RegisterMappings[I].second.AliasRegID = 0U;317 }318 319 // No physical registers are allocated for instructions that are optimized320 // in hardware. For example, zero-latency data-dependency breaking321 // instructions don't consume physical registers.322 if (ShouldAllocatePhysRegs)323 allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);324 }325 326 if (!WS.clearsSuperRegisters())327 return;328 329 for (MCPhysReg I : MRI.superregs(RegID)) {330 if (!IsEliminated) {331 RegisterMappings[I].first = Write;332 RegisterMappings[I].second.AliasRegID = 0U;333 }334 335 ZeroRegisters.setBitVal(I, IsWriteZero);336 }337}338 339void RegisterFile::removeRegisterWrite(340 const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {341 // Early exit if this write was eliminated. A write eliminated at register342 // renaming stage generates an alias, and it is not added to the PRF.343 if (WS.isEliminated())344 return;345 346 MCPhysReg RegID = WS.getRegisterID();347 348 // This allows InstrPostProcess to remove register Defs349 // by setting their RegisterID to 0.350 if (!RegID)351 return;352 353 assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&354 "Invalidating a write of unknown cycles!");355 assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");356 357 bool ShouldFreePhysRegs = !WS.isWriteZero();358 MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;359 if (RenameAs && RenameAs != RegID) {360 RegID = RenameAs;361 362 if (!WS.clearsSuperRegisters()) {363 // Keep the definition of `RegID` together with register `RenameAs`.364 ShouldFreePhysRegs = false;365 }366 }367 368 if (ShouldFreePhysRegs)369 freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);370 371 WriteRef &WR = RegisterMappings[RegID].first;372 if (WR.getWriteState() == &WS)373 WR.commit();374 375 for (MCPhysReg I : MRI.subregs(RegID)) {376 WriteRef &OtherWR = RegisterMappings[I].first;377 if (OtherWR.getWriteState() == &WS)378 OtherWR.commit();379 }380 381 if (!WS.clearsSuperRegisters())382 return;383 384 for (MCPhysReg I : MRI.superregs(RegID)) {385 WriteRef &OtherWR = RegisterMappings[I].first;386 if (OtherWR.getWriteState() == &WS)387 OtherWR.commit();388 }389}390 391bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,392 unsigned RegisterFileIndex) const {393 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];394 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];395 const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];396 397 // From and To must be owned by the PRF at index `RegisterFileIndex`.398 const RegisterRenamingInfo &RRIFrom = RMFrom.second;399 if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)400 return false;401 402 const RegisterRenamingInfo &RRITo = RMTo.second;403 if (RRITo.IndexPlusCost.first != RegisterFileIndex)404 return false;405 406 // Early exit if the destination register is from a register class that407 // doesn't allow move elimination.408 if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)409 return false;410 411 // We only allow move elimination for writes that update a full physical412 // register. On X86, move elimination is possible with 32-bit general purpose413 // registers because writes to those registers are not partial writes. If a414 // register move is a partial write, then we conservatively assume that move415 // elimination fails, since it would either trigger a partial update, or the416 // issue of a merge opcode.417 //418 // Note that this constraint may be lifted in future. For example, we could419 // make this model more flexible, and let users customize the set of registers420 // (i.e. register classes) that allow move elimination.421 //422 // For now, we assume that there is a strong correlation between registers423 // that allow move elimination, and how those same registers are renamed in424 // hardware.425 if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())426 if (!WS.clearsSuperRegisters())427 return false;428 429 bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];430 return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);431}432 433bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,434 MutableArrayRef<ReadState> Reads) {435 if (Writes.size() != Reads.size())436 return false;437 438 // This logic assumes that writes and reads are contributed by a register move439 // or a register swap operation. In particular, it assumes a simple register440 // move if there is only one write. It assumes a swap operation if there are441 // exactly two writes.442 if (Writes.empty() || Writes.size() > 2)443 return false;444 445 // All registers must be owned by the same PRF.446 const RegisterRenamingInfo &RRInfo =447 RegisterMappings[Writes[0].getRegisterID()].second;448 unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;449 RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];450 451 // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.452 if (RMT.MaxMoveEliminatedPerCycle &&453 (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)454 return false;455 456 for (size_t I = 0, E = Writes.size(); I < E; ++I) {457 const ReadState &RS = Reads[I];458 const WriteState &WS = Writes[E - (I + 1)];459 if (!canEliminateMove(WS, RS, RegisterFileIndex))460 return false;461 }462 463 for (size_t I = 0, E = Writes.size(); I < E; ++I) {464 ReadState &RS = Reads[I];465 WriteState &WS = Writes[E - (I + 1)];466 467 const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];468 const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];469 const RegisterRenamingInfo &RRIFrom = RMFrom.second;470 const RegisterRenamingInfo &RRITo = RMTo.second;471 472 // Construct an alias.473 MCPhysReg AliasedReg =474 RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();475 MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();476 477 const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;478 if (RMAlias.AliasRegID)479 AliasedReg = RMAlias.AliasRegID;480 481 RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;482 for (MCPhysReg I :483 make_filter_range(MRI.subregs(AliasReg), isNonArtificial(MRI)))484 RegisterMappings[I].second.AliasRegID = AliasedReg;485 486 if (ZeroRegisters[RS.getRegisterID()]) {487 WS.setWriteZero();488 RS.setReadZero();489 }490 491 WS.setEliminated();492 RMT.NumMoveEliminated++;493 }494 495 return true;496}497 498unsigned WriteRef::getWriteBackCycle() const {499 assert(hasKnownWriteBackCycle() && "Instruction not executed!");500 assert((!Write || Write->getCyclesLeft() <= 0) &&501 "Inconsistent state found!");502 return WriteBackCycle;503}504 505unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {506 assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");507 return CurrentCycle - WR.getWriteBackCycle();508}509 510void RegisterFile::collectWrites(511 const MCSubtargetInfo &STI, const ReadState &RS,512 SmallVectorImpl<WriteRef> &Writes,513 SmallVectorImpl<WriteRef> &CommittedWrites) const {514 const ReadDescriptor &RD = RS.getDescriptor();515 const MCSchedModel &SM = STI.getSchedModel();516 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);517 MCPhysReg RegID = RS.getRegisterID();518 assert(RegID && RegID < RegisterMappings.size());519 LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "520 << MRI.getName(RegID) << '\n');521 522 // Check if this is an alias.523 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;524 if (RRI.AliasRegID)525 RegID = RRI.AliasRegID;526 527 const WriteRef &WR = RegisterMappings[RegID].first;528 if (WR.getWriteState()) {529 Writes.push_back(WR);530 } else if (WR.hasKnownWriteBackCycle()) {531 unsigned WriteResID = WR.getWriteResourceID();532 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);533 if (ReadAdvance < 0) {534 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);535 if (Elapsed < static_cast<unsigned>(-ReadAdvance))536 CommittedWrites.push_back(WR);537 }538 }539 540 // Handle potential partial register updates.541 for (MCPhysReg I : MRI.subregs(RegID)) {542 const WriteRef &WR = RegisterMappings[I].first;543 if (WR.getWriteState()) {544 Writes.push_back(WR);545 } else if (WR.hasKnownWriteBackCycle()) {546 unsigned WriteResID = WR.getWriteResourceID();547 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);548 if (ReadAdvance < 0) {549 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);550 if (Elapsed < static_cast<unsigned>(-ReadAdvance))551 CommittedWrites.push_back(WR);552 }553 }554 }555 556 // Remove duplicate entries and resize the input vector.557 if (Writes.size() > 1) {558 sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {559 return Lhs.getWriteState() < Rhs.getWriteState();560 });561 auto It = llvm::unique(Writes);562 Writes.resize(std::distance(Writes.begin(), It));563 }564 565 LLVM_DEBUG({566 for (const WriteRef &WR : Writes) {567 const WriteState &WS = *WR.getWriteState();568 dbgs() << "[PRF] Found a dependent use of Register "569 << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"570 << WR.getSourceIndex() << ")\n";571 }572 });573}574 575RegisterFile::RAWHazard576RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,577 const ReadState &RS) const {578 RAWHazard Hazard;579 SmallVector<WriteRef, 4> Writes;580 SmallVector<WriteRef, 4> CommittedWrites;581 582 const MCSchedModel &SM = STI.getSchedModel();583 const ReadDescriptor &RD = RS.getDescriptor();584 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);585 586 collectWrites(STI, RS, Writes, CommittedWrites);587 for (const WriteRef &WR : Writes) {588 const WriteState *WS = WR.getWriteState();589 unsigned WriteResID = WS->getWriteResourceID();590 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);591 592 if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {593 if (Hazard.isValid())594 continue;595 596 Hazard.RegisterID = WR.getRegisterID();597 Hazard.CyclesLeft = UNKNOWN_CYCLES;598 continue;599 }600 601 int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;602 if (CyclesLeft > 0) {603 if (Hazard.CyclesLeft < CyclesLeft) {604 Hazard.RegisterID = WR.getRegisterID();605 Hazard.CyclesLeft = CyclesLeft;606 }607 }608 }609 Writes.clear();610 611 for (const WriteRef &WR : CommittedWrites) {612 unsigned WriteResID = WR.getWriteResourceID();613 int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);614 int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));615 int CyclesLeft = NegReadAdvance - Elapsed;616 assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");617 if (Hazard.CyclesLeft < CyclesLeft) {618 Hazard.RegisterID = WR.getRegisterID();619 Hazard.CyclesLeft = CyclesLeft;620 }621 }622 623 return Hazard;624}625 626void RegisterFile::addRegisterRead(ReadState &RS,627 const MCSubtargetInfo &STI) const {628 MCPhysReg RegID = RS.getRegisterID();629 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;630 RS.setPRF(RRI.IndexPlusCost.first);631 if (RS.isIndependentFromDef())632 return;633 634 if (ZeroRegisters[RS.getRegisterID()])635 RS.setReadZero();636 637 SmallVector<WriteRef, 4> DependentWrites;638 SmallVector<WriteRef, 4> CompletedWrites;639 collectWrites(STI, RS, DependentWrites, CompletedWrites);640 RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());641 642 // We know that this read depends on all the writes in DependentWrites.643 // For each write, check if we have ReadAdvance information, and use it644 // to figure out in how many cycles this read will be available.645 const ReadDescriptor &RD = RS.getDescriptor();646 const MCSchedModel &SM = STI.getSchedModel();647 const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);648 for (WriteRef &WR : DependentWrites) {649 unsigned WriteResID = WR.getWriteResourceID();650 WriteState &WS = *WR.getWriteState();651 int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);652 WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);653 }654 655 for (WriteRef &WR : CompletedWrites) {656 unsigned WriteResID = WR.getWriteResourceID();657 assert(WR.hasKnownWriteBackCycle() && "Invalid write!");658 assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);659 unsigned ReadAdvance = static_cast<unsigned>(660 -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));661 unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);662 assert(Elapsed < ReadAdvance && "Should not have been added to the set!");663 RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),664 ReadAdvance - Elapsed);665 }666}667 668unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {669 SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());670 671 // Find how many new mappings must be created for each register file.672 for (const MCPhysReg RegID : Regs) {673 const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;674 const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;675 if (Entry.first)676 NumPhysRegs[Entry.first] += Entry.second;677 NumPhysRegs[0] += Entry.second;678 }679 680 unsigned Response = 0;681 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {682 unsigned NumRegs = NumPhysRegs[I];683 if (!NumRegs)684 continue;685 686 const RegisterMappingTracker &RMT = RegisterFiles[I];687 if (!RMT.NumPhysRegs) {688 // The register file has an unbounded number of microarchitectural689 // registers.690 continue;691 }692 693 if (RMT.NumPhysRegs < NumRegs) {694 // The current register file is too small. This may occur if the number of695 // microarchitectural registers in register file #0 was changed by the696 // users via flag -reg-file-size. Alternatively, the scheduling model697 // specified a too small number of registers for this register file.698 LLVM_DEBUG(699 dbgs() << "[PRF] Not enough registers in the register file.\n");700 701 // FIXME: Normalize the instruction register count to match the702 // NumPhysRegs value. This is a highly unusual case, and is not expected703 // to occur. This normalization is hiding an inconsistency in either the704 // scheduling model or in the value that the user might have specified705 // for NumPhysRegs.706 NumRegs = RMT.NumPhysRegs;707 }708 709 if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))710 Response |= (1U << I);711 }712 713 return Response;714}715 716#ifndef NDEBUG717void WriteRef::dump() const {718 dbgs() << "IID=" << getSourceIndex() << ' ';719 if (isValid())720 getWriteState()->dump();721 else722 dbgs() << "(null)";723}724 725void RegisterFile::dump() const {726 for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {727 const RegisterMapping &RM = RegisterMappings[I];728 const RegisterRenamingInfo &RRI = RM.second;729 if (ZeroRegisters[I]) {730 dbgs() << MRI.getName(I) << ", " << I731 << ", PRF=" << RRI.IndexPlusCost.first732 << ", Cost=" << RRI.IndexPlusCost.second733 << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]734 << ",";735 RM.first.dump();736 dbgs() << '\n';737 }738 }739 740 for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {741 dbgs() << "Register File #" << I;742 const RegisterMappingTracker &RMT = RegisterFiles[I];743 dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs744 << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';745 }746}747#endif748 749} // namespace mca750} // namespace llvm751