mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-23 12:40:38 +00:00
9262f00f1a
The previously used "names" are rather descriptions (they use multiple words and contain spaces), use short programming language identifier like strings for the "names" which should be used when exporting to machine parseable formats. Also removed a unused TimerGroup from Hexxagon. Differential Revision: https://reviews.llvm.org/D25583 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287369 91177308-0d34-0410-b5e6-96231b3b80d8
165 lines
6.0 KiB
C++
165 lines
6.0 KiB
C++
//===-- RegAllocBase.cpp - Register Allocator Base Class ------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the RegAllocBase class which provides common functionality
|
|
// for LiveIntervalUnion-based register allocators.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "RegAllocBase.h"
|
|
#include "Spiller.h"
|
|
#include "llvm/ADT/Statistic.h"
|
|
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
|
|
#include "llvm/CodeGen/LiveRangeEdit.h"
|
|
#include "llvm/CodeGen/LiveRegMatrix.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/CodeGen/VirtRegMap.h"
|
|
#include "llvm/Target/TargetRegisterInfo.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "regalloc"
|
|
|
|
STATISTIC(NumNewQueued , "Number of new live ranges queued");
|
|
|
|
// Temporary verification option until we can put verification inside
|
|
// MachineVerifier.
|
|
static cl::opt<bool, true>
|
|
VerifyRegAlloc("verify-regalloc", cl::location(RegAllocBase::VerifyEnabled),
|
|
cl::desc("Verify during register allocation"));
|
|
|
|
const char RegAllocBase::TimerGroupName[] = "regalloc";
|
|
const char RegAllocBase::TimerGroupDescription[] = "Register Allocation";
|
|
bool RegAllocBase::VerifyEnabled = false;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// RegAllocBase Implementation
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Pin the vtable to this file.
|
|
void RegAllocBase::anchor() {}
|
|
|
|
void RegAllocBase::init(VirtRegMap &vrm,
|
|
LiveIntervals &lis,
|
|
LiveRegMatrix &mat) {
|
|
TRI = &vrm.getTargetRegInfo();
|
|
MRI = &vrm.getRegInfo();
|
|
VRM = &vrm;
|
|
LIS = &lis;
|
|
Matrix = &mat;
|
|
MRI->freezeReservedRegs(vrm.getMachineFunction());
|
|
RegClassInfo.runOnMachineFunction(vrm.getMachineFunction());
|
|
}
|
|
|
|
// Visit all the live registers. If they are already assigned to a physical
|
|
// register, unify them with the corresponding LiveIntervalUnion, otherwise push
|
|
// them on the priority queue for later assignment.
|
|
void RegAllocBase::seedLiveRegs() {
|
|
NamedRegionTimer T("seed", "Seed Live Regs", TimerGroupName,
|
|
TimerGroupDescription, TimePassesIsEnabled);
|
|
for (unsigned i = 0, e = MRI->getNumVirtRegs(); i != e; ++i) {
|
|
unsigned Reg = TargetRegisterInfo::index2VirtReg(i);
|
|
if (MRI->reg_nodbg_empty(Reg))
|
|
continue;
|
|
enqueue(&LIS->getInterval(Reg));
|
|
}
|
|
}
|
|
|
|
// Top-level driver to manage the queue of unassigned VirtRegs and call the
|
|
// selectOrSplit implementation.
|
|
void RegAllocBase::allocatePhysRegs() {
|
|
seedLiveRegs();
|
|
|
|
// Continue assigning vregs one at a time to available physical registers.
|
|
while (LiveInterval *VirtReg = dequeue()) {
|
|
assert(!VRM->hasPhys(VirtReg->reg) && "Register already assigned");
|
|
|
|
// Unused registers can appear when the spiller coalesces snippets.
|
|
if (MRI->reg_nodbg_empty(VirtReg->reg)) {
|
|
DEBUG(dbgs() << "Dropping unused " << *VirtReg << '\n');
|
|
aboutToRemoveInterval(*VirtReg);
|
|
LIS->removeInterval(VirtReg->reg);
|
|
continue;
|
|
}
|
|
|
|
// Invalidate all interference queries, live ranges could have changed.
|
|
Matrix->invalidateVirtRegs();
|
|
|
|
// selectOrSplit requests the allocator to return an available physical
|
|
// register if possible and populate a list of new live intervals that
|
|
// result from splitting.
|
|
DEBUG(dbgs() << "\nselectOrSplit "
|
|
<< TRI->getRegClassName(MRI->getRegClass(VirtReg->reg))
|
|
<< ':' << *VirtReg << " w=" << VirtReg->weight << '\n');
|
|
typedef SmallVector<unsigned, 4> VirtRegVec;
|
|
VirtRegVec SplitVRegs;
|
|
unsigned AvailablePhysReg = selectOrSplit(*VirtReg, SplitVRegs);
|
|
|
|
if (AvailablePhysReg == ~0u) {
|
|
// selectOrSplit failed to find a register!
|
|
// Probably caused by an inline asm.
|
|
MachineInstr *MI = nullptr;
|
|
for (MachineRegisterInfo::reg_instr_iterator
|
|
I = MRI->reg_instr_begin(VirtReg->reg), E = MRI->reg_instr_end();
|
|
I != E; ) {
|
|
MachineInstr *TmpMI = &*(I++);
|
|
if (TmpMI->isInlineAsm()) {
|
|
MI = TmpMI;
|
|
break;
|
|
}
|
|
}
|
|
if (MI)
|
|
MI->emitError("inline assembly requires more registers than available");
|
|
else
|
|
report_fatal_error("ran out of registers during register allocation");
|
|
// Keep going after reporting the error.
|
|
VRM->assignVirt2Phys(VirtReg->reg,
|
|
RegClassInfo.getOrder(MRI->getRegClass(VirtReg->reg)).front());
|
|
continue;
|
|
}
|
|
|
|
if (AvailablePhysReg)
|
|
Matrix->assign(*VirtReg, AvailablePhysReg);
|
|
|
|
for (VirtRegVec::iterator I = SplitVRegs.begin(), E = SplitVRegs.end();
|
|
I != E; ++I) {
|
|
LiveInterval *SplitVirtReg = &LIS->getInterval(*I);
|
|
assert(!VRM->hasPhys(SplitVirtReg->reg) && "Register already assigned");
|
|
if (MRI->reg_nodbg_empty(SplitVirtReg->reg)) {
|
|
DEBUG(dbgs() << "not queueing unused " << *SplitVirtReg << '\n');
|
|
aboutToRemoveInterval(*SplitVirtReg);
|
|
LIS->removeInterval(SplitVirtReg->reg);
|
|
continue;
|
|
}
|
|
DEBUG(dbgs() << "queuing new interval: " << *SplitVirtReg << "\n");
|
|
assert(!SplitVirtReg->empty() && "expecting non-empty interval");
|
|
assert(TargetRegisterInfo::isVirtualRegister(SplitVirtReg->reg) &&
|
|
"expect split value in virtual register");
|
|
enqueue(SplitVirtReg);
|
|
++NumNewQueued;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RegAllocBase::postOptimization() {
|
|
spiller().postOptimization();
|
|
for (auto DeadInst : DeadRemats) {
|
|
LIS->RemoveMachineInstrFromMaps(*DeadInst);
|
|
DeadInst->eraseFromParent();
|
|
}
|
|
DeadRemats.clear();
|
|
}
|