109467b48Spatrick //===--------------------- RegisterFile.cpp ---------------------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick /// \file
909467b48Spatrick ///
1009467b48Spatrick /// This file defines a register mapping file class. This class is responsible
1109467b48Spatrick /// for managing hardware register files and the tracking of data dependencies
1209467b48Spatrick /// between registers.
1309467b48Spatrick ///
1409467b48Spatrick //===----------------------------------------------------------------------===//
1509467b48Spatrick
1609467b48Spatrick #include "llvm/MCA/HardwareUnits/RegisterFile.h"
1709467b48Spatrick #include "llvm/MCA/Instruction.h"
1809467b48Spatrick #include "llvm/Support/Debug.h"
1909467b48Spatrick
2009467b48Spatrick #define DEBUG_TYPE "llvm-mca"
2109467b48Spatrick
2209467b48Spatrick namespace llvm {
2309467b48Spatrick namespace mca {
2409467b48Spatrick
2573471bf0Spatrick const unsigned WriteRef::INVALID_IID = std::numeric_limits<unsigned>::max();
2673471bf0Spatrick
WriteRef(unsigned SourceIndex,WriteState * WS)2773471bf0Spatrick WriteRef::WriteRef(unsigned SourceIndex, WriteState *WS)
2873471bf0Spatrick : IID(SourceIndex), WriteBackCycle(), WriteResID(), RegisterID(),
2973471bf0Spatrick Write(WS) {}
3073471bf0Spatrick
commit()3173471bf0Spatrick void WriteRef::commit() {
3273471bf0Spatrick assert(Write && Write->isExecuted() && "Cannot commit before write back!");
3373471bf0Spatrick RegisterID = Write->getRegisterID();
3473471bf0Spatrick WriteResID = Write->getWriteResourceID();
3573471bf0Spatrick Write = nullptr;
3673471bf0Spatrick }
3773471bf0Spatrick
notifyExecuted(unsigned Cycle)3873471bf0Spatrick void WriteRef::notifyExecuted(unsigned Cycle) {
3973471bf0Spatrick assert(Write && Write->isExecuted() && "Not executed!");
4073471bf0Spatrick WriteBackCycle = Cycle;
4173471bf0Spatrick }
4273471bf0Spatrick
hasKnownWriteBackCycle() const4373471bf0Spatrick bool WriteRef::hasKnownWriteBackCycle() const {
4473471bf0Spatrick return isValid() && (!Write || Write->isExecuted());
4573471bf0Spatrick }
4673471bf0Spatrick
isWriteZero() const4773471bf0Spatrick bool WriteRef::isWriteZero() const {
4873471bf0Spatrick assert(isValid() && "Invalid null WriteState found!");
4973471bf0Spatrick return getWriteState()->isWriteZero();
5073471bf0Spatrick }
5173471bf0Spatrick
getWriteResourceID() const5273471bf0Spatrick unsigned WriteRef::getWriteResourceID() const {
5373471bf0Spatrick if (Write)
5473471bf0Spatrick return Write->getWriteResourceID();
5573471bf0Spatrick return WriteResID;
5673471bf0Spatrick }
5773471bf0Spatrick
getRegisterID() const5873471bf0Spatrick MCPhysReg WriteRef::getRegisterID() const {
5973471bf0Spatrick if (Write)
6073471bf0Spatrick return Write->getRegisterID();
6173471bf0Spatrick return RegisterID;
6273471bf0Spatrick }
6373471bf0Spatrick
RegisterFile(const MCSchedModel & SM,const MCRegisterInfo & mri,unsigned NumRegs)6409467b48Spatrick RegisterFile::RegisterFile(const MCSchedModel &SM, const MCRegisterInfo &mri,
6509467b48Spatrick unsigned NumRegs)
6609467b48Spatrick : MRI(mri),
6709467b48Spatrick RegisterMappings(mri.getNumRegs(), {WriteRef(), RegisterRenamingInfo()}),
6873471bf0Spatrick ZeroRegisters(mri.getNumRegs(), false), CurrentCycle() {
6909467b48Spatrick initialize(SM, NumRegs);
7009467b48Spatrick }
7109467b48Spatrick
initialize(const MCSchedModel & SM,unsigned NumRegs)7209467b48Spatrick void RegisterFile::initialize(const MCSchedModel &SM, unsigned NumRegs) {
7309467b48Spatrick // Create a default register file that "sees" all the machine registers
7409467b48Spatrick // declared by the target. The number of physical registers in the default
7509467b48Spatrick // register file is set equal to `NumRegs`. A value of zero for `NumRegs`
7609467b48Spatrick // means: this register file has an unbounded number of physical registers.
7709467b48Spatrick RegisterFiles.emplace_back(NumRegs);
7809467b48Spatrick if (!SM.hasExtraProcessorInfo())
7909467b48Spatrick return;
8009467b48Spatrick
8109467b48Spatrick // For each user defined register file, allocate a RegisterMappingTracker
8209467b48Spatrick // object. The size of every register file, as well as the mapping between
8309467b48Spatrick // register files and register classes is specified via tablegen.
8409467b48Spatrick const MCExtraProcessorInfo &Info = SM.getExtraProcessorInfo();
8509467b48Spatrick
8609467b48Spatrick // Skip invalid register file at index 0.
8709467b48Spatrick for (unsigned I = 1, E = Info.NumRegisterFiles; I < E; ++I) {
8809467b48Spatrick const MCRegisterFileDesc &RF = Info.RegisterFiles[I];
8909467b48Spatrick assert(RF.NumPhysRegs && "Invalid PRF with zero physical registers!");
9009467b48Spatrick
9109467b48Spatrick // The cost of a register definition is equivalent to the number of
9209467b48Spatrick // physical registers that are allocated at register renaming stage.
9309467b48Spatrick unsigned Length = RF.NumRegisterCostEntries;
9409467b48Spatrick const MCRegisterCostEntry *FirstElt =
9509467b48Spatrick &Info.RegisterCostTable[RF.RegisterCostEntryIdx];
9609467b48Spatrick addRegisterFile(RF, ArrayRef<MCRegisterCostEntry>(FirstElt, Length));
9709467b48Spatrick }
9809467b48Spatrick }
9909467b48Spatrick
cycleStart()10009467b48Spatrick void RegisterFile::cycleStart() {
10109467b48Spatrick for (RegisterMappingTracker &RMT : RegisterFiles)
10209467b48Spatrick RMT.NumMoveEliminated = 0;
10309467b48Spatrick }
10409467b48Spatrick
onInstructionExecuted(Instruction * IS)10573471bf0Spatrick void RegisterFile::onInstructionExecuted(Instruction *IS) {
10673471bf0Spatrick assert(IS && IS->isExecuted() && "Unexpected internal state found!");
10773471bf0Spatrick for (WriteState &WS : IS->getDefs()) {
10873471bf0Spatrick if (WS.isEliminated())
10973471bf0Spatrick return;
11073471bf0Spatrick
11173471bf0Spatrick MCPhysReg RegID = WS.getRegisterID();
11273471bf0Spatrick
11373471bf0Spatrick // This allows InstrPostProcess to remove register Defs
11473471bf0Spatrick // by setting their RegisterID to 0.
11573471bf0Spatrick if (!RegID)
11673471bf0Spatrick continue;
11773471bf0Spatrick
11873471bf0Spatrick assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
11973471bf0Spatrick "The number of cycles should be known at this point!");
12073471bf0Spatrick assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
12173471bf0Spatrick
12273471bf0Spatrick MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
12373471bf0Spatrick if (RenameAs && RenameAs != RegID)
12473471bf0Spatrick RegID = RenameAs;
12573471bf0Spatrick
12673471bf0Spatrick WriteRef &WR = RegisterMappings[RegID].first;
12773471bf0Spatrick if (WR.getWriteState() == &WS)
12873471bf0Spatrick WR.notifyExecuted(CurrentCycle);
12973471bf0Spatrick
13073471bf0Spatrick for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
13173471bf0Spatrick WriteRef &OtherWR = RegisterMappings[*I].first;
13273471bf0Spatrick if (OtherWR.getWriteState() == &WS)
13373471bf0Spatrick OtherWR.notifyExecuted(CurrentCycle);
13473471bf0Spatrick }
13573471bf0Spatrick
13673471bf0Spatrick if (!WS.clearsSuperRegisters())
13773471bf0Spatrick continue;
13873471bf0Spatrick
13973471bf0Spatrick for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
14073471bf0Spatrick WriteRef &OtherWR = RegisterMappings[*I].first;
14173471bf0Spatrick if (OtherWR.getWriteState() == &WS)
14273471bf0Spatrick OtherWR.notifyExecuted(CurrentCycle);
14373471bf0Spatrick }
14473471bf0Spatrick }
14573471bf0Spatrick }
14673471bf0Spatrick
addRegisterFile(const MCRegisterFileDesc & RF,ArrayRef<MCRegisterCostEntry> Entries)14709467b48Spatrick void RegisterFile::addRegisterFile(const MCRegisterFileDesc &RF,
14809467b48Spatrick ArrayRef<MCRegisterCostEntry> Entries) {
14909467b48Spatrick // A default register file is always allocated at index #0. That register file
15009467b48Spatrick // is mainly used to count the total number of mappings created by all
15109467b48Spatrick // register files at runtime. Users can limit the number of available physical
15209467b48Spatrick // registers in register file #0 through the command line flag
15309467b48Spatrick // `-register-file-size`.
15409467b48Spatrick unsigned RegisterFileIndex = RegisterFiles.size();
15509467b48Spatrick RegisterFiles.emplace_back(RF.NumPhysRegs, RF.MaxMovesEliminatedPerCycle,
15609467b48Spatrick RF.AllowZeroMoveEliminationOnly);
15709467b48Spatrick
15809467b48Spatrick // Special case where there is no register class identifier in the set.
15909467b48Spatrick // An empty set of register classes means: this register file contains all
16009467b48Spatrick // the physical registers specified by the target.
16109467b48Spatrick // We optimistically assume that a register can be renamed at the cost of a
16209467b48Spatrick // single physical register. The constructor of RegisterFile ensures that
16309467b48Spatrick // a RegisterMapping exists for each logical register defined by the Target.
16409467b48Spatrick if (Entries.empty())
16509467b48Spatrick return;
16609467b48Spatrick
16709467b48Spatrick // Now update the cost of individual registers.
16809467b48Spatrick for (const MCRegisterCostEntry &RCE : Entries) {
16909467b48Spatrick const MCRegisterClass &RC = MRI.getRegClass(RCE.RegisterClassID);
17009467b48Spatrick for (const MCPhysReg Reg : RC) {
17109467b48Spatrick RegisterRenamingInfo &Entry = RegisterMappings[Reg].second;
17209467b48Spatrick IndexPlusCostPairTy &IPC = Entry.IndexPlusCost;
17309467b48Spatrick if (IPC.first && IPC.first != RegisterFileIndex) {
17409467b48Spatrick // The only register file that is allowed to overlap is the default
17509467b48Spatrick // register file at index #0. The analysis is inaccurate if register
17609467b48Spatrick // files overlap.
17709467b48Spatrick errs() << "warning: register " << MRI.getName(Reg)
17809467b48Spatrick << " defined in multiple register files.";
17909467b48Spatrick }
18009467b48Spatrick IPC = std::make_pair(RegisterFileIndex, RCE.Cost);
18109467b48Spatrick Entry.RenameAs = Reg;
18209467b48Spatrick Entry.AllowMoveElimination = RCE.AllowMoveElimination;
18309467b48Spatrick
18409467b48Spatrick // Assume the same cost for each sub-register.
18509467b48Spatrick for (MCSubRegIterator I(Reg, &MRI); I.isValid(); ++I) {
18609467b48Spatrick RegisterRenamingInfo &OtherEntry = RegisterMappings[*I].second;
18709467b48Spatrick if (!OtherEntry.IndexPlusCost.first &&
18809467b48Spatrick (!OtherEntry.RenameAs ||
18909467b48Spatrick MRI.isSuperRegister(*I, OtherEntry.RenameAs))) {
19009467b48Spatrick OtherEntry.IndexPlusCost = IPC;
19109467b48Spatrick OtherEntry.RenameAs = Reg;
19209467b48Spatrick }
19309467b48Spatrick }
19409467b48Spatrick }
19509467b48Spatrick }
19609467b48Spatrick }
19709467b48Spatrick
allocatePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> UsedPhysRegs)19809467b48Spatrick void RegisterFile::allocatePhysRegs(const RegisterRenamingInfo &Entry,
19909467b48Spatrick MutableArrayRef<unsigned> UsedPhysRegs) {
20009467b48Spatrick unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
20109467b48Spatrick unsigned Cost = Entry.IndexPlusCost.second;
20209467b48Spatrick if (RegisterFileIndex) {
20309467b48Spatrick RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
20409467b48Spatrick RMT.NumUsedPhysRegs += Cost;
20509467b48Spatrick UsedPhysRegs[RegisterFileIndex] += Cost;
20609467b48Spatrick }
20709467b48Spatrick
20809467b48Spatrick // Now update the default register mapping tracker.
20909467b48Spatrick RegisterFiles[0].NumUsedPhysRegs += Cost;
21009467b48Spatrick UsedPhysRegs[0] += Cost;
21109467b48Spatrick }
21209467b48Spatrick
freePhysRegs(const RegisterRenamingInfo & Entry,MutableArrayRef<unsigned> FreedPhysRegs)21309467b48Spatrick void RegisterFile::freePhysRegs(const RegisterRenamingInfo &Entry,
21409467b48Spatrick MutableArrayRef<unsigned> FreedPhysRegs) {
21509467b48Spatrick unsigned RegisterFileIndex = Entry.IndexPlusCost.first;
21609467b48Spatrick unsigned Cost = Entry.IndexPlusCost.second;
21709467b48Spatrick if (RegisterFileIndex) {
21809467b48Spatrick RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
21909467b48Spatrick RMT.NumUsedPhysRegs -= Cost;
22009467b48Spatrick FreedPhysRegs[RegisterFileIndex] += Cost;
22109467b48Spatrick }
22209467b48Spatrick
22309467b48Spatrick // Now update the default register mapping tracker.
22409467b48Spatrick RegisterFiles[0].NumUsedPhysRegs -= Cost;
22509467b48Spatrick FreedPhysRegs[0] += Cost;
22609467b48Spatrick }
22709467b48Spatrick
addRegisterWrite(WriteRef Write,MutableArrayRef<unsigned> UsedPhysRegs)22809467b48Spatrick void RegisterFile::addRegisterWrite(WriteRef Write,
22909467b48Spatrick MutableArrayRef<unsigned> UsedPhysRegs) {
23009467b48Spatrick WriteState &WS = *Write.getWriteState();
23109467b48Spatrick MCPhysReg RegID = WS.getRegisterID();
23273471bf0Spatrick
23373471bf0Spatrick // This allows InstrPostProcess to remove register Defs
23473471bf0Spatrick // by setting their RegisterID to 0.
23573471bf0Spatrick if (!RegID)
23673471bf0Spatrick return;
23709467b48Spatrick
23809467b48Spatrick LLVM_DEBUG({
23973471bf0Spatrick dbgs() << "[PRF] addRegisterWrite [ " << Write.getSourceIndex() << ", "
24073471bf0Spatrick << MRI.getName(RegID) << "]\n";
24109467b48Spatrick });
24209467b48Spatrick
24309467b48Spatrick // If RenameAs is equal to RegID, then RegID is subject to register renaming
24409467b48Spatrick // and false dependencies on RegID are all eliminated.
24509467b48Spatrick
24609467b48Spatrick // If RenameAs references the invalid register, then we optimistically assume
24709467b48Spatrick // that it can be renamed. In the absence of tablegen descriptors for register
24809467b48Spatrick // files, RenameAs is always set to the invalid register ID. In all other
24909467b48Spatrick // cases, RenameAs must be either equal to RegID, or it must reference a
25009467b48Spatrick // super-register of RegID.
25109467b48Spatrick
25209467b48Spatrick // If RenameAs is a super-register of RegID, then a write to RegID has always
25309467b48Spatrick // a false dependency on RenameAs. The only exception is for when the write
25409467b48Spatrick // implicitly clears the upper portion of the underlying register.
25509467b48Spatrick // If a write clears its super-registers, then it is renamed as `RenameAs`.
25609467b48Spatrick bool IsWriteZero = WS.isWriteZero();
25709467b48Spatrick bool IsEliminated = WS.isEliminated();
25809467b48Spatrick bool ShouldAllocatePhysRegs = !IsWriteZero && !IsEliminated;
25909467b48Spatrick const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
26009467b48Spatrick WS.setPRF(RRI.IndexPlusCost.first);
26109467b48Spatrick
26209467b48Spatrick if (RRI.RenameAs && RRI.RenameAs != RegID) {
26309467b48Spatrick RegID = RRI.RenameAs;
26409467b48Spatrick WriteRef &OtherWrite = RegisterMappings[RegID].first;
26509467b48Spatrick
26609467b48Spatrick if (!WS.clearsSuperRegisters()) {
26709467b48Spatrick // The processor keeps the definition of `RegID` together with register
26809467b48Spatrick // `RenameAs`. Since this partial write is not renamed, no physical
26909467b48Spatrick // register is allocated.
27009467b48Spatrick ShouldAllocatePhysRegs = false;
27109467b48Spatrick
27209467b48Spatrick WriteState *OtherWS = OtherWrite.getWriteState();
27309467b48Spatrick if (OtherWS && (OtherWrite.getSourceIndex() != Write.getSourceIndex())) {
27409467b48Spatrick // This partial write has a false dependency on RenameAs.
27509467b48Spatrick assert(!IsEliminated && "Unexpected partial update!");
27609467b48Spatrick OtherWS->addUser(OtherWrite.getSourceIndex(), &WS);
27709467b48Spatrick }
27809467b48Spatrick }
27909467b48Spatrick }
28009467b48Spatrick
28109467b48Spatrick // Update zero registers.
28209467b48Spatrick MCPhysReg ZeroRegisterID =
28309467b48Spatrick WS.clearsSuperRegisters() ? RegID : WS.getRegisterID();
28473471bf0Spatrick ZeroRegisters.setBitVal(ZeroRegisterID, IsWriteZero);
28509467b48Spatrick for (MCSubRegIterator I(ZeroRegisterID, &MRI); I.isValid(); ++I)
28673471bf0Spatrick ZeroRegisters.setBitVal(*I, IsWriteZero);
28709467b48Spatrick
28873471bf0Spatrick // If this move has been eliminated, then method tryEliminateMoveOrSwap should
28973471bf0Spatrick // have already updated all the register mappings.
29009467b48Spatrick if (!IsEliminated) {
291*d415bd75Srobert // Check if this is one of multiple writes performed by this
292*d415bd75Srobert // instruction to register RegID.
293*d415bd75Srobert const WriteRef &OtherWrite = RegisterMappings[RegID].first;
294*d415bd75Srobert const WriteState *OtherWS = OtherWrite.getWriteState();
295*d415bd75Srobert if (OtherWS && OtherWrite.getSourceIndex() == Write.getSourceIndex()) {
296*d415bd75Srobert if (OtherWS->getLatency() > WS.getLatency()) {
297*d415bd75Srobert // Conservatively keep the slowest write on RegID.
298*d415bd75Srobert if (ShouldAllocatePhysRegs)
299*d415bd75Srobert allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
300*d415bd75Srobert return;
301*d415bd75Srobert }
302*d415bd75Srobert }
303*d415bd75Srobert
30409467b48Spatrick // Update the mapping for register RegID including its sub-registers.
30509467b48Spatrick RegisterMappings[RegID].first = Write;
30609467b48Spatrick RegisterMappings[RegID].second.AliasRegID = 0U;
30709467b48Spatrick for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
30809467b48Spatrick RegisterMappings[*I].first = Write;
30909467b48Spatrick RegisterMappings[*I].second.AliasRegID = 0U;
31009467b48Spatrick }
31109467b48Spatrick
31209467b48Spatrick // No physical registers are allocated for instructions that are optimized
31309467b48Spatrick // in hardware. For example, zero-latency data-dependency breaking
31409467b48Spatrick // instructions don't consume physical registers.
31509467b48Spatrick if (ShouldAllocatePhysRegs)
31609467b48Spatrick allocatePhysRegs(RegisterMappings[RegID].second, UsedPhysRegs);
31709467b48Spatrick }
31809467b48Spatrick
31909467b48Spatrick if (!WS.clearsSuperRegisters())
32009467b48Spatrick return;
32109467b48Spatrick
32209467b48Spatrick for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
32309467b48Spatrick if (!IsEliminated) {
32409467b48Spatrick RegisterMappings[*I].first = Write;
32509467b48Spatrick RegisterMappings[*I].second.AliasRegID = 0U;
32609467b48Spatrick }
32709467b48Spatrick
32873471bf0Spatrick ZeroRegisters.setBitVal(*I, IsWriteZero);
32909467b48Spatrick }
33009467b48Spatrick }
33109467b48Spatrick
removeRegisterWrite(const WriteState & WS,MutableArrayRef<unsigned> FreedPhysRegs)33209467b48Spatrick void RegisterFile::removeRegisterWrite(
33309467b48Spatrick const WriteState &WS, MutableArrayRef<unsigned> FreedPhysRegs) {
33409467b48Spatrick // Early exit if this write was eliminated. A write eliminated at register
33509467b48Spatrick // renaming stage generates an alias, and it is not added to the PRF.
33609467b48Spatrick if (WS.isEliminated())
33709467b48Spatrick return;
33809467b48Spatrick
33909467b48Spatrick MCPhysReg RegID = WS.getRegisterID();
34009467b48Spatrick
34173471bf0Spatrick // This allows InstrPostProcess to remove register Defs
34273471bf0Spatrick // by setting their RegisterID to 0.
34373471bf0Spatrick if (!RegID)
34473471bf0Spatrick return;
34573471bf0Spatrick
34609467b48Spatrick assert(WS.getCyclesLeft() != UNKNOWN_CYCLES &&
34709467b48Spatrick "Invalidating a write of unknown cycles!");
34809467b48Spatrick assert(WS.getCyclesLeft() <= 0 && "Invalid cycles left for this write!");
34909467b48Spatrick
35009467b48Spatrick bool ShouldFreePhysRegs = !WS.isWriteZero();
35109467b48Spatrick MCPhysReg RenameAs = RegisterMappings[RegID].second.RenameAs;
35209467b48Spatrick if (RenameAs && RenameAs != RegID) {
35309467b48Spatrick RegID = RenameAs;
35409467b48Spatrick
35509467b48Spatrick if (!WS.clearsSuperRegisters()) {
35609467b48Spatrick // Keep the definition of `RegID` together with register `RenameAs`.
35709467b48Spatrick ShouldFreePhysRegs = false;
35809467b48Spatrick }
35909467b48Spatrick }
36009467b48Spatrick
36109467b48Spatrick if (ShouldFreePhysRegs)
36209467b48Spatrick freePhysRegs(RegisterMappings[RegID].second, FreedPhysRegs);
36309467b48Spatrick
36409467b48Spatrick WriteRef &WR = RegisterMappings[RegID].first;
36509467b48Spatrick if (WR.getWriteState() == &WS)
36673471bf0Spatrick WR.commit();
36709467b48Spatrick
36809467b48Spatrick for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
36909467b48Spatrick WriteRef &OtherWR = RegisterMappings[*I].first;
37009467b48Spatrick if (OtherWR.getWriteState() == &WS)
37173471bf0Spatrick OtherWR.commit();
37209467b48Spatrick }
37309467b48Spatrick
37409467b48Spatrick if (!WS.clearsSuperRegisters())
37509467b48Spatrick return;
37609467b48Spatrick
37709467b48Spatrick for (MCSuperRegIterator I(RegID, &MRI); I.isValid(); ++I) {
37809467b48Spatrick WriteRef &OtherWR = RegisterMappings[*I].first;
37909467b48Spatrick if (OtherWR.getWriteState() == &WS)
38073471bf0Spatrick OtherWR.commit();
38109467b48Spatrick }
38209467b48Spatrick }
38309467b48Spatrick
canEliminateMove(const WriteState & WS,const ReadState & RS,unsigned RegisterFileIndex) const38473471bf0Spatrick bool RegisterFile::canEliminateMove(const WriteState &WS, const ReadState &RS,
38573471bf0Spatrick unsigned RegisterFileIndex) const {
38609467b48Spatrick const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
38709467b48Spatrick const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
38873471bf0Spatrick const RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
38909467b48Spatrick
39073471bf0Spatrick // From and To must be owned by the PRF at index `RegisterFileIndex`.
39109467b48Spatrick const RegisterRenamingInfo &RRIFrom = RMFrom.second;
39273471bf0Spatrick if (RRIFrom.IndexPlusCost.first != RegisterFileIndex)
39373471bf0Spatrick return false;
39473471bf0Spatrick
39509467b48Spatrick const RegisterRenamingInfo &RRITo = RMTo.second;
39673471bf0Spatrick if (RRITo.IndexPlusCost.first != RegisterFileIndex)
39773471bf0Spatrick return false;
39873471bf0Spatrick
39973471bf0Spatrick // Early exit if the destination register is from a register class that
40073471bf0Spatrick // doesn't allow move elimination.
40173471bf0Spatrick if (!RegisterMappings[RRITo.RenameAs].second.AllowMoveElimination)
40209467b48Spatrick return false;
40309467b48Spatrick
40409467b48Spatrick // We only allow move elimination for writes that update a full physical
40509467b48Spatrick // register. On X86, move elimination is possible with 32-bit general purpose
40609467b48Spatrick // registers because writes to those registers are not partial writes. If a
40709467b48Spatrick // register move is a partial write, then we conservatively assume that move
40809467b48Spatrick // elimination fails, since it would either trigger a partial update, or the
40909467b48Spatrick // issue of a merge opcode.
41009467b48Spatrick //
41109467b48Spatrick // Note that this constraint may be lifted in future. For example, we could
41209467b48Spatrick // make this model more flexible, and let users customize the set of registers
41309467b48Spatrick // (i.e. register classes) that allow move elimination.
41409467b48Spatrick //
41509467b48Spatrick // For now, we assume that there is a strong correlation between registers
41609467b48Spatrick // that allow move elimination, and how those same registers are renamed in
41709467b48Spatrick // hardware.
41873471bf0Spatrick if (RRITo.RenameAs && RRITo.RenameAs != WS.getRegisterID())
41909467b48Spatrick if (!WS.clearsSuperRegisters())
42009467b48Spatrick return false;
42109467b48Spatrick
42209467b48Spatrick bool IsZeroMove = ZeroRegisters[RS.getRegisterID()];
42373471bf0Spatrick return (!RMT.AllowZeroMoveEliminationOnly || IsZeroMove);
42473471bf0Spatrick }
42573471bf0Spatrick
tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,MutableArrayRef<ReadState> Reads)42673471bf0Spatrick bool RegisterFile::tryEliminateMoveOrSwap(MutableArrayRef<WriteState> Writes,
42773471bf0Spatrick MutableArrayRef<ReadState> Reads) {
42873471bf0Spatrick if (Writes.size() != Reads.size())
42909467b48Spatrick return false;
43009467b48Spatrick
43173471bf0Spatrick // This logic assumes that writes and reads are contributed by a register move
43273471bf0Spatrick // or a register swap operation. In particular, it assumes a simple register
43373471bf0Spatrick // move if there is only one write. It assumes a swap operation if there are
43473471bf0Spatrick // exactly two writes.
43573471bf0Spatrick if (Writes.empty() || Writes.size() > 2)
43673471bf0Spatrick return false;
43773471bf0Spatrick
43873471bf0Spatrick // All registers must be owned by the same PRF.
43973471bf0Spatrick const RegisterRenamingInfo &RRInfo =
44073471bf0Spatrick RegisterMappings[Writes[0].getRegisterID()].second;
44173471bf0Spatrick unsigned RegisterFileIndex = RRInfo.IndexPlusCost.first;
44273471bf0Spatrick RegisterMappingTracker &RMT = RegisterFiles[RegisterFileIndex];
44373471bf0Spatrick
44473471bf0Spatrick // Early exit if the PRF cannot eliminate more moves/xchg in this cycle.
44573471bf0Spatrick if (RMT.MaxMoveEliminatedPerCycle &&
44673471bf0Spatrick (RMT.NumMoveEliminated + Writes.size()) > RMT.MaxMoveEliminatedPerCycle)
44773471bf0Spatrick return false;
44873471bf0Spatrick
44973471bf0Spatrick for (size_t I = 0, E = Writes.size(); I < E; ++I) {
45073471bf0Spatrick const ReadState &RS = Reads[I];
45173471bf0Spatrick const WriteState &WS = Writes[E - (I + 1)];
45273471bf0Spatrick if (!canEliminateMove(WS, RS, RegisterFileIndex))
45373471bf0Spatrick return false;
45473471bf0Spatrick }
45573471bf0Spatrick
45673471bf0Spatrick for (size_t I = 0, E = Writes.size(); I < E; ++I) {
45773471bf0Spatrick ReadState &RS = Reads[I];
45873471bf0Spatrick WriteState &WS = Writes[E - (I + 1)];
45973471bf0Spatrick
46073471bf0Spatrick const RegisterMapping &RMFrom = RegisterMappings[RS.getRegisterID()];
46173471bf0Spatrick const RegisterMapping &RMTo = RegisterMappings[WS.getRegisterID()];
46273471bf0Spatrick const RegisterRenamingInfo &RRIFrom = RMFrom.second;
46373471bf0Spatrick const RegisterRenamingInfo &RRITo = RMTo.second;
46473471bf0Spatrick
46509467b48Spatrick // Construct an alias.
46609467b48Spatrick MCPhysReg AliasedReg =
46709467b48Spatrick RRIFrom.RenameAs ? RRIFrom.RenameAs : RS.getRegisterID();
46809467b48Spatrick MCPhysReg AliasReg = RRITo.RenameAs ? RRITo.RenameAs : WS.getRegisterID();
46909467b48Spatrick
47009467b48Spatrick const RegisterRenamingInfo &RMAlias = RegisterMappings[AliasedReg].second;
47109467b48Spatrick if (RMAlias.AliasRegID)
47209467b48Spatrick AliasedReg = RMAlias.AliasRegID;
47309467b48Spatrick
47409467b48Spatrick RegisterMappings[AliasReg].second.AliasRegID = AliasedReg;
47509467b48Spatrick for (MCSubRegIterator I(AliasReg, &MRI); I.isValid(); ++I)
47609467b48Spatrick RegisterMappings[*I].second.AliasRegID = AliasedReg;
47709467b48Spatrick
47873471bf0Spatrick if (ZeroRegisters[RS.getRegisterID()]) {
47909467b48Spatrick WS.setWriteZero();
48009467b48Spatrick RS.setReadZero();
48109467b48Spatrick }
48273471bf0Spatrick
48309467b48Spatrick WS.setEliminated();
48409467b48Spatrick RMT.NumMoveEliminated++;
48573471bf0Spatrick }
48609467b48Spatrick
48709467b48Spatrick return true;
48809467b48Spatrick }
48909467b48Spatrick
getWriteBackCycle() const49073471bf0Spatrick unsigned WriteRef::getWriteBackCycle() const {
49173471bf0Spatrick assert(hasKnownWriteBackCycle() && "Instruction not executed!");
49273471bf0Spatrick assert((!Write || Write->getCyclesLeft() <= 0) &&
49373471bf0Spatrick "Inconsistent state found!");
49473471bf0Spatrick return WriteBackCycle;
49573471bf0Spatrick }
49673471bf0Spatrick
getElapsedCyclesFromWriteBack(const WriteRef & WR) const49773471bf0Spatrick unsigned RegisterFile::getElapsedCyclesFromWriteBack(const WriteRef &WR) const {
49873471bf0Spatrick assert(WR.hasKnownWriteBackCycle() && "Write hasn't been committed yet!");
49973471bf0Spatrick return CurrentCycle - WR.getWriteBackCycle();
50073471bf0Spatrick }
50173471bf0Spatrick
collectWrites(const MCSubtargetInfo & STI,const ReadState & RS,SmallVectorImpl<WriteRef> & Writes,SmallVectorImpl<WriteRef> & CommittedWrites) const50273471bf0Spatrick void RegisterFile::collectWrites(
50373471bf0Spatrick const MCSubtargetInfo &STI, const ReadState &RS,
50473471bf0Spatrick SmallVectorImpl<WriteRef> &Writes,
50573471bf0Spatrick SmallVectorImpl<WriteRef> &CommittedWrites) const {
50673471bf0Spatrick const ReadDescriptor &RD = RS.getDescriptor();
50773471bf0Spatrick const MCSchedModel &SM = STI.getSchedModel();
50873471bf0Spatrick const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
50909467b48Spatrick MCPhysReg RegID = RS.getRegisterID();
51009467b48Spatrick assert(RegID && RegID < RegisterMappings.size());
51173471bf0Spatrick LLVM_DEBUG(dbgs() << "[PRF] collecting writes for register "
51209467b48Spatrick << MRI.getName(RegID) << '\n');
51309467b48Spatrick
51409467b48Spatrick // Check if this is an alias.
51509467b48Spatrick const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
51609467b48Spatrick if (RRI.AliasRegID)
51709467b48Spatrick RegID = RRI.AliasRegID;
51809467b48Spatrick
51909467b48Spatrick const WriteRef &WR = RegisterMappings[RegID].first;
52073471bf0Spatrick if (WR.getWriteState()) {
52109467b48Spatrick Writes.push_back(WR);
52273471bf0Spatrick } else if (WR.hasKnownWriteBackCycle()) {
52373471bf0Spatrick unsigned WriteResID = WR.getWriteResourceID();
52473471bf0Spatrick int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
52573471bf0Spatrick if (ReadAdvance < 0) {
52673471bf0Spatrick unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
52773471bf0Spatrick if (Elapsed < static_cast<unsigned>(-ReadAdvance))
52873471bf0Spatrick CommittedWrites.push_back(WR);
52973471bf0Spatrick }
53073471bf0Spatrick }
53109467b48Spatrick
53209467b48Spatrick // Handle potential partial register updates.
53309467b48Spatrick for (MCSubRegIterator I(RegID, &MRI); I.isValid(); ++I) {
53409467b48Spatrick const WriteRef &WR = RegisterMappings[*I].first;
53573471bf0Spatrick if (WR.getWriteState()) {
53609467b48Spatrick Writes.push_back(WR);
53773471bf0Spatrick } else if (WR.hasKnownWriteBackCycle()) {
53873471bf0Spatrick unsigned WriteResID = WR.getWriteResourceID();
53973471bf0Spatrick int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
54073471bf0Spatrick if (ReadAdvance < 0) {
54173471bf0Spatrick unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
54273471bf0Spatrick if (Elapsed < static_cast<unsigned>(-ReadAdvance))
54373471bf0Spatrick CommittedWrites.push_back(WR);
54473471bf0Spatrick }
54573471bf0Spatrick }
54609467b48Spatrick }
54709467b48Spatrick
54809467b48Spatrick // Remove duplicate entries and resize the input vector.
54909467b48Spatrick if (Writes.size() > 1) {
55009467b48Spatrick sort(Writes, [](const WriteRef &Lhs, const WriteRef &Rhs) {
55109467b48Spatrick return Lhs.getWriteState() < Rhs.getWriteState();
55209467b48Spatrick });
55309467b48Spatrick auto It = std::unique(Writes.begin(), Writes.end());
55409467b48Spatrick Writes.resize(std::distance(Writes.begin(), It));
55509467b48Spatrick }
55609467b48Spatrick
55709467b48Spatrick LLVM_DEBUG({
55809467b48Spatrick for (const WriteRef &WR : Writes) {
55909467b48Spatrick const WriteState &WS = *WR.getWriteState();
56009467b48Spatrick dbgs() << "[PRF] Found a dependent use of Register "
56109467b48Spatrick << MRI.getName(WS.getRegisterID()) << " (defined by instruction #"
56209467b48Spatrick << WR.getSourceIndex() << ")\n";
56309467b48Spatrick }
56409467b48Spatrick });
56509467b48Spatrick }
56609467b48Spatrick
56773471bf0Spatrick RegisterFile::RAWHazard
checkRAWHazards(const MCSubtargetInfo & STI,const ReadState & RS) const56873471bf0Spatrick RegisterFile::checkRAWHazards(const MCSubtargetInfo &STI,
56973471bf0Spatrick const ReadState &RS) const {
57073471bf0Spatrick RAWHazard Hazard;
57173471bf0Spatrick SmallVector<WriteRef, 4> Writes;
57273471bf0Spatrick SmallVector<WriteRef, 4> CommittedWrites;
57373471bf0Spatrick
57473471bf0Spatrick const MCSchedModel &SM = STI.getSchedModel();
57573471bf0Spatrick const ReadDescriptor &RD = RS.getDescriptor();
57673471bf0Spatrick const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
57773471bf0Spatrick
57873471bf0Spatrick collectWrites(STI, RS, Writes, CommittedWrites);
57973471bf0Spatrick for (const WriteRef &WR : Writes) {
58073471bf0Spatrick const WriteState *WS = WR.getWriteState();
58173471bf0Spatrick unsigned WriteResID = WS->getWriteResourceID();
58273471bf0Spatrick int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
58373471bf0Spatrick
58473471bf0Spatrick if (WS->getCyclesLeft() == UNKNOWN_CYCLES) {
58573471bf0Spatrick if (Hazard.isValid())
58673471bf0Spatrick continue;
58773471bf0Spatrick
58873471bf0Spatrick Hazard.RegisterID = WR.getRegisterID();
58973471bf0Spatrick Hazard.CyclesLeft = UNKNOWN_CYCLES;
59073471bf0Spatrick continue;
59173471bf0Spatrick }
59273471bf0Spatrick
59373471bf0Spatrick int CyclesLeft = WS->getCyclesLeft() - ReadAdvance;
59473471bf0Spatrick if (CyclesLeft > 0) {
59573471bf0Spatrick if (Hazard.CyclesLeft < CyclesLeft) {
59673471bf0Spatrick Hazard.RegisterID = WR.getRegisterID();
59773471bf0Spatrick Hazard.CyclesLeft = CyclesLeft;
59873471bf0Spatrick }
59973471bf0Spatrick }
60073471bf0Spatrick }
60173471bf0Spatrick Writes.clear();
60273471bf0Spatrick
60373471bf0Spatrick for (const WriteRef &WR : CommittedWrites) {
60473471bf0Spatrick unsigned WriteResID = WR.getWriteResourceID();
60573471bf0Spatrick int NegReadAdvance = -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
60673471bf0Spatrick int Elapsed = static_cast<int>(getElapsedCyclesFromWriteBack(WR));
60773471bf0Spatrick int CyclesLeft = NegReadAdvance - Elapsed;
60873471bf0Spatrick assert(CyclesLeft > 0 && "Write should not be in the CommottedWrites set!");
60973471bf0Spatrick if (Hazard.CyclesLeft < CyclesLeft) {
61073471bf0Spatrick Hazard.RegisterID = WR.getRegisterID();
61173471bf0Spatrick Hazard.CyclesLeft = CyclesLeft;
61273471bf0Spatrick }
61373471bf0Spatrick }
61473471bf0Spatrick
61573471bf0Spatrick return Hazard;
61673471bf0Spatrick }
61773471bf0Spatrick
addRegisterRead(ReadState & RS,const MCSubtargetInfo & STI) const61809467b48Spatrick void RegisterFile::addRegisterRead(ReadState &RS,
61909467b48Spatrick const MCSubtargetInfo &STI) const {
62009467b48Spatrick MCPhysReg RegID = RS.getRegisterID();
62109467b48Spatrick const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
62209467b48Spatrick RS.setPRF(RRI.IndexPlusCost.first);
62309467b48Spatrick if (RS.isIndependentFromDef())
62409467b48Spatrick return;
62509467b48Spatrick
62609467b48Spatrick if (ZeroRegisters[RS.getRegisterID()])
62709467b48Spatrick RS.setReadZero();
62809467b48Spatrick
62909467b48Spatrick SmallVector<WriteRef, 4> DependentWrites;
63073471bf0Spatrick SmallVector<WriteRef, 4> CompletedWrites;
63173471bf0Spatrick collectWrites(STI, RS, DependentWrites, CompletedWrites);
63273471bf0Spatrick RS.setDependentWrites(DependentWrites.size() + CompletedWrites.size());
63309467b48Spatrick
63409467b48Spatrick // We know that this read depends on all the writes in DependentWrites.
63509467b48Spatrick // For each write, check if we have ReadAdvance information, and use it
63673471bf0Spatrick // to figure out in how many cycles this read will be available.
63709467b48Spatrick const ReadDescriptor &RD = RS.getDescriptor();
63809467b48Spatrick const MCSchedModel &SM = STI.getSchedModel();
63909467b48Spatrick const MCSchedClassDesc *SC = SM.getSchedClassDesc(RD.SchedClassID);
64009467b48Spatrick for (WriteRef &WR : DependentWrites) {
64173471bf0Spatrick unsigned WriteResID = WR.getWriteResourceID();
64209467b48Spatrick WriteState &WS = *WR.getWriteState();
64309467b48Spatrick int ReadAdvance = STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID);
64409467b48Spatrick WS.addUser(WR.getSourceIndex(), &RS, ReadAdvance);
64509467b48Spatrick }
64673471bf0Spatrick
64773471bf0Spatrick for (WriteRef &WR : CompletedWrites) {
64873471bf0Spatrick unsigned WriteResID = WR.getWriteResourceID();
64973471bf0Spatrick assert(WR.hasKnownWriteBackCycle() && "Invalid write!");
65073471bf0Spatrick assert(STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID) < 0);
65173471bf0Spatrick unsigned ReadAdvance = static_cast<unsigned>(
65273471bf0Spatrick -STI.getReadAdvanceCycles(SC, RD.UseIndex, WriteResID));
65373471bf0Spatrick unsigned Elapsed = getElapsedCyclesFromWriteBack(WR);
65473471bf0Spatrick assert(Elapsed < ReadAdvance && "Should not have been added to the set!");
65573471bf0Spatrick RS.writeStartEvent(WR.getSourceIndex(), WR.getRegisterID(),
65673471bf0Spatrick ReadAdvance - Elapsed);
65773471bf0Spatrick }
65809467b48Spatrick }
65909467b48Spatrick
isAvailable(ArrayRef<MCPhysReg> Regs) const66009467b48Spatrick unsigned RegisterFile::isAvailable(ArrayRef<MCPhysReg> Regs) const {
66109467b48Spatrick SmallVector<unsigned, 4> NumPhysRegs(getNumRegisterFiles());
66209467b48Spatrick
66309467b48Spatrick // Find how many new mappings must be created for each register file.
66409467b48Spatrick for (const MCPhysReg RegID : Regs) {
66509467b48Spatrick const RegisterRenamingInfo &RRI = RegisterMappings[RegID].second;
66609467b48Spatrick const IndexPlusCostPairTy &Entry = RRI.IndexPlusCost;
66709467b48Spatrick if (Entry.first)
66809467b48Spatrick NumPhysRegs[Entry.first] += Entry.second;
66909467b48Spatrick NumPhysRegs[0] += Entry.second;
67009467b48Spatrick }
67109467b48Spatrick
67209467b48Spatrick unsigned Response = 0;
67309467b48Spatrick for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
67409467b48Spatrick unsigned NumRegs = NumPhysRegs[I];
67509467b48Spatrick if (!NumRegs)
67609467b48Spatrick continue;
67709467b48Spatrick
67809467b48Spatrick const RegisterMappingTracker &RMT = RegisterFiles[I];
67909467b48Spatrick if (!RMT.NumPhysRegs) {
68009467b48Spatrick // The register file has an unbounded number of microarchitectural
68109467b48Spatrick // registers.
68209467b48Spatrick continue;
68309467b48Spatrick }
68409467b48Spatrick
68509467b48Spatrick if (RMT.NumPhysRegs < NumRegs) {
68609467b48Spatrick // The current register file is too small. This may occur if the number of
68709467b48Spatrick // microarchitectural registers in register file #0 was changed by the
68809467b48Spatrick // users via flag -reg-file-size. Alternatively, the scheduling model
68909467b48Spatrick // specified a too small number of registers for this register file.
69073471bf0Spatrick LLVM_DEBUG(
69173471bf0Spatrick dbgs() << "[PRF] Not enough registers in the register file.\n");
69209467b48Spatrick
69309467b48Spatrick // FIXME: Normalize the instruction register count to match the
69409467b48Spatrick // NumPhysRegs value. This is a highly unusual case, and is not expected
69509467b48Spatrick // to occur. This normalization is hiding an inconsistency in either the
69609467b48Spatrick // scheduling model or in the value that the user might have specified
69709467b48Spatrick // for NumPhysRegs.
69809467b48Spatrick NumRegs = RMT.NumPhysRegs;
69909467b48Spatrick }
70009467b48Spatrick
70109467b48Spatrick if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
70209467b48Spatrick Response |= (1U << I);
70309467b48Spatrick }
70409467b48Spatrick
70509467b48Spatrick return Response;
70609467b48Spatrick }
70709467b48Spatrick
70809467b48Spatrick #ifndef NDEBUG
dump() const70973471bf0Spatrick void WriteRef::dump() const {
71073471bf0Spatrick dbgs() << "IID=" << getSourceIndex() << ' ';
71173471bf0Spatrick if (isValid())
71273471bf0Spatrick getWriteState()->dump();
71373471bf0Spatrick else
71473471bf0Spatrick dbgs() << "(null)";
71573471bf0Spatrick }
71673471bf0Spatrick
dump() const71709467b48Spatrick void RegisterFile::dump() const {
71809467b48Spatrick for (unsigned I = 0, E = MRI.getNumRegs(); I < E; ++I) {
71909467b48Spatrick const RegisterMapping &RM = RegisterMappings[I];
72009467b48Spatrick const RegisterRenamingInfo &RRI = RM.second;
72109467b48Spatrick if (ZeroRegisters[I]) {
72209467b48Spatrick dbgs() << MRI.getName(I) << ", " << I
72309467b48Spatrick << ", PRF=" << RRI.IndexPlusCost.first
72409467b48Spatrick << ", Cost=" << RRI.IndexPlusCost.second
72509467b48Spatrick << ", RenameAs=" << RRI.RenameAs << ", IsZero=" << ZeroRegisters[I]
72609467b48Spatrick << ",";
72709467b48Spatrick RM.first.dump();
72809467b48Spatrick dbgs() << '\n';
72909467b48Spatrick }
73009467b48Spatrick }
73109467b48Spatrick
73209467b48Spatrick for (unsigned I = 0, E = getNumRegisterFiles(); I < E; ++I) {
73309467b48Spatrick dbgs() << "Register File #" << I;
73409467b48Spatrick const RegisterMappingTracker &RMT = RegisterFiles[I];
73509467b48Spatrick dbgs() << "\n TotalMappings: " << RMT.NumPhysRegs
73609467b48Spatrick << "\n NumUsedMappings: " << RMT.NumUsedPhysRegs << '\n';
73709467b48Spatrick }
73809467b48Spatrick }
73909467b48Spatrick #endif
74009467b48Spatrick
74109467b48Spatrick } // namespace mca
74209467b48Spatrick } // namespace llvm
743