llvm-6502/lib/CodeGen/RegisterClassInfo.cpp
Jakob Stoklund Olesen 7c48913af6 Don't try to be clever, just preserve the target's allocation order.
The order of registers returned by getCalleeSavedRegs is used to lay out
the fixed stack slots for CSRs. Some targets like their CSRs used from
one end, and some targets want them used from the other end.

When computing an allocation order, simply preserve the relative
ordering of CSRs that the target specifies in its allocation order.
Reordering CSRs would break some targets, ARM in particular.

We still place volatiles before the CSRs, providing slightly better
results with different calling conventions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132680 91177308-0d34-0410-b5e6-96231b3b80d8
2011-06-06 16:36:30 +00:00

115 lines
3.7 KiB
C++

//===-- RegisterClassInfo.cpp - Dynamic Register Class Info ---------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the RegisterClassInfo class which provides dynamic
// information about target register classes. Callee saved and reserved
// registers depends on calling conventions and other dynamic information, so
// some things cannot be determined statically.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "regalloc"
#include "RegisterClassInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
RegisterClassInfo::RegisterClassInfo() : Tag(0), MF(0), TRI(0), CalleeSaved(0)
{}
void RegisterClassInfo::runOnMachineFunction(const MachineFunction &mf) {
bool Update = false;
MF = &mf;
// Allocate new array the first time we see a new target.
if (MF->getTarget().getRegisterInfo() != TRI) {
TRI = MF->getTarget().getRegisterInfo();
RegClass.reset(new RCInfo[TRI->getNumRegClasses()]);
Update = true;
}
// Does this MF have different CSRs?
const unsigned *CSR = TRI->getCalleeSavedRegs(MF);
if (Update || CSR != CalleeSaved) {
// Build a CSRNum map. Every CSR alias gets an entry pointing to the last
// overlapping CSR.
CSRNum.clear();
CSRNum.resize(TRI->getNumRegs(), 0);
for (unsigned N = 0; unsigned Reg = CSR[N]; ++N)
for (const unsigned *AS = TRI->getOverlaps(Reg);
unsigned Alias = *AS; ++AS)
CSRNum[Alias] = N + 1; // 0 means no CSR, 1 means CalleeSaved[0], ...
Update = true;
}
CalleeSaved = CSR;
// Different reserved registers?
BitVector RR = TRI->getReservedRegs(*MF);
if (RR != Reserved)
Update = true;
Reserved = RR;
// Invalidate cached information from previous function.
if (Update)
++Tag;
}
/// compute - Compute the preferred allocation order for RC with reserved
/// registers filtered out. Volatile registers come first followed by CSR
/// aliases ordered according to the CSR order specified by the target.
void RegisterClassInfo::compute(const TargetRegisterClass *RC) const {
RCInfo &RCI = RegClass[RC->getID()];
// Raw register count, including all reserved regs.
unsigned NumRegs = RC->getNumRegs();
if (!RCI.Order)
RCI.Order.reset(new unsigned[NumRegs]);
unsigned N = 0;
SmallVector<unsigned, 16> CSRAlias;
// FIXME: Once targets reserve registers instead of removing them from the
// allocation order, we can simply use begin/end here.
TargetRegisterClass::iterator AOB = RC->allocation_order_begin(*MF);
TargetRegisterClass::iterator AOE = RC->allocation_order_end(*MF);
for (TargetRegisterClass::iterator I = AOB; I != AOE; ++I) {
unsigned PhysReg = *I;
// Remove reserved registers from the allocation order.
if (Reserved.test(PhysReg))
continue;
if (CSRNum[PhysReg])
// PhysReg aliases a CSR, save it for later.
CSRAlias.push_back(PhysReg);
else
RCI.Order[N++] = PhysReg;
}
RCI.NumRegs = N + CSRAlias.size();
assert (RCI.NumRegs <= NumRegs && "Allocation order larger than regclass");
// CSR aliases go after the volatile registers, preserve the target's order.
std::copy(CSRAlias.begin(), CSRAlias.end(), &RCI.Order[N]);
DEBUG({
dbgs() << "AllocationOrder(" << RC->getName() << ") = [";
for (unsigned I = 0; I != N; ++I)
dbgs() << ' ' << PrintReg(RCI.Order[I], TRI);
dbgs() << " ]\n";
});
// RCI is now up-to-date.
RCI.Tag = Tag;
}