10b57cec5SDimitry Andric //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This file defines a register mapping file class. This class is responsible 110b57cec5SDimitry Andric /// for managing hardware register files and the tracking of data dependencies 120b57cec5SDimitry Andric /// between registers. 130b57cec5SDimitry Andric /// 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/MCA/HardwareUnits/RegisterFile.h" 170b57cec5SDimitry Andric #include "llvm/MCA/Instruction.h" 180b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #define DEBUG_TYPE "llvm-mca" 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric namespace llvm { 230b57cec5SDimitry Andric namespace mca { 240b57cec5SDimitry Andric 25fe6060f1SDimitry Andric const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max(); 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS) 28fe6060f1SDimitry Andric : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(), 29fe6060f1SDimitry Andric Write(WS) {} 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric void WriteRef::commit() { 32fe6060f1SDimitry Andric assert(Write && Write->isExecuted() && "Cannot commit before write back!"); 33fe6060f1SDimitry Andric RegisterID = Write->getRegisterID(); 34fe6060f1SDimitry Andric WriteResID = Write->getWriteResourceID(); 35fe6060f1SDimitry Andric Write = nullptr; 36fe6060f1SDimitry Andric } 37fe6060f1SDimitry Andric 38fe6060f1SDimitry Andric void WriteRef::notifyExecuted(unsigned Cycle) { 39fe6060f1SDimitry Andric assert(Write && Write->isExecuted() && "Not executed!"); 40fe6060f1SDimitry Andric WriteBackCycle = Cycle; 41fe6060f1SDimitry Andric } 42fe6060f1SDimitry Andric 43fe6060f1SDimitry Andric bool WriteRef::hasKnownWriteBackCycle() const { 44fe6060f1SDimitry Andric return isValid() && (!Write || Write->isExecuted()); 45fe6060f1SDimitry Andric } 46fe6060f1SDimitry Andric 47fe6060f1SDimitry Andric bool WriteRef::isWriteZero() const { 48fe6060f1SDimitry Andric assert(isValid() && "Invalid null WriteState found!"); 49fe6060f1SDimitry Andric return getWriteState()->isWriteZero(); 50fe6060f1SDimitry Andric } 51fe6060f1SDimitry Andric 52fe6060f1SDimitry Andric unsigned WriteRef::getWriteResourceID() const { 53fe6060f1SDimitry Andric if (Write) 54fe6060f1SDimitry Andric return Write->getWriteResourceID(); 55fe6060f1SDimitry Andric return WriteResID; 56fe6060f1SDimitry Andric } 57fe6060f1SDimitry Andric 58fe6060f1SDimitry Andric MCPhysReg WriteRef::getRegisterID() const { 59fe6060f1SDimitry Andric if (Write) 60fe6060f1SDimitry Andric return Write->getRegisterID(); 61fe6060f1SDimitry Andric return RegisterID; 62fe6060f1SDimitry Andric } 63fe6060f1SDimitry Andric 640b57cec5SDimitry Andric RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri, 650b57cec5SDimitry Andric unsigned NumRegs) 660b57cec5SDimitry Andric : MRI(mri), 670b57cec5SDimitry Andric RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}), 68fe6060f1SDimitry Andric ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() { 690b57cec5SDimitry Andric initialize(SM, NumRegs); 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) { 730b57cec5SDimitry Andric // Create a default register file that "sees" all the machine registers 740b57cec5SDimitry Andric // declared by the target. The number of physical registers in the default 750b57cec5SDimitry Andric // register file is set equal to `NumRegs`. A value of zero for `NumRegs` 760b57cec5SDimitry Andric // means: this register file has an unbounded number of physical registers. 770b57cec5SDimitry Andric RegisterFiles.emplace_back(NumRegs); 780b57cec5SDimitry Andric if (!SM.hasExtraProcessorInfo()) 790b57cec5SDimitry Andric return; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric // For each user defined register file, allocate a RegisterMappingTracker 820b57cec5SDimitry Andric // object. The size of every register file, as well as the mapping between 830b57cec5SDimitry Andric // register files and register classes is specified via tablegen. 840b57cec5SDimitry Andric const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo(); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // Skip invalid register file at index 0. 870b57cec5SDimitry Andric for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) { 880b57cec5SDimitry Andric const MCRegisterFileDesc &RF = Info.RegisterFiles[I]; 890b57cec5SDimitry Andric assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!"); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // The cost of a register definition is equivalent to the number of 920b57cec5SDimitry Andric // physical registers that are allocated at register renaming stage. 930b57cec5SDimitry Andric unsigned Length = RF.NumRegisterCostEntries; 940b57cec5SDimitry Andric const MCRegisterCostEntry *FirstElt = 950b57cec5SDimitry Andric &Info.RegisterCostTable[RF.RegisterCostEntryIdx]; 960b57cec5SDimitry Andric addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length)); 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric void RegisterFile::cycleStart() { 1010b57cec5SDimitry Andric for (RegisterMappingTracker &RMT : RegisterFiles) 1020b57cec5SDimitry Andric RMT.NumMoveEliminated = 0; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 105fe6060f1SDimitry Andric void RegisterFile::onInstructionExecuted(Instruction *IS) { 106fe6060f1SDimitry Andric assert(IS && IS->isExecuted() && "Unexpected internal state found!"); 107fe6060f1SDimitry Andric for (WriteState &WS : IS->getDefs()) { 108fe6060f1SDimitry Andric if (WS.isEliminated()) 109fe6060f1SDimitry Andric return; 110fe6060f1SDimitry Andric 111fe6060f1SDimitry Andric MCPhysReg RegID = WS.getRegisterID(); 112fe6060f1SDimitry Andric 113fe6060f1SDimitry Andric // This allows InstrPostProcess to remove register Defs 114fe6060f1SDimitry Andric // by setting their RegisterID to 0. 115fe6060f1SDimitry Andric if (!RegID) 116fe6060f1SDimitry Andric continue; 117fe6060f1SDimitry Andric 118fe6060f1SDimitry Andric assert(WS.getCyclesLeft() != UNKNOWN_CYCLES && 119fe6060f1SDimitry Andric "The number of cycles should be known at this point!"); 120fe6060f1SDimitry Andric assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!"); 121fe6060f1SDimitry Andric 122fe6060f1SDimitry Andric MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs; 123fe6060f1SDimitry Andric if (RenameAs && RenameAs != RegID) 124fe6060f1SDimitry Andric RegID = RenameAs; 125fe6060f1SDimitry Andric 126fe6060f1SDimitry Andric WriteRef &WR = RegisterMappings[RegID].first; 127fe6060f1SDimitry Andric if (WR.getWriteState() == &WS) 128fe6060f1SDimitry Andric WR.notifyExecuted(CurrentCycle); 129fe6060f1SDimitry Andric 13006c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(RegID)) { 13106c3fb27SDimitry Andric WriteRef &OtherWR = RegisterMappings[I].first; 132fe6060f1SDimitry Andric if (OtherWR.getWriteState() == &WS) 133fe6060f1SDimitry Andric OtherWR.notifyExecuted(CurrentCycle); 134fe6060f1SDimitry Andric } 135fe6060f1SDimitry Andric 136fe6060f1SDimitry Andric if (!WS.clearsSuperRegisters()) 137fe6060f1SDimitry Andric continue; 138fe6060f1SDimitry Andric 13906c3fb27SDimitry Andric for (MCPhysReg I : MRI.superregs(RegID)) { 14006c3fb27SDimitry Andric WriteRef &OtherWR = RegisterMappings[I].first; 141fe6060f1SDimitry Andric if (OtherWR.getWriteState() == &WS) 142fe6060f1SDimitry Andric OtherWR.notifyExecuted(CurrentCycle); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric } 145fe6060f1SDimitry Andric } 146fe6060f1SDimitry Andric 1470b57cec5SDimitry Andric void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF, 1480b57cec5SDimitry Andric ArrayRef<MCRegisterCostEntry> Entries) { 1490b57cec5SDimitry Andric // A default register file is always allocated at index #0. That register file 1500b57cec5SDimitry Andric // is mainly used to count the total number of mappings created by all 1510b57cec5SDimitry Andric // register files at runtime. Users can limit the number of available physical 1520b57cec5SDimitry Andric // registers in register file #0 through the command line flag 1530b57cec5SDimitry Andric // `-register-file-size`. 1540b57cec5SDimitry Andric unsigned RegisterFileIndex = RegisterFiles.size(); 1550b57cec5SDimitry Andric RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle, 1560b57cec5SDimitry Andric RF.AllowZeroMoveEliminationOnly); 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric // Special case where there is no register class identifier in the set. 1590b57cec5SDimitry Andric // An empty set of register classes means: this register file contains all 1600b57cec5SDimitry Andric // the physical registers specified by the target. 1610b57cec5SDimitry Andric // We optimistically assume that a register can be renamed at the cost of a 1620b57cec5SDimitry Andric // single physical register. The constructor of RegisterFile ensures that 1630b57cec5SDimitry Andric // a RegisterMapping exists for each logical register defined by the Target. 1640b57cec5SDimitry Andric if (Entries.empty()) 1650b57cec5SDimitry Andric return; 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric // Now update the cost of individual registers. 1680b57cec5SDimitry Andric for (const MCRegisterCostEntry &RCE : Entries) { 1690b57cec5SDimitry Andric const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID); 1700b57cec5SDimitry Andric for (const MCPhysReg Reg : RC) { 1710b57cec5SDimitry Andric RegisterRenamingInfo &Entry = RegisterMappings[Reg].second; 1720b57cec5SDimitry Andric IndexPlusCostPairTy &IPC = Entry.IndexPlusCost; 1730b57cec5SDimitry Andric if (IPC.first && IPC.first != RegisterFileIndex) { 1740b57cec5SDimitry Andric // The only register file that is allowed to overlap is the default 1750b57cec5SDimitry Andric // register file at index #0. The analysis is inaccurate if register 1760b57cec5SDimitry Andric // files overlap. 1770b57cec5SDimitry Andric errs() << "warning: register " << MRI.getName(Reg) 1780b57cec5SDimitry Andric << " defined in multiple register files."; 1790b57cec5SDimitry Andric } 1800b57cec5SDimitry Andric IPC = std::make_pair(RegisterFileIndex, RCE.Cost); 1810b57cec5SDimitry Andric Entry.RenameAs = Reg; 1820b57cec5SDimitry Andric Entry.AllowMoveElimination = RCE.AllowMoveElimination; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Assume the same cost for each sub-register. 18506c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(Reg)) { 18606c3fb27SDimitry Andric RegisterRenamingInfo &OtherEntry = RegisterMappings[I].second; 1870b57cec5SDimitry Andric if (!OtherEntry.IndexPlusCost.first && 1880b57cec5SDimitry Andric (!OtherEntry.RenameAs || 18906c3fb27SDimitry Andric MRI.isSuperRegister(I, OtherEntry.RenameAs))) { 1900b57cec5SDimitry Andric OtherEntry.IndexPlusCost = IPC; 1910b57cec5SDimitry Andric OtherEntry.RenameAs = Reg; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry, 1990b57cec5SDimitry Andric MutableArrayRef<unsigned> UsedPhysRegs) { 2000b57cec5SDimitry Andric unsigned RegisterFileIndex = Entry.IndexPlusCost.first; 2010b57cec5SDimitry Andric unsigned Cost = Entry.IndexPlusCost.second; 2020b57cec5SDimitry Andric if (RegisterFileIndex) { 2030b57cec5SDimitry Andric RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; 2040b57cec5SDimitry Andric RMT.NumUsedPhysRegs += Cost; 2050b57cec5SDimitry Andric UsedPhysRegs[RegisterFileIndex] += Cost; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Now update the default register mapping tracker. 2090b57cec5SDimitry Andric RegisterFiles[0].NumUsedPhysRegs += Cost; 2100b57cec5SDimitry Andric UsedPhysRegs[0] += Cost; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry, 2140b57cec5SDimitry Andric MutableArrayRef<unsigned> FreedPhysRegs) { 2150b57cec5SDimitry Andric unsigned RegisterFileIndex = Entry.IndexPlusCost.first; 2160b57cec5SDimitry Andric unsigned Cost = Entry.IndexPlusCost.second; 2170b57cec5SDimitry Andric if (RegisterFileIndex) { 2180b57cec5SDimitry Andric RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; 2190b57cec5SDimitry Andric RMT.NumUsedPhysRegs -= Cost; 2200b57cec5SDimitry Andric FreedPhysRegs[RegisterFileIndex] += Cost; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric // Now update the default register mapping tracker. 2240b57cec5SDimitry Andric RegisterFiles[0].NumUsedPhysRegs -= Cost; 2250b57cec5SDimitry Andric FreedPhysRegs[0] += Cost; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void RegisterFile::addRegisterWrite(WriteRef Write, 2290b57cec5SDimitry Andric MutableArrayRef<unsigned> UsedPhysRegs) { 2300b57cec5SDimitry Andric WriteState &WS = *Write.getWriteState(); 2318bcb0991SDimitry Andric MCPhysReg RegID = WS.getRegisterID(); 232fe6060f1SDimitry Andric 233fe6060f1SDimitry Andric // This allows InstrPostProcess to remove register Defs 234fe6060f1SDimitry Andric // by setting their RegisterID to 0. 235fe6060f1SDimitry Andric if (!RegID) 236fe6060f1SDimitry Andric return; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric LLVM_DEBUG({ 239fe6060f1SDimitry Andric dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", " 240fe6060f1SDimitry Andric << MRI.getName(RegID) << "]\n"; 2410b57cec5SDimitry Andric }); 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // If RenameAs is equal to RegID, then RegID is subject to register renaming 2440b57cec5SDimitry Andric // and false dependencies on RegID are all eliminated. 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric // If RenameAs references the invalid register, then we optimistically assume 2470b57cec5SDimitry Andric // that it can be renamed. In the absence of tablegen descriptors for register 2480b57cec5SDimitry Andric // files, RenameAs is always set to the invalid register ID. In all other 2490b57cec5SDimitry Andric // cases, RenameAs must be either equal to RegID, or it must reference a 2500b57cec5SDimitry Andric // super-register of RegID. 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // If RenameAs is a super-register of RegID, then a write to RegID has always 2530b57cec5SDimitry Andric // a false dependency on RenameAs. The only exception is for when the write 2540b57cec5SDimitry Andric // implicitly clears the upper portion of the underlying register. 2550b57cec5SDimitry Andric // If a write clears its super-registers, then it is renamed as `RenameAs`. 2560b57cec5SDimitry Andric bool IsWriteZero = WS.isWriteZero(); 2570b57cec5SDimitry Andric bool IsEliminated = WS.isEliminated(); 2580b57cec5SDimitry Andric bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated; 2590b57cec5SDimitry Andric const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second; 2600b57cec5SDimitry Andric WS.setPRF(RRI.IndexPlusCost.first); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric if (RRI.RenameAs && RRI.RenameAs != RegID) { 2630b57cec5SDimitry Andric RegID = RRI.RenameAs; 2640b57cec5SDimitry Andric WriteRef &OtherWrite = RegisterMappings[RegID].first; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric if (!WS.clearsSuperRegisters()) { 2670b57cec5SDimitry Andric // The processor keeps the definition of `RegID` together with register 2680b57cec5SDimitry Andric // `RenameAs`. Since this partial write is not renamed, no physical 2690b57cec5SDimitry Andric // register is allocated. 2700b57cec5SDimitry Andric ShouldAllocatePhysRegs = false; 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric WriteState *OtherWS = OtherWrite.getWriteState(); 2730b57cec5SDimitry Andric if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) { 2740b57cec5SDimitry Andric // This partial write has a false dependency on RenameAs. 2750b57cec5SDimitry Andric assert(!IsEliminated && "Unexpected partial update!"); 2760b57cec5SDimitry Andric OtherWS->addUser(OtherWrite.getSourceIndex(), &WS); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric // Update zero registers. 2828bcb0991SDimitry Andric MCPhysReg ZeroRegisterID = 2830b57cec5SDimitry Andric WS.clearsSuperRegisters() ? RegID : WS.getRegisterID(); 284e8d8bef9SDimitry Andric ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero); 28506c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(ZeroRegisterID)) 28606c3fb27SDimitry Andric ZeroRegisters.setBitVal(I, IsWriteZero); 2870b57cec5SDimitry Andric 288fe6060f1SDimitry Andric // If this move has been eliminated, then method tryEliminateMoveOrSwap should 289fe6060f1SDimitry Andric // have already updated all the register mappings. 2900b57cec5SDimitry Andric if (!IsEliminated) { 291349cc55cSDimitry Andric // Check if this is one of multiple writes performed by this 292349cc55cSDimitry Andric // instruction to register RegID. 293349cc55cSDimitry Andric const WriteRef &OtherWrite = RegisterMappings[RegID].first; 294349cc55cSDimitry Andric const WriteState *OtherWS = OtherWrite.getWriteState(); 295349cc55cSDimitry Andric if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) { 296349cc55cSDimitry Andric if (OtherWS->getLatency() > WS.getLatency()) { 297349cc55cSDimitry Andric // Conservatively keep the slowest write on RegID. 298349cc55cSDimitry Andric if (ShouldAllocatePhysRegs) 299349cc55cSDimitry Andric allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs); 300349cc55cSDimitry Andric return; 301349cc55cSDimitry Andric } 302349cc55cSDimitry Andric } 303349cc55cSDimitry Andric 3040b57cec5SDimitry Andric // Update the mapping for register RegID including its sub-registers. 3050b57cec5SDimitry Andric RegisterMappings[RegID].first = Write; 3060b57cec5SDimitry Andric RegisterMappings[RegID].second.AliasRegID = 0U; 30706c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(RegID)) { 30806c3fb27SDimitry Andric RegisterMappings[I].first = Write; 30906c3fb27SDimitry Andric RegisterMappings[I].second.AliasRegID = 0U; 3100b57cec5SDimitry Andric } 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // No physical registers are allocated for instructions that are optimized 3130b57cec5SDimitry Andric // in hardware. For example, zero-latency data-dependency breaking 3140b57cec5SDimitry Andric // instructions don't consume physical registers. 3150b57cec5SDimitry Andric if (ShouldAllocatePhysRegs) 3160b57cec5SDimitry Andric allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs); 3170b57cec5SDimitry Andric } 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric if (!WS.clearsSuperRegisters()) 3200b57cec5SDimitry Andric return; 3210b57cec5SDimitry Andric 32206c3fb27SDimitry Andric for (MCPhysReg I : MRI.superregs(RegID)) { 3230b57cec5SDimitry Andric if (!IsEliminated) { 32406c3fb27SDimitry Andric RegisterMappings[I].first = Write; 32506c3fb27SDimitry Andric RegisterMappings[I].second.AliasRegID = 0U; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric 32806c3fb27SDimitry Andric ZeroRegisters.setBitVal(I, IsWriteZero); 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric void RegisterFile::removeRegisterWrite( 3330b57cec5SDimitry Andric const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) { 3340b57cec5SDimitry Andric // Early exit if this write was eliminated. A write eliminated at register 3350b57cec5SDimitry Andric // renaming stage generates an alias, and it is not added to the PRF. 3360b57cec5SDimitry Andric if (WS.isEliminated()) 3370b57cec5SDimitry Andric return; 3380b57cec5SDimitry Andric 3398bcb0991SDimitry Andric MCPhysReg RegID = WS.getRegisterID(); 3400b57cec5SDimitry Andric 341fe6060f1SDimitry Andric // This allows InstrPostProcess to remove register Defs 342fe6060f1SDimitry Andric // by setting their RegisterID to 0. 343fe6060f1SDimitry Andric if (!RegID) 344fe6060f1SDimitry Andric return; 345fe6060f1SDimitry Andric 3460b57cec5SDimitry Andric assert(WS.getCyclesLeft() != UNKNOWN_CYCLES && 3470b57cec5SDimitry Andric "Invalidating a write of unknown cycles!"); 3480b57cec5SDimitry Andric assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!"); 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool ShouldFreePhysRegs = !WS.isWriteZero(); 3518bcb0991SDimitry Andric MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs; 3520b57cec5SDimitry Andric if (RenameAs && RenameAs != RegID) { 3530b57cec5SDimitry Andric RegID = RenameAs; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric if (!WS.clearsSuperRegisters()) { 3560b57cec5SDimitry Andric // Keep the definition of `RegID` together with register `RenameAs`. 3570b57cec5SDimitry Andric ShouldFreePhysRegs = false; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric if (ShouldFreePhysRegs) 3620b57cec5SDimitry Andric freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs); 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric WriteRef &WR = RegisterMappings[RegID].first; 3650b57cec5SDimitry Andric if (WR.getWriteState() == &WS) 366fe6060f1SDimitry Andric WR.commit(); 3670b57cec5SDimitry Andric 36806c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(RegID)) { 36906c3fb27SDimitry Andric WriteRef &OtherWR = RegisterMappings[I].first; 3700b57cec5SDimitry Andric if (OtherWR.getWriteState() == &WS) 371fe6060f1SDimitry Andric OtherWR.commit(); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric if (!WS.clearsSuperRegisters()) 3750b57cec5SDimitry Andric return; 3760b57cec5SDimitry Andric 37706c3fb27SDimitry Andric for (MCPhysReg I : MRI.superregs(RegID)) { 37806c3fb27SDimitry Andric WriteRef &OtherWR = RegisterMappings[I].first; 3790b57cec5SDimitry Andric if (OtherWR.getWriteState() == &WS) 380fe6060f1SDimitry Andric OtherWR.commit(); 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 384fe6060f1SDimitry Andric bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS, 385fe6060f1SDimitry Andric unsigned RegisterFileIndex) const { 3860b57cec5SDimitry Andric const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()]; 3870b57cec5SDimitry Andric const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()]; 388fe6060f1SDimitry Andric const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; 3890b57cec5SDimitry Andric 390fe6060f1SDimitry Andric // From and To must be owned by the PRF at index `RegisterFileIndex`. 3910b57cec5SDimitry Andric const RegisterRenamingInfo &RRIFrom = RMFrom.second; 392fe6060f1SDimitry Andric if (RRIFrom.IndexPlusCost.first != RegisterFileIndex) 393fe6060f1SDimitry Andric return false; 394fe6060f1SDimitry Andric 3950b57cec5SDimitry Andric const RegisterRenamingInfo &RRITo = RMTo.second; 396fe6060f1SDimitry Andric if (RRITo.IndexPlusCost.first != RegisterFileIndex) 397fe6060f1SDimitry Andric return false; 398fe6060f1SDimitry Andric 399fe6060f1SDimitry Andric // Early exit if the destination register is from a register class that 400fe6060f1SDimitry Andric // doesn't allow move elimination. 401fe6060f1SDimitry Andric if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination) 4020b57cec5SDimitry Andric return false; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric // We only allow move elimination for writes that update a full physical 4050b57cec5SDimitry Andric // register. On X86, move elimination is possible with 32-bit general purpose 4060b57cec5SDimitry Andric // registers because writes to those registers are not partial writes. If a 4070b57cec5SDimitry Andric // register move is a partial write, then we conservatively assume that move 4080b57cec5SDimitry Andric // elimination fails, since it would either trigger a partial update, or the 4090b57cec5SDimitry Andric // issue of a merge opcode. 4100b57cec5SDimitry Andric // 4110b57cec5SDimitry Andric // Note that this constraint may be lifted in future. For example, we could 4120b57cec5SDimitry Andric // make this model more flexible, and let users customize the set of registers 4130b57cec5SDimitry Andric // (i.e. register classes) that allow move elimination. 4140b57cec5SDimitry Andric // 4150b57cec5SDimitry Andric // For now, we assume that there is a strong correlation between registers 4160b57cec5SDimitry Andric // that allow move elimination, and how those same registers are renamed in 4170b57cec5SDimitry Andric // hardware. 418fe6060f1SDimitry Andric if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID()) 4190b57cec5SDimitry Andric if (!WS.clearsSuperRegisters()) 4200b57cec5SDimitry Andric return false; 4210b57cec5SDimitry Andric 4220b57cec5SDimitry Andric bool IsZeroMove = ZeroRegisters[RS.getRegisterID()]; 423fe6060f1SDimitry Andric return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove); 424fe6060f1SDimitry Andric } 425fe6060f1SDimitry Andric 426fe6060f1SDimitry Andric bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes, 427fe6060f1SDimitry Andric MutableArrayRef<ReadState> Reads) { 428fe6060f1SDimitry Andric if (Writes.size() != Reads.size()) 4290b57cec5SDimitry Andric return false; 4300b57cec5SDimitry Andric 431fe6060f1SDimitry Andric // This logic assumes that writes and reads are contributed by a register move 432fe6060f1SDimitry Andric // or a register swap operation. In particular, it assumes a simple register 433fe6060f1SDimitry Andric // move if there is only one write. It assumes a swap operation if there are 434fe6060f1SDimitry Andric // exactly two writes. 435fe6060f1SDimitry Andric if (Writes.empty() || Writes.size() > 2) 436fe6060f1SDimitry Andric return false; 437fe6060f1SDimitry Andric 438fe6060f1SDimitry Andric // All registers must be owned by the same PRF. 439fe6060f1SDimitry Andric const RegisterRenamingInfo &RRInfo = 440fe6060f1SDimitry Andric RegisterMappings[Writes[0].getRegisterID()].second; 441fe6060f1SDimitry Andric unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first; 442fe6060f1SDimitry Andric RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex]; 443fe6060f1SDimitry Andric 444fe6060f1SDimitry Andric // Early exit if the PRF cannot eliminate more moves/xchg in this cycle. 445fe6060f1SDimitry Andric if (RMT.MaxMoveEliminatedPerCycle && 446fe6060f1SDimitry Andric (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle) 447fe6060f1SDimitry Andric return false; 448fe6060f1SDimitry Andric 449fe6060f1SDimitry Andric for (size_t I = 0, E = Writes.size(); I < E; ++I) { 450fe6060f1SDimitry Andric const ReadState &RS = Reads[I]; 451fe6060f1SDimitry Andric const WriteState &WS = Writes[E - (I + 1)]; 452fe6060f1SDimitry Andric if (!canEliminateMove(WS, RS, RegisterFileIndex)) 453fe6060f1SDimitry Andric return false; 454fe6060f1SDimitry Andric } 455fe6060f1SDimitry Andric 456fe6060f1SDimitry Andric for (size_t I = 0, E = Writes.size(); I < E; ++I) { 457fe6060f1SDimitry Andric ReadState &RS = Reads[I]; 458fe6060f1SDimitry Andric WriteState &WS = Writes[E - (I + 1)]; 459fe6060f1SDimitry Andric 460fe6060f1SDimitry Andric const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()]; 461fe6060f1SDimitry Andric const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()]; 462fe6060f1SDimitry Andric const RegisterRenamingInfo &RRIFrom = RMFrom.second; 463fe6060f1SDimitry Andric const RegisterRenamingInfo &RRITo = RMTo.second; 464fe6060f1SDimitry Andric 4650b57cec5SDimitry Andric // Construct an alias. 4660b57cec5SDimitry Andric MCPhysReg AliasedReg = 4670b57cec5SDimitry Andric RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID(); 4680b57cec5SDimitry Andric MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID(); 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second; 4710b57cec5SDimitry Andric if (RMAlias.AliasRegID) 4720b57cec5SDimitry Andric AliasedReg = RMAlias.AliasRegID; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric RegisterMappings[AliasReg].second.AliasRegID = AliasedReg; 47506c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(AliasReg)) 47606c3fb27SDimitry Andric RegisterMappings[I].second.AliasRegID = AliasedReg; 4770b57cec5SDimitry Andric 478fe6060f1SDimitry Andric if (ZeroRegisters[RS.getRegisterID()]) { 4790b57cec5SDimitry Andric WS.setWriteZero(); 4800b57cec5SDimitry Andric RS.setReadZero(); 4810b57cec5SDimitry Andric } 482fe6060f1SDimitry Andric 4830b57cec5SDimitry Andric WS.setEliminated(); 4840b57cec5SDimitry Andric RMT.NumMoveEliminated++; 485fe6060f1SDimitry Andric } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric return true; 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 490fe6060f1SDimitry Andric unsigned WriteRef::getWriteBackCycle() const { 491fe6060f1SDimitry Andric assert(hasKnownWriteBackCycle() && "Instruction not executed!"); 492fe6060f1SDimitry Andric assert((!Write || Write->getCyclesLeft() <= 0) && 493fe6060f1SDimitry Andric "Inconsistent state found!"); 494fe6060f1SDimitry Andric return WriteBackCycle; 495fe6060f1SDimitry Andric } 496fe6060f1SDimitry Andric 497fe6060f1SDimitry Andric unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const { 498fe6060f1SDimitry Andric assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!"); 499fe6060f1SDimitry Andric return CurrentCycle - WR.getWriteBackCycle(); 500fe6060f1SDimitry Andric } 501fe6060f1SDimitry Andric 502fe6060f1SDimitry Andric void RegisterFile::collectWrites( 503fe6060f1SDimitry Andric const MCSubtargetInfo &STI, const ReadState &RS, 504fe6060f1SDimitry Andric SmallVectorImpl<WriteRef> &Writes, 505fe6060f1SDimitry Andric SmallVectorImpl<WriteRef> &CommittedWrites) const { 506fe6060f1SDimitry Andric const ReadDescriptor &RD = RS.getDescriptor(); 507fe6060f1SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 508fe6060f1SDimitry Andric const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID); 5098bcb0991SDimitry Andric MCPhysReg RegID = RS.getRegisterID(); 5100b57cec5SDimitry Andric assert(RegID && RegID < RegisterMappings.size()); 511fe6060f1SDimitry Andric LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register " 5120b57cec5SDimitry Andric << MRI.getName(RegID) << '\n'); 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric // Check if this is an alias. 5150b57cec5SDimitry Andric const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second; 5160b57cec5SDimitry Andric if (RRI.AliasRegID) 5170b57cec5SDimitry Andric RegID = RRI.AliasRegID; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric const WriteRef &WR = RegisterMappings[RegID].first; 520fe6060f1SDimitry Andric if (WR.getWriteState()) { 5210b57cec5SDimitry Andric Writes.push_back(WR); 522fe6060f1SDimitry Andric } else if (WR.hasKnownWriteBackCycle()) { 523fe6060f1SDimitry Andric unsigned WriteResID = WR.getWriteResourceID(); 524fe6060f1SDimitry Andric int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID); 525fe6060f1SDimitry Andric if (ReadAdvance < 0) { 526fe6060f1SDimitry Andric unsigned Elapsed = getElapsedCyclesFromWriteBack(WR); 527fe6060f1SDimitry Andric if (Elapsed < static_cast<unsigned>(-ReadAdvance)) 528fe6060f1SDimitry Andric CommittedWrites.push_back(WR); 529fe6060f1SDimitry Andric } 530fe6060f1SDimitry Andric } 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric // Handle potential partial register updates. 53306c3fb27SDimitry Andric for (MCPhysReg I : MRI.subregs(RegID)) { 53406c3fb27SDimitry Andric const WriteRef &WR = RegisterMappings[I].first; 535fe6060f1SDimitry Andric if (WR.getWriteState()) { 5360b57cec5SDimitry Andric Writes.push_back(WR); 537fe6060f1SDimitry Andric } else if (WR.hasKnownWriteBackCycle()) { 538fe6060f1SDimitry Andric unsigned WriteResID = WR.getWriteResourceID(); 539fe6060f1SDimitry Andric int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID); 540fe6060f1SDimitry Andric if (ReadAdvance < 0) { 541fe6060f1SDimitry Andric unsigned Elapsed = getElapsedCyclesFromWriteBack(WR); 542fe6060f1SDimitry Andric if (Elapsed < static_cast<unsigned>(-ReadAdvance)) 543fe6060f1SDimitry Andric CommittedWrites.push_back(WR); 544fe6060f1SDimitry Andric } 545fe6060f1SDimitry Andric } 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric // Remove duplicate entries and resize the input vector. 5490b57cec5SDimitry Andric if (Writes.size() > 1) { 5500b57cec5SDimitry Andric sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) { 5510b57cec5SDimitry Andric return Lhs.getWriteState() < Rhs.getWriteState(); 5520b57cec5SDimitry Andric }); 553*0fca6ea1SDimitry Andric auto It = llvm::unique(Writes); 5540b57cec5SDimitry Andric Writes.resize(std::distance(Writes.begin(), It)); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric LLVM_DEBUG({ 5580b57cec5SDimitry Andric for (const WriteRef &WR : Writes) { 5590b57cec5SDimitry Andric const WriteState &WS = *WR.getWriteState(); 5600b57cec5SDimitry Andric dbgs() << "[PRF] Found a dependent use of Register " 5610b57cec5SDimitry Andric << MRI.getName(WS.getRegisterID()) << " (defined by instruction #" 5620b57cec5SDimitry Andric << WR.getSourceIndex() << ")\n"; 5630b57cec5SDimitry Andric } 5640b57cec5SDimitry Andric }); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric 567fe6060f1SDimitry Andric RegisterFile::RAWHazard 568fe6060f1SDimitry Andric RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI, 569fe6060f1SDimitry Andric const ReadState &RS) const { 570fe6060f1SDimitry Andric RAWHazard Hazard; 571fe6060f1SDimitry Andric SmallVector<WriteRef, 4> Writes; 572fe6060f1SDimitry Andric SmallVector<WriteRef, 4> CommittedWrites; 573fe6060f1SDimitry Andric 574fe6060f1SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 575fe6060f1SDimitry Andric const ReadDescriptor &RD = RS.getDescriptor(); 576fe6060f1SDimitry Andric const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID); 577fe6060f1SDimitry Andric 578fe6060f1SDimitry Andric collectWrites(STI, RS, Writes, CommittedWrites); 579fe6060f1SDimitry Andric for (const WriteRef &WR : Writes) { 580fe6060f1SDimitry Andric const WriteState *WS = WR.getWriteState(); 581fe6060f1SDimitry Andric unsigned WriteResID = WS->getWriteResourceID(); 582fe6060f1SDimitry Andric int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID); 583fe6060f1SDimitry Andric 584fe6060f1SDimitry Andric if (WS->getCyclesLeft() == UNKNOWN_CYCLES) { 585fe6060f1SDimitry Andric if (Hazard.isValid()) 586fe6060f1SDimitry Andric continue; 587fe6060f1SDimitry Andric 588fe6060f1SDimitry Andric Hazard.RegisterID = WR.getRegisterID(); 589fe6060f1SDimitry Andric Hazard.CyclesLeft = UNKNOWN_CYCLES; 590fe6060f1SDimitry Andric continue; 591fe6060f1SDimitry Andric } 592fe6060f1SDimitry Andric 593fe6060f1SDimitry Andric int CyclesLeft = WS->getCyclesLeft() - ReadAdvance; 594fe6060f1SDimitry Andric if (CyclesLeft > 0) { 595fe6060f1SDimitry Andric if (Hazard.CyclesLeft < CyclesLeft) { 596fe6060f1SDimitry Andric Hazard.RegisterID = WR.getRegisterID(); 597fe6060f1SDimitry Andric Hazard.CyclesLeft = CyclesLeft; 598fe6060f1SDimitry Andric } 599fe6060f1SDimitry Andric } 600fe6060f1SDimitry Andric } 601fe6060f1SDimitry Andric Writes.clear(); 602fe6060f1SDimitry Andric 603fe6060f1SDimitry Andric for (const WriteRef &WR : CommittedWrites) { 604fe6060f1SDimitry Andric unsigned WriteResID = WR.getWriteResourceID(); 605fe6060f1SDimitry Andric int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID); 606fe6060f1SDimitry Andric int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR)); 607fe6060f1SDimitry Andric int CyclesLeft = NegReadAdvance - Elapsed; 608fe6060f1SDimitry Andric assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!"); 609fe6060f1SDimitry Andric if (Hazard.CyclesLeft < CyclesLeft) { 610fe6060f1SDimitry Andric Hazard.RegisterID = WR.getRegisterID(); 611fe6060f1SDimitry Andric Hazard.CyclesLeft = CyclesLeft; 612fe6060f1SDimitry Andric } 613fe6060f1SDimitry Andric } 614fe6060f1SDimitry Andric 615fe6060f1SDimitry Andric return Hazard; 616fe6060f1SDimitry Andric } 617fe6060f1SDimitry Andric 6180b57cec5SDimitry Andric void RegisterFile::addRegisterRead(ReadState &RS, 6190b57cec5SDimitry Andric const MCSubtargetInfo &STI) const { 6208bcb0991SDimitry Andric MCPhysReg RegID = RS.getRegisterID(); 6210b57cec5SDimitry Andric const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second; 6220b57cec5SDimitry Andric RS.setPRF(RRI.IndexPlusCost.first); 6230b57cec5SDimitry Andric if (RS.isIndependentFromDef()) 6240b57cec5SDimitry Andric return; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric if (ZeroRegisters[RS.getRegisterID()]) 6270b57cec5SDimitry Andric RS.setReadZero(); 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric SmallVector<WriteRef, 4> DependentWrites; 630fe6060f1SDimitry Andric SmallVector<WriteRef, 4> CompletedWrites; 631fe6060f1SDimitry Andric collectWrites(STI, RS, DependentWrites, CompletedWrites); 632fe6060f1SDimitry Andric RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size()); 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric // We know that this read depends on all the writes in DependentWrites. 6350b57cec5SDimitry Andric // For each write, check if we have ReadAdvance information, and use it 636fe6060f1SDimitry Andric // to figure out in how many cycles this read will be available. 6370b57cec5SDimitry Andric const ReadDescriptor &RD = RS.getDescriptor(); 6380b57cec5SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 6390b57cec5SDimitry Andric const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID); 6400b57cec5SDimitry Andric for (WriteRef &WR : DependentWrites) { 641fe6060f1SDimitry Andric unsigned WriteResID = WR.getWriteResourceID(); 6420b57cec5SDimitry Andric WriteState &WS = *WR.getWriteState(); 6430b57cec5SDimitry Andric int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID); 6440b57cec5SDimitry Andric WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance); 6450b57cec5SDimitry Andric } 646fe6060f1SDimitry Andric 647fe6060f1SDimitry Andric for (WriteRef &WR : CompletedWrites) { 648fe6060f1SDimitry Andric unsigned WriteResID = WR.getWriteResourceID(); 649fe6060f1SDimitry Andric assert(WR.hasKnownWriteBackCycle() && "Invalid write!"); 650fe6060f1SDimitry Andric assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0); 651fe6060f1SDimitry Andric unsigned ReadAdvance = static_cast<unsigned>( 652fe6060f1SDimitry Andric -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID)); 653fe6060f1SDimitry Andric unsigned Elapsed = getElapsedCyclesFromWriteBack(WR); 654fe6060f1SDimitry Andric assert(Elapsed < ReadAdvance && "Should not have been added to the set!"); 655fe6060f1SDimitry Andric RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(), 656fe6060f1SDimitry Andric ReadAdvance - Elapsed); 657fe6060f1SDimitry Andric } 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6608bcb0991SDimitry Andric unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const { 6610b57cec5SDimitry Andric SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles()); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric // Find how many new mappings must be created for each register file. 6648bcb0991SDimitry Andric for (const MCPhysReg RegID : Regs) { 6650b57cec5SDimitry Andric const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second; 6660b57cec5SDimitry Andric const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost; 6670b57cec5SDimitry Andric if (Entry.first) 6680b57cec5SDimitry Andric NumPhysRegs[Entry.first] += Entry.second; 6690b57cec5SDimitry Andric NumPhysRegs[0] += Entry.second; 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric unsigned Response = 0; 6730b57cec5SDimitry Andric for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) { 6740b57cec5SDimitry Andric unsigned NumRegs = NumPhysRegs[I]; 6750b57cec5SDimitry Andric if (!NumRegs) 6760b57cec5SDimitry Andric continue; 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric const RegisterMappingTracker &RMT = RegisterFiles[I]; 6790b57cec5SDimitry Andric if (!RMT.NumPhysRegs) { 6800b57cec5SDimitry Andric // The register file has an unbounded number of microarchitectural 6810b57cec5SDimitry Andric // registers. 6820b57cec5SDimitry Andric continue; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric if (RMT.NumPhysRegs < NumRegs) { 6860b57cec5SDimitry Andric // The current register file is too small. This may occur if the number of 6870b57cec5SDimitry Andric // microarchitectural registers in register file #0 was changed by the 6880b57cec5SDimitry Andric // users via flag -reg-file-size. Alternatively, the scheduling model 6890b57cec5SDimitry Andric // specified a too small number of registers for this register file. 690fe6060f1SDimitry Andric LLVM_DEBUG( 691fe6060f1SDimitry Andric dbgs() << "[PRF] Not enough registers in the register file.\n"); 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // FIXME: Normalize the instruction register count to match the 6940b57cec5SDimitry Andric // NumPhysRegs value. This is a highly unusual case, and is not expected 6950b57cec5SDimitry Andric // to occur. This normalization is hiding an inconsistency in either the 6960b57cec5SDimitry Andric // scheduling model or in the value that the user might have specified 6970b57cec5SDimitry Andric // for NumPhysRegs. 6980b57cec5SDimitry Andric NumRegs = RMT.NumPhysRegs; 6990b57cec5SDimitry Andric } 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs)) 7020b57cec5SDimitry Andric Response |= (1U << I); 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric return Response; 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric #ifndef NDEBUG 709fe6060f1SDimitry Andric void WriteRef::dump() const { 710fe6060f1SDimitry Andric dbgs() << "IID=" << getSourceIndex() << ' '; 711fe6060f1SDimitry Andric if (isValid()) 712fe6060f1SDimitry Andric getWriteState()->dump(); 713fe6060f1SDimitry Andric else 714fe6060f1SDimitry Andric dbgs() << "(null)"; 715fe6060f1SDimitry Andric } 716fe6060f1SDimitry Andric 7170b57cec5SDimitry Andric void RegisterFile::dump() const { 7180b57cec5SDimitry Andric for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) { 7190b57cec5SDimitry Andric const RegisterMapping &RM = RegisterMappings[I]; 7200b57cec5SDimitry Andric const RegisterRenamingInfo &RRI = RM.second; 7210b57cec5SDimitry Andric if (ZeroRegisters[I]) { 7220b57cec5SDimitry Andric dbgs() << MRI.getName(I) << ", " << I 7230b57cec5SDimitry Andric << ", PRF=" << RRI.IndexPlusCost.first 7240b57cec5SDimitry Andric << ", Cost=" << RRI.IndexPlusCost.second 7250b57cec5SDimitry Andric << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I] 7260b57cec5SDimitry Andric << ","; 7270b57cec5SDimitry Andric RM.first.dump(); 7280b57cec5SDimitry Andric dbgs() << '\n'; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) { 7330b57cec5SDimitry Andric dbgs() << "Register File #" << I; 7340b57cec5SDimitry Andric const RegisterMappingTracker &RMT = RegisterFiles[I]; 7350b57cec5SDimitry Andric dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs 7360b57cec5SDimitry Andric << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n'; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric #endif 7400b57cec5SDimitry Andric 7410b57cec5SDimitry Andric } // namespace mca 7420b57cec5SDimitry Andric } // namespace llvm 743