xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/MCA/HardwareUnits/RegisterFile.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg /// \file
97330f729Sjoerg ///
107330f729Sjoerg /// This file defines a register mapping file class.  This class is responsible
117330f729Sjoerg /// for managing hardware register files and the tracking of data dependencies
127330f729Sjoerg /// between registers.
137330f729Sjoerg ///
147330f729Sjoerg //===----------------------------------------------------------------------===//
157330f729Sjoerg 
167330f729Sjoerg #include "llvm/MCA/HardwareUnits/RegisterFile.h"
177330f729Sjoerg #include "llvm/MCA/Instruction.h"
187330f729Sjoerg #include "llvm/Support/Debug.h"
197330f729Sjoerg 
207330f729Sjoerg #define DEBUG_TYPE "llvm-mca"
217330f729Sjoerg 
227330f729Sjoerg namespace llvm {
237330f729Sjoerg namespace mca {
247330f729Sjoerg 
25*82d56013Sjoerg const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
26*82d56013Sjoerg 
WriteRef(unsigned SourceIndex,WriteState * WS)27*82d56013Sjoerg WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
28*82d56013Sjoerg     : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
29*82d56013Sjoerg       Write(WS) {}
30*82d56013Sjoerg 
commit()31*82d56013Sjoerg void WriteRef::commit() {
32*82d56013Sjoerg   assert(Write && Write->isExecuted() && "Cannot commit before write back!");
33*82d56013Sjoerg   Write = nullptr;
34*82d56013Sjoerg }
35*82d56013Sjoerg 
notifyExecuted(unsigned Cycle)36*82d56013Sjoerg void WriteRef::notifyExecuted(unsigned Cycle) {
37*82d56013Sjoerg   assert(Write && Write->isExecuted() && "Not executed!");
38*82d56013Sjoerg   WriteBackCycle = Cycle;
39*82d56013Sjoerg }
40*82d56013Sjoerg 
hasKnownWriteBackCycle() const41*82d56013Sjoerg bool WriteRef::hasKnownWriteBackCycle() const {
42*82d56013Sjoerg   return isValid() && (!Write || Write->isExecuted());
43*82d56013Sjoerg }
44*82d56013Sjoerg 
isWriteZero() const45*82d56013Sjoerg bool WriteRef::isWriteZero() const {
46*82d56013Sjoerg   assert(isValid() && "Invalid null WriteState found!");
47*82d56013Sjoerg   return getWriteState()->isWriteZero();
48*82d56013Sjoerg }
49*82d56013Sjoerg 
getWriteResourceID() const50*82d56013Sjoerg unsigned WriteRef::getWriteResourceID() const {
51*82d56013Sjoerg   if (Write)
52*82d56013Sjoerg     return Write->getWriteResourceID();
53*82d56013Sjoerg   return WriteResID;
54*82d56013Sjoerg }
55*82d56013Sjoerg 
getRegisterID() const56*82d56013Sjoerg MCPhysReg WriteRef::getRegisterID() const {
57*82d56013Sjoerg   if (Write)
58*82d56013Sjoerg     return Write->getRegisterID();
59*82d56013Sjoerg   return RegisterID;
60*82d56013Sjoerg }
61*82d56013Sjoerg 
RegisterFile(const MCSchedModel & SM,const MCRegisterInfo & mri,unsigned NumRegs)627330f729Sjoerg RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
637330f729Sjoerg                            unsigned NumRegs)
647330f729Sjoerg     : MRI(mri),
657330f729Sjoerg       RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
66*82d56013Sjoerg       ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
677330f729Sjoerg   initialize(SM, NumRegs);
687330f729Sjoerg }
697330f729Sjoerg 
initialize(const MCSchedModel & SM,unsigned NumRegs)707330f729Sjoerg void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
717330f729Sjoerg   // Create a default register file that "sees" all the machine registers
727330f729Sjoerg   // declared by the target. The number of physical registers in the default
737330f729Sjoerg   // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
747330f729Sjoerg   // means: this register file has an unbounded number of physical registers.
757330f729Sjoerg   RegisterFiles.emplace_back(NumRegs);
767330f729Sjoerg   if (!SM.hasExtraProcessorInfo())
777330f729Sjoerg     return;
787330f729Sjoerg 
797330f729Sjoerg   // For each user defined register file, allocate a RegisterMappingTracker
807330f729Sjoerg   // object. The size of every register file, as well as the mapping between
817330f729Sjoerg   // register files and register classes is specified via tablegen.
827330f729Sjoerg   const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
837330f729Sjoerg 
847330f729Sjoerg   // Skip invalid register file at index 0.
857330f729Sjoerg   for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
867330f729Sjoerg     const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
877330f729Sjoerg     assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
887330f729Sjoerg 
897330f729Sjoerg     // The cost of a register definition is equivalent to the number of
907330f729Sjoerg     // physical registers that are allocated at register renaming stage.
917330f729Sjoerg     unsigned Length = RF.NumRegisterCostEntries;
927330f729Sjoerg     const MCRegisterCostEntry *FirstElt =
937330f729Sjoerg         &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
947330f729Sjoerg     addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
957330f729Sjoerg   }
967330f729Sjoerg }
977330f729Sjoerg 
cycleStart()987330f729Sjoerg void RegisterFile::cycleStart() {
997330f729Sjoerg   for (RegisterMappingTracker &RMT : RegisterFiles)
1007330f729Sjoerg     RMT.NumMoveEliminated = 0;
1017330f729Sjoerg }
1027330f729Sjoerg 
onInstructionExecuted(Instruction * IS)103*82d56013Sjoerg void RegisterFile::onInstructionExecuted(Instruction *IS) {
104*82d56013Sjoerg   assert(IS && IS->isExecuted() && "Unexpected internal state found!");
105*82d56013Sjoerg   for (WriteState &WS : IS->getDefs()) {
106*82d56013Sjoerg     if (WS.isEliminated())
107*82d56013Sjoerg       return;
108*82d56013Sjoerg 
109*82d56013Sjoerg     MCPhysReg RegID = WS.getRegisterID();
110*82d56013Sjoerg     assert(RegID != 0 && "A write of an invalid register?");
111*82d56013Sjoerg     assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
112*82d56013Sjoerg            "The number of cycles should be known at this point!");
113*82d56013Sjoerg     assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
114*82d56013Sjoerg 
115*82d56013Sjoerg     MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
116*82d56013Sjoerg     if (RenameAs && RenameAs != RegID)
117*82d56013Sjoerg       RegID = RenameAs;
118*82d56013Sjoerg 
119*82d56013Sjoerg     WriteRef &WR = RegisterMappings[RegID].first;
120*82d56013Sjoerg     if (WR.getWriteState() == &WS)
121*82d56013Sjoerg       WR.notifyExecuted(CurrentCycle);
122*82d56013Sjoerg 
123*82d56013Sjoerg     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
124*82d56013Sjoerg       WriteRef &OtherWR = RegisterMappings[*I].first;
125*82d56013Sjoerg       if (OtherWR.getWriteState() == &WS)
126*82d56013Sjoerg         OtherWR.notifyExecuted(CurrentCycle);
127*82d56013Sjoerg     }
128*82d56013Sjoerg 
129*82d56013Sjoerg     if (!WS.clearsSuperRegisters())
130*82d56013Sjoerg       continue;
131*82d56013Sjoerg 
132*82d56013Sjoerg     for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
133*82d56013Sjoerg       WriteRef &OtherWR = RegisterMappings[*I].first;
134*82d56013Sjoerg       if (OtherWR.getWriteState() == &WS)
135*82d56013Sjoerg         OtherWR.notifyExecuted(CurrentCycle);
136*82d56013Sjoerg     }
137*82d56013Sjoerg   }
138*82d56013Sjoerg }
139*82d56013Sjoerg 
addRegisterFile(const MCRegisterFileDesc & RF,ArrayRef<MCRegisterCostEntry> Entries)1407330f729Sjoerg void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
1417330f729Sjoerg                                    ArrayRef<MCRegisterCostEntry> Entries) {
1427330f729Sjoerg   // A default register file is always allocated at index #0. That register file
1437330f729Sjoerg   // is mainly used to count the total number of mappings created by all
1447330f729Sjoerg   // register files at runtime. Users can limit the number of available physical
1457330f729Sjoerg   // registers in register file #0 through the command line flag
1467330f729Sjoerg   // `-register-file-size`.
1477330f729Sjoerg   unsigned RegisterFileIndex = RegisterFiles.size();
1487330f729Sjoerg   RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
1497330f729Sjoerg                              RF.AllowZeroMoveEliminationOnly);
1507330f729Sjoerg 
1517330f729Sjoerg   // Special case where there is no register class identifier in the set.
1527330f729Sjoerg   // An empty set of register classes means: this register file contains all
1537330f729Sjoerg   // the physical registers specified by the target.
1547330f729Sjoerg   // We optimistically assume that a register can be renamed at the cost of a
1557330f729Sjoerg   // single physical register. The constructor of RegisterFile ensures that
1567330f729Sjoerg   // a RegisterMapping exists for each logical register defined by the Target.
1577330f729Sjoerg   if (Entries.empty())
1587330f729Sjoerg     return;
1597330f729Sjoerg 
1607330f729Sjoerg   // Now update the cost of individual registers.
1617330f729Sjoerg   for (const MCRegisterCostEntry &RCE : Entries) {
1627330f729Sjoerg     const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
1637330f729Sjoerg     for (const MCPhysReg Reg : RC) {
1647330f729Sjoerg       RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
1657330f729Sjoerg       IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
1667330f729Sjoerg       if (IPC.first && IPC.first != RegisterFileIndex) {
1677330f729Sjoerg         // The only register file that is allowed to overlap is the default
1687330f729Sjoerg         // register file at index #0. The analysis is inaccurate if register
1697330f729Sjoerg         // files overlap.
1707330f729Sjoerg         errs() << "warning: register " << MRI.getName(Reg)
1717330f729Sjoerg                << " defined in multiple register files.";
1727330f729Sjoerg       }
1737330f729Sjoerg       IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
1747330f729Sjoerg       Entry.RenameAs = Reg;
1757330f729Sjoerg       Entry.AllowMoveElimination = RCE.AllowMoveElimination;
1767330f729Sjoerg 
1777330f729Sjoerg       // Assume the same cost for each sub-register.
1787330f729Sjoerg       for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
1797330f729Sjoerg         RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
1807330f729Sjoerg         if (!OtherEntry.IndexPlusCost.first &&
1817330f729Sjoerg             (!OtherEntry.RenameAs ||
1827330f729Sjoerg              MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
1837330f729Sjoerg           OtherEntry.IndexPlusCost = IPC;
1847330f729Sjoerg           OtherEntry.RenameAs = Reg;
1857330f729Sjoerg         }
1867330f729Sjoerg       }
1877330f729Sjoerg     }
1887330f729Sjoerg   }
1897330f729Sjoerg }
1907330f729Sjoerg 
allocatePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> UsedPhysRegs)1917330f729Sjoerg void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
1927330f729Sjoerg                                     MutableArrayRef<unsigned> UsedPhysRegs) {
1937330f729Sjoerg   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
1947330f729Sjoerg   unsigned Cost = Entry.IndexPlusCost.second;
1957330f729Sjoerg   if (RegisterFileIndex) {
1967330f729Sjoerg     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
1977330f729Sjoerg     RMT.NumUsedPhysRegs += Cost;
1987330f729Sjoerg     UsedPhysRegs[RegisterFileIndex] += Cost;
1997330f729Sjoerg   }
2007330f729Sjoerg 
2017330f729Sjoerg   // Now update the default register mapping tracker.
2027330f729Sjoerg   RegisterFiles[0].NumUsedPhysRegs += Cost;
2037330f729Sjoerg   UsedPhysRegs[0] += Cost;
2047330f729Sjoerg }
2057330f729Sjoerg 
freePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> FreedPhysRegs)2067330f729Sjoerg void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
2077330f729Sjoerg                                 MutableArrayRef<unsigned> FreedPhysRegs) {
2087330f729Sjoerg   unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
2097330f729Sjoerg   unsigned Cost = Entry.IndexPlusCost.second;
2107330f729Sjoerg   if (RegisterFileIndex) {
2117330f729Sjoerg     RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
2127330f729Sjoerg     RMT.NumUsedPhysRegs -= Cost;
2137330f729Sjoerg     FreedPhysRegs[RegisterFileIndex] += Cost;
2147330f729Sjoerg   }
2157330f729Sjoerg 
2167330f729Sjoerg   // Now update the default register mapping tracker.
2177330f729Sjoerg   RegisterFiles[0].NumUsedPhysRegs -= Cost;
2187330f729Sjoerg   FreedPhysRegs[0] += Cost;
2197330f729Sjoerg }
2207330f729Sjoerg 
addRegisterWrite(WriteRef Write,MutableArrayRef<unsigned> UsedPhysRegs)2217330f729Sjoerg void RegisterFile::addRegisterWrite(WriteRef Write,
2227330f729Sjoerg                                     MutableArrayRef<unsigned> UsedPhysRegs) {
2237330f729Sjoerg   WriteState &WS = *Write.getWriteState();
2247330f729Sjoerg   MCPhysReg RegID = WS.getRegisterID();
2257330f729Sjoerg   assert(RegID && "Adding an invalid register definition?");
2267330f729Sjoerg 
2277330f729Sjoerg   LLVM_DEBUG({
2287330f729Sjoerg     dbgs() << "RegisterFile: addRegisterWrite [ " << Write.getSourceIndex()
2297330f729Sjoerg            << ", " << MRI.getName(RegID) << "]\n";
2307330f729Sjoerg   });
2317330f729Sjoerg 
2327330f729Sjoerg   // If RenameAs is equal to RegID, then RegID is subject to register renaming
2337330f729Sjoerg   // and false dependencies on RegID are all eliminated.
2347330f729Sjoerg 
2357330f729Sjoerg   // If RenameAs references the invalid register, then we optimistically assume
2367330f729Sjoerg   // that it can be renamed. In the absence of tablegen descriptors for register
2377330f729Sjoerg   // files, RenameAs is always set to the invalid register ID.  In all other
2387330f729Sjoerg   // cases, RenameAs must be either equal to RegID, or it must reference a
2397330f729Sjoerg   // super-register of RegID.
2407330f729Sjoerg 
2417330f729Sjoerg   // If RenameAs is a super-register of RegID, then a write to RegID has always
2427330f729Sjoerg   // a false dependency on RenameAs. The only exception is for when the write
2437330f729Sjoerg   // implicitly clears the upper portion of the underlying register.
2447330f729Sjoerg   // If a write clears its super-registers, then it is renamed as `RenameAs`.
2457330f729Sjoerg   bool IsWriteZero = WS.isWriteZero();
2467330f729Sjoerg   bool IsEliminated = WS.isEliminated();
2477330f729Sjoerg   bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
2487330f729Sjoerg   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
2497330f729Sjoerg   WS.setPRF(RRI.IndexPlusCost.first);
2507330f729Sjoerg 
2517330f729Sjoerg   if (RRI.RenameAs && RRI.RenameAs != RegID) {
2527330f729Sjoerg     RegID = RRI.RenameAs;
2537330f729Sjoerg     WriteRef &OtherWrite = RegisterMappings[RegID].first;
2547330f729Sjoerg 
2557330f729Sjoerg     if (!WS.clearsSuperRegisters()) {
2567330f729Sjoerg       // The processor keeps the definition of `RegID` together with register
2577330f729Sjoerg       // `RenameAs`. Since this partial write is not renamed, no physical
2587330f729Sjoerg       // register is allocated.
2597330f729Sjoerg       ShouldAllocatePhysRegs = false;
2607330f729Sjoerg 
2617330f729Sjoerg       WriteState *OtherWS = OtherWrite.getWriteState();
2627330f729Sjoerg       if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
2637330f729Sjoerg         // This partial write has a false dependency on RenameAs.
2647330f729Sjoerg         assert(!IsEliminated && "Unexpected partial update!");
2657330f729Sjoerg         OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
2667330f729Sjoerg       }
2677330f729Sjoerg     }
2687330f729Sjoerg   }
2697330f729Sjoerg 
2707330f729Sjoerg   // Update zero registers.
2717330f729Sjoerg   MCPhysReg ZeroRegisterID =
2727330f729Sjoerg       WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
273*82d56013Sjoerg   ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
2747330f729Sjoerg   for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
275*82d56013Sjoerg     ZeroRegisters.setBitVal(*I, IsWriteZero);
2767330f729Sjoerg 
277*82d56013Sjoerg   // If this move has been eliminated, then method tryEliminateMoveOrSwap should
278*82d56013Sjoerg   // have already updated all the register mappings.
2797330f729Sjoerg   if (!IsEliminated) {
2807330f729Sjoerg     // Update the mapping for register RegID including its sub-registers.
2817330f729Sjoerg     RegisterMappings[RegID].first = Write;
2827330f729Sjoerg     RegisterMappings[RegID].second.AliasRegID = 0U;
2837330f729Sjoerg     for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
2847330f729Sjoerg       RegisterMappings[*I].first = Write;
2857330f729Sjoerg       RegisterMappings[*I].second.AliasRegID = 0U;
2867330f729Sjoerg     }
2877330f729Sjoerg 
2887330f729Sjoerg     // No physical registers are allocated for instructions that are optimized
2897330f729Sjoerg     // in hardware. For example, zero-latency data-dependency breaking
2907330f729Sjoerg     // instructions don't consume physical registers.
2917330f729Sjoerg     if (ShouldAllocatePhysRegs)
2927330f729Sjoerg       allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
2937330f729Sjoerg   }
2947330f729Sjoerg 
2957330f729Sjoerg   if (!WS.clearsSuperRegisters())
2967330f729Sjoerg     return;
2977330f729Sjoerg 
2987330f729Sjoerg   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
2997330f729Sjoerg     if (!IsEliminated) {
3007330f729Sjoerg       RegisterMappings[*I].first = Write;
3017330f729Sjoerg       RegisterMappings[*I].second.AliasRegID = 0U;
3027330f729Sjoerg     }
3037330f729Sjoerg 
304*82d56013Sjoerg     ZeroRegisters.setBitVal(*I, IsWriteZero);
3057330f729Sjoerg   }
3067330f729Sjoerg }
3077330f729Sjoerg 
removeRegisterWrite(const WriteState & WS,MutableArrayRef<unsigned> FreedPhysRegs)3087330f729Sjoerg void RegisterFile::removeRegisterWrite(
3097330f729Sjoerg     const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
3107330f729Sjoerg   // Early exit if this write was eliminated. A write eliminated at register
3117330f729Sjoerg   // renaming stage generates an alias, and it is not added to the PRF.
3127330f729Sjoerg   if (WS.isEliminated())
3137330f729Sjoerg     return;
3147330f729Sjoerg 
3157330f729Sjoerg   MCPhysReg RegID = WS.getRegisterID();
3167330f729Sjoerg 
3177330f729Sjoerg   assert(RegID != 0 && "Invalidating an already invalid register?");
3187330f729Sjoerg   assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
3197330f729Sjoerg          "Invalidating a write of unknown cycles!");
3207330f729Sjoerg   assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
3217330f729Sjoerg 
3227330f729Sjoerg   bool ShouldFreePhysRegs = !WS.isWriteZero();
3237330f729Sjoerg   MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
3247330f729Sjoerg   if (RenameAs && RenameAs != RegID) {
3257330f729Sjoerg     RegID = RenameAs;
3267330f729Sjoerg 
3277330f729Sjoerg     if (!WS.clearsSuperRegisters()) {
3287330f729Sjoerg       // Keep the definition of `RegID` together with register `RenameAs`.
3297330f729Sjoerg       ShouldFreePhysRegs = false;
3307330f729Sjoerg     }
3317330f729Sjoerg   }
3327330f729Sjoerg 
3337330f729Sjoerg   if (ShouldFreePhysRegs)
3347330f729Sjoerg     freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
3357330f729Sjoerg 
3367330f729Sjoerg   WriteRef &WR = RegisterMappings[RegID].first;
3377330f729Sjoerg   if (WR.getWriteState() == &WS)
338*82d56013Sjoerg     WR.commit();
3397330f729Sjoerg 
3407330f729Sjoerg   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
3417330f729Sjoerg     WriteRef &OtherWR = RegisterMappings[*I].first;
3427330f729Sjoerg     if (OtherWR.getWriteState() == &WS)
343*82d56013Sjoerg       OtherWR.commit();
3447330f729Sjoerg   }
3457330f729Sjoerg 
3467330f729Sjoerg   if (!WS.clearsSuperRegisters())
3477330f729Sjoerg     return;
3487330f729Sjoerg 
3497330f729Sjoerg   for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
3507330f729Sjoerg     WriteRef &OtherWR = RegisterMappings[*I].first;
3517330f729Sjoerg     if (OtherWR.getWriteState() == &WS)
352*82d56013Sjoerg       OtherWR.commit();
3537330f729Sjoerg   }
3547330f729Sjoerg }
3557330f729Sjoerg 
canEliminateMove(const WriteState & WS,const ReadState & RS,unsigned RegisterFileIndex) const356*82d56013Sjoerg bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
357*82d56013Sjoerg                                     unsigned RegisterFileIndex) const {
3587330f729Sjoerg   const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
3597330f729Sjoerg   const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
360*82d56013Sjoerg   const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
3617330f729Sjoerg 
362*82d56013Sjoerg   // From and To must be owned by the PRF at index `RegisterFileIndex`.
3637330f729Sjoerg   const RegisterRenamingInfo &RRIFrom = RMFrom.second;
364*82d56013Sjoerg   if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
365*82d56013Sjoerg     return false;
366*82d56013Sjoerg 
3677330f729Sjoerg   const RegisterRenamingInfo &RRITo = RMTo.second;
368*82d56013Sjoerg   if (RRITo.IndexPlusCost.first != RegisterFileIndex)
369*82d56013Sjoerg     return false;
370*82d56013Sjoerg 
371*82d56013Sjoerg   // Early exit if the destination register is from a register class that
372*82d56013Sjoerg   // doesn't allow move elimination.
373*82d56013Sjoerg   if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
3747330f729Sjoerg     return false;
3757330f729Sjoerg 
3767330f729Sjoerg   // We only allow move elimination for writes that update a full physical
3777330f729Sjoerg   // register. On X86, move elimination is possible with 32-bit general purpose
3787330f729Sjoerg   // registers because writes to those registers are not partial writes.  If a
3797330f729Sjoerg   // register move is a partial write, then we conservatively assume that move
3807330f729Sjoerg   // elimination fails, since it would either trigger a partial update, or the
3817330f729Sjoerg   // issue of a merge opcode.
3827330f729Sjoerg   //
3837330f729Sjoerg   // Note that this constraint may be lifted in future.  For example, we could
3847330f729Sjoerg   // make this model more flexible, and let users customize the set of registers
3857330f729Sjoerg   // (i.e. register classes) that allow move elimination.
3867330f729Sjoerg   //
3877330f729Sjoerg   // For now, we assume that there is a strong correlation between registers
3887330f729Sjoerg   // that allow move elimination, and how those same registers are renamed in
3897330f729Sjoerg   // hardware.
390*82d56013Sjoerg   if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
3917330f729Sjoerg     if (!WS.clearsSuperRegisters())
3927330f729Sjoerg       return false;
3937330f729Sjoerg 
3947330f729Sjoerg   bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
395*82d56013Sjoerg   return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
396*82d56013Sjoerg }
397*82d56013Sjoerg 
tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,MutableArrayRef<ReadState> Reads)398*82d56013Sjoerg bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
399*82d56013Sjoerg                                           MutableArrayRef<ReadState> Reads) {
400*82d56013Sjoerg   if (Writes.size() != Reads.size())
4017330f729Sjoerg     return false;
4027330f729Sjoerg 
403*82d56013Sjoerg   // This logic assumes that writes and reads are contributed by a register move
404*82d56013Sjoerg   // or a register swap operation. In particular, it assumes a simple register
405*82d56013Sjoerg   // move if there is only one write.  It assumes a swap operation if there are
406*82d56013Sjoerg   // exactly two writes.
407*82d56013Sjoerg   if (Writes.empty() || Writes.size() > 2)
408*82d56013Sjoerg     return false;
409*82d56013Sjoerg 
410*82d56013Sjoerg   // All registers must be owned by the same PRF.
411*82d56013Sjoerg   const RegisterRenamingInfo &RRInfo =
412*82d56013Sjoerg       RegisterMappings[Writes[0].getRegisterID()].second;
413*82d56013Sjoerg   unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
414*82d56013Sjoerg   RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
415*82d56013Sjoerg 
416*82d56013Sjoerg   // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
417*82d56013Sjoerg   if (RMT.MaxMoveEliminatedPerCycle &&
418*82d56013Sjoerg       (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
419*82d56013Sjoerg     return false;
420*82d56013Sjoerg 
421*82d56013Sjoerg   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
422*82d56013Sjoerg     const ReadState &RS = Reads[I];
423*82d56013Sjoerg     const WriteState &WS = Writes[E - (I + 1)];
424*82d56013Sjoerg     if (!canEliminateMove(WS, RS, RegisterFileIndex))
425*82d56013Sjoerg       return false;
426*82d56013Sjoerg   }
427*82d56013Sjoerg 
428*82d56013Sjoerg   for (size_t I = 0, E = Writes.size(); I < E; ++I) {
429*82d56013Sjoerg     ReadState &RS = Reads[I];
430*82d56013Sjoerg     WriteState &WS = Writes[E - (I + 1)];
431*82d56013Sjoerg 
432*82d56013Sjoerg     const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
433*82d56013Sjoerg     const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
434*82d56013Sjoerg     const RegisterRenamingInfo &RRIFrom = RMFrom.second;
435*82d56013Sjoerg     const RegisterRenamingInfo &RRITo = RMTo.second;
436*82d56013Sjoerg 
4377330f729Sjoerg     // Construct an alias.
4387330f729Sjoerg     MCPhysReg AliasedReg =
4397330f729Sjoerg         RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
4407330f729Sjoerg     MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
4417330f729Sjoerg 
4427330f729Sjoerg     const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
4437330f729Sjoerg     if (RMAlias.AliasRegID)
4447330f729Sjoerg       AliasedReg = RMAlias.AliasRegID;
4457330f729Sjoerg 
4467330f729Sjoerg     RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
4477330f729Sjoerg     for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
4487330f729Sjoerg       RegisterMappings[*I].second.AliasRegID = AliasedReg;
4497330f729Sjoerg 
450*82d56013Sjoerg     if (ZeroRegisters[RS.getRegisterID()]) {
4517330f729Sjoerg       WS.setWriteZero();
4527330f729Sjoerg       RS.setReadZero();
4537330f729Sjoerg     }
454*82d56013Sjoerg 
4557330f729Sjoerg     WS.setEliminated();
4567330f729Sjoerg     RMT.NumMoveEliminated++;
457*82d56013Sjoerg   }
4587330f729Sjoerg 
4597330f729Sjoerg   return true;
4607330f729Sjoerg }
4617330f729Sjoerg 
getWriteBackCycle() const462*82d56013Sjoerg unsigned WriteRef::getWriteBackCycle() const {
463*82d56013Sjoerg   assert(hasKnownWriteBackCycle() && "Instruction not executed!");
464*82d56013Sjoerg   assert((!Write || Write->getCyclesLeft() <= 0) &&
465*82d56013Sjoerg          "Inconsistent state found!");
466*82d56013Sjoerg   return WriteBackCycle;
467*82d56013Sjoerg }
468*82d56013Sjoerg 
getElapsedCyclesFromWriteBack(const WriteRef & WR) const469*82d56013Sjoerg unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
470*82d56013Sjoerg   assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
471*82d56013Sjoerg   return CurrentCycle - WR.getWriteBackCycle();
472*82d56013Sjoerg }
473*82d56013Sjoerg 
collectWrites(const MCSubtargetInfo & STI,const ReadState & RS,SmallVectorImpl<WriteRef> & Writes,SmallVectorImpl<WriteRef> & CommittedWrites) const474*82d56013Sjoerg void RegisterFile::collectWrites(
475*82d56013Sjoerg     const MCSubtargetInfo &STI, const ReadState &RS,
476*82d56013Sjoerg     SmallVectorImpl<WriteRef> &Writes,
477*82d56013Sjoerg     SmallVectorImpl<WriteRef> &CommittedWrites) const {
478*82d56013Sjoerg   const ReadDescriptor &RD = RS.getDescriptor();
479*82d56013Sjoerg   const MCSchedModel &SM = STI.getSchedModel();
480*82d56013Sjoerg   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
4817330f729Sjoerg   MCPhysReg RegID = RS.getRegisterID();
4827330f729Sjoerg   assert(RegID && RegID < RegisterMappings.size());
4837330f729Sjoerg   LLVM_DEBUG(dbgs() << "RegisterFile: collecting writes for register "
4847330f729Sjoerg                     << MRI.getName(RegID) << '\n');
4857330f729Sjoerg 
4867330f729Sjoerg   // Check if this is an alias.
4877330f729Sjoerg   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
4887330f729Sjoerg   if (RRI.AliasRegID)
4897330f729Sjoerg     RegID = RRI.AliasRegID;
4907330f729Sjoerg 
4917330f729Sjoerg   const WriteRef &WR = RegisterMappings[RegID].first;
492*82d56013Sjoerg   if (WR.getWriteState()) {
4937330f729Sjoerg     Writes.push_back(WR);
494*82d56013Sjoerg   } else if (WR.hasKnownWriteBackCycle()) {
495*82d56013Sjoerg     unsigned WriteResID = WR.getWriteResourceID();
496*82d56013Sjoerg     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
497*82d56013Sjoerg     if (ReadAdvance < 0) {
498*82d56013Sjoerg       unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
499*82d56013Sjoerg       if (Elapsed < static_cast<unsigned>(-ReadAdvance))
500*82d56013Sjoerg         CommittedWrites.push_back(WR);
501*82d56013Sjoerg     }
502*82d56013Sjoerg   }
5037330f729Sjoerg 
5047330f729Sjoerg   // Handle potential partial register updates.
5057330f729Sjoerg   for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
5067330f729Sjoerg     const WriteRef &WR = RegisterMappings[*I].first;
507*82d56013Sjoerg     if (WR.getWriteState()) {
5087330f729Sjoerg       Writes.push_back(WR);
509*82d56013Sjoerg     } else if (WR.hasKnownWriteBackCycle()) {
510*82d56013Sjoerg       unsigned WriteResID = WR.getWriteResourceID();
511*82d56013Sjoerg       int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
512*82d56013Sjoerg       if (ReadAdvance < 0) {
513*82d56013Sjoerg         unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
514*82d56013Sjoerg         if (Elapsed < static_cast<unsigned>(-ReadAdvance))
515*82d56013Sjoerg           CommittedWrites.push_back(WR);
516*82d56013Sjoerg       }
517*82d56013Sjoerg     }
5187330f729Sjoerg   }
5197330f729Sjoerg 
5207330f729Sjoerg   // Remove duplicate entries and resize the input vector.
5217330f729Sjoerg   if (Writes.size() > 1) {
5227330f729Sjoerg     sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
5237330f729Sjoerg       return Lhs.getWriteState() < Rhs.getWriteState();
5247330f729Sjoerg     });
5257330f729Sjoerg     auto It = std::unique(Writes.begin(), Writes.end());
5267330f729Sjoerg     Writes.resize(std::distance(Writes.begin(), It));
5277330f729Sjoerg   }
5287330f729Sjoerg 
5297330f729Sjoerg   LLVM_DEBUG({
5307330f729Sjoerg     for (const WriteRef &WR : Writes) {
5317330f729Sjoerg       const WriteState &WS = *WR.getWriteState();
5327330f729Sjoerg       dbgs() << "[PRF] Found a dependent use of Register "
5337330f729Sjoerg              << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
5347330f729Sjoerg              << WR.getSourceIndex() << ")\n";
5357330f729Sjoerg     }
5367330f729Sjoerg   });
5377330f729Sjoerg }
5387330f729Sjoerg 
addRegisterRead(ReadState & RS,const MCSubtargetInfo & STI) const5397330f729Sjoerg void RegisterFile::addRegisterRead(ReadState &RS,
5407330f729Sjoerg                                    const MCSubtargetInfo &STI) const {
5417330f729Sjoerg   MCPhysReg RegID = RS.getRegisterID();
5427330f729Sjoerg   const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
5437330f729Sjoerg   RS.setPRF(RRI.IndexPlusCost.first);
5447330f729Sjoerg   if (RS.isIndependentFromDef())
5457330f729Sjoerg     return;
5467330f729Sjoerg 
5477330f729Sjoerg   if (ZeroRegisters[RS.getRegisterID()])
5487330f729Sjoerg     RS.setReadZero();
5497330f729Sjoerg 
5507330f729Sjoerg   SmallVector<WriteRef, 4> DependentWrites;
551*82d56013Sjoerg   SmallVector<WriteRef, 4> CompletedWrites;
552*82d56013Sjoerg   collectWrites(STI, RS, DependentWrites, CompletedWrites);
553*82d56013Sjoerg   RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
5547330f729Sjoerg 
5557330f729Sjoerg   // We know that this read depends on all the writes in DependentWrites.
5567330f729Sjoerg   // For each write, check if we have ReadAdvance information, and use it
557*82d56013Sjoerg   // to figure out in how many cycles this read will be available.
5587330f729Sjoerg   const ReadDescriptor &RD = RS.getDescriptor();
5597330f729Sjoerg   const MCSchedModel &SM = STI.getSchedModel();
5607330f729Sjoerg   const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
5617330f729Sjoerg   for (WriteRef &WR : DependentWrites) {
562*82d56013Sjoerg     unsigned WriteResID = WR.getWriteResourceID();
5637330f729Sjoerg     WriteState &WS = *WR.getWriteState();
5647330f729Sjoerg     int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
5657330f729Sjoerg     WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
5667330f729Sjoerg   }
567*82d56013Sjoerg 
568*82d56013Sjoerg   for (WriteRef &WR : CompletedWrites) {
569*82d56013Sjoerg     unsigned WriteResID = WR.getWriteResourceID();
570*82d56013Sjoerg     assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
571*82d56013Sjoerg     assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
572*82d56013Sjoerg     unsigned ReadAdvance = static_cast<unsigned>(
573*82d56013Sjoerg         -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
574*82d56013Sjoerg     unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
575*82d56013Sjoerg     assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
576*82d56013Sjoerg     RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
577*82d56013Sjoerg                        ReadAdvance - Elapsed);
578*82d56013Sjoerg   }
5797330f729Sjoerg }
5807330f729Sjoerg 
isAvailable(ArrayRef<MCPhysReg> Regs) const5817330f729Sjoerg unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
5827330f729Sjoerg   SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
5837330f729Sjoerg 
5847330f729Sjoerg   // Find how many new mappings must be created for each register file.
5857330f729Sjoerg   for (const MCPhysReg RegID : Regs) {
5867330f729Sjoerg     const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
5877330f729Sjoerg     const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
5887330f729Sjoerg     if (Entry.first)
5897330f729Sjoerg       NumPhysRegs[Entry.first] += Entry.second;
5907330f729Sjoerg     NumPhysRegs[0] += Entry.second;
5917330f729Sjoerg   }
5927330f729Sjoerg 
5937330f729Sjoerg   unsigned Response = 0;
5947330f729Sjoerg   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
5957330f729Sjoerg     unsigned NumRegs = NumPhysRegs[I];
5967330f729Sjoerg     if (!NumRegs)
5977330f729Sjoerg       continue;
5987330f729Sjoerg 
5997330f729Sjoerg     const RegisterMappingTracker &RMT = RegisterFiles[I];
6007330f729Sjoerg     if (!RMT.NumPhysRegs) {
6017330f729Sjoerg       // The register file has an unbounded number of microarchitectural
6027330f729Sjoerg       // registers.
6037330f729Sjoerg       continue;
6047330f729Sjoerg     }
6057330f729Sjoerg 
6067330f729Sjoerg     if (RMT.NumPhysRegs < NumRegs) {
6077330f729Sjoerg       // The current register file is too small. This may occur if the number of
6087330f729Sjoerg       // microarchitectural registers in register file #0 was changed by the
6097330f729Sjoerg       // users via flag -reg-file-size. Alternatively, the scheduling model
6107330f729Sjoerg       // specified a too small number of registers for this register file.
6117330f729Sjoerg       LLVM_DEBUG(dbgs() << "Not enough registers in the register file.\n");
6127330f729Sjoerg 
6137330f729Sjoerg       // FIXME: Normalize the instruction register count to match the
6147330f729Sjoerg       // NumPhysRegs value.  This is a highly unusual case, and is not expected
6157330f729Sjoerg       // to occur.  This normalization is hiding an inconsistency in either the
6167330f729Sjoerg       // scheduling model or in the value that the user might have specified
6177330f729Sjoerg       // for NumPhysRegs.
6187330f729Sjoerg       NumRegs = RMT.NumPhysRegs;
6197330f729Sjoerg     }
6207330f729Sjoerg 
6217330f729Sjoerg     if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
6227330f729Sjoerg       Response |= (1U << I);
6237330f729Sjoerg   }
6247330f729Sjoerg 
6257330f729Sjoerg   return Response;
6267330f729Sjoerg }
6277330f729Sjoerg 
6287330f729Sjoerg #ifndef NDEBUG
dump() const629*82d56013Sjoerg void WriteRef::dump() const {
630*82d56013Sjoerg   dbgs() << "IID=" << getSourceIndex() << ' ';
631*82d56013Sjoerg   if (isValid())
632*82d56013Sjoerg     getWriteState()->dump();
633*82d56013Sjoerg   else
634*82d56013Sjoerg     dbgs() << "(null)";
635*82d56013Sjoerg }
636*82d56013Sjoerg 
dump() const6377330f729Sjoerg void RegisterFile::dump() const {
6387330f729Sjoerg   for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
6397330f729Sjoerg     const RegisterMapping &RM = RegisterMappings[I];
6407330f729Sjoerg     const RegisterRenamingInfo &RRI = RM.second;
6417330f729Sjoerg     if (ZeroRegisters[I]) {
6427330f729Sjoerg       dbgs() << MRI.getName(I) << ", " << I
6437330f729Sjoerg              << ", PRF=" << RRI.IndexPlusCost.first
6447330f729Sjoerg              << ", Cost=" << RRI.IndexPlusCost.second
6457330f729Sjoerg              << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
6467330f729Sjoerg              << ",";
6477330f729Sjoerg       RM.first.dump();
6487330f729Sjoerg       dbgs() << '\n';
6497330f729Sjoerg     }
6507330f729Sjoerg   }
6517330f729Sjoerg 
6527330f729Sjoerg   for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
6537330f729Sjoerg     dbgs() << "Register File #" << I;
6547330f729Sjoerg     const RegisterMappingTracker &RMT = RegisterFiles[I];
6557330f729Sjoerg     dbgs() << "\n  TotalMappings:        " << RMT.NumPhysRegs
6567330f729Sjoerg            << "\n  NumUsedMappings:      " << RMT.NumUsedPhysRegs << '\n';
6577330f729Sjoerg   }
6587330f729Sjoerg }
6597330f729Sjoerg #endif
6607330f729Sjoerg 
6617330f729Sjoerg } // namespace mca
6627330f729Sjoerg } // namespace llvm
663