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
WriteRef(unsigned SourceIndex,WriteState * WS)27fe6060f1SDimitry Andric WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
28fe6060f1SDimitry Andric : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
29fe6060f1SDimitry Andric Write(WS) {}
30fe6060f1SDimitry Andric
commit()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
notifyExecuted(unsigned Cycle)38fe6060f1SDimitry Andric void WriteRef::notifyExecuted(unsigned Cycle) {
39fe6060f1SDimitry Andric assert(Write && Write->isExecuted() && "Not executed!");
40fe6060f1SDimitry Andric WriteBackCycle = Cycle;
41fe6060f1SDimitry Andric }
42fe6060f1SDimitry Andric
hasKnownWriteBackCycle() const43fe6060f1SDimitry Andric bool WriteRef::hasKnownWriteBackCycle() const {
44fe6060f1SDimitry Andric return isValid() && (!Write || Write->isExecuted());
45fe6060f1SDimitry Andric }
46fe6060f1SDimitry Andric
isWriteZero() const47fe6060f1SDimitry Andric bool WriteRef::isWriteZero() const {
48fe6060f1SDimitry Andric assert(isValid() && "Invalid null WriteState found!");
49fe6060f1SDimitry Andric return getWriteState()->isWriteZero();
50fe6060f1SDimitry Andric }
51fe6060f1SDimitry Andric
getWriteResourceID() const52fe6060f1SDimitry Andric unsigned WriteRef::getWriteResourceID() const {
53fe6060f1SDimitry Andric if (Write)
54fe6060f1SDimitry Andric return Write->getWriteResourceID();
55fe6060f1SDimitry Andric return WriteResID;
56fe6060f1SDimitry Andric }
57fe6060f1SDimitry Andric
getRegisterID() const58fe6060f1SDimitry Andric MCPhysReg WriteRef::getRegisterID() const {
59fe6060f1SDimitry Andric if (Write)
60fe6060f1SDimitry Andric return Write->getRegisterID();
61fe6060f1SDimitry Andric return RegisterID;
62fe6060f1SDimitry Andric }
63fe6060f1SDimitry Andric
RegisterFile(const MCSchedModel & SM,const MCRegisterInfo & mri,unsigned NumRegs)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
initialize(const MCSchedModel & SM,unsigned NumRegs)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
cycleStart()1000b57cec5SDimitry Andric void RegisterFile::cycleStart() {
1010b57cec5SDimitry Andric for (RegisterMappingTracker &RMT : RegisterFiles)
1020b57cec5SDimitry Andric RMT.NumMoveEliminated = 0;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric
onInstructionExecuted(Instruction * IS)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
addRegisterFile(const MCRegisterFileDesc & RF,ArrayRef<MCRegisterCostEntry> Entries)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
allocatePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> UsedPhysRegs)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
freePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> FreedPhysRegs)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
addRegisterWrite(WriteRef Write,MutableArrayRef<unsigned> UsedPhysRegs)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
removeRegisterWrite(const WriteState & WS,MutableArrayRef<unsigned> FreedPhysRegs)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
canEliminateMove(const WriteState & WS,const ReadState & RS,unsigned RegisterFileIndex) const384fe6060f1SDimitry 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
tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,MutableArrayRef<ReadState> Reads)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
getWriteBackCycle() const490fe6060f1SDimitry 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
getElapsedCyclesFromWriteBack(const WriteRef & WR) const497fe6060f1SDimitry 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
collectWrites(const MCSubtargetInfo & STI,const ReadState & RS,SmallVectorImpl<WriteRef> & Writes,SmallVectorImpl<WriteRef> & CommittedWrites) const502fe6060f1SDimitry 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
checkRAWHazards(const MCSubtargetInfo & STI,const ReadState & RS) const568fe6060f1SDimitry 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
addRegisterRead(ReadState & RS,const MCSubtargetInfo & STI) const6180b57cec5SDimitry 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
isAvailable(ArrayRef<MCPhysReg> Regs) const6608bcb0991SDimitry 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
dump() const709fe6060f1SDimitry 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
dump() const7170b57cec5SDimitry 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