llvm-6502/lib/Target/Alpha/AlphaRegisterInfo.cpp
Jim Grosbach b58f498f75 Add register-reuse to frame-index register scavenging. When a target uses
a virtual register to eliminate a frame index, it can return that register
and the constant stored there to PEI to track. When scavenging to allocate
for those registers, PEI then tracks the last-used register and value, and
if it is still available and matches the value for the next index, reuses
the existing value rather and removes the re-materialization instructions.
Fancier tracking and adjustment of scavenger allocations to keep more
values live for longer is possible, but not yet implemented and would likely
be better done via a different, less special-purpose, approach to the
problem.

eliminateFrameIndex() is modified so the target implementations can return
the registers they wish to be tracked for reuse.

ARM Thumb1 implements and utilizes the new mechanism. All other targets are
simply modified to adjust for the changed eliminateFrameIndex() prototype.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@83467 91177308-0d34-0410-b5e6-96231b3b80d8
2009-10-07 17:12:56 +00:00

343 lines
11 KiB
C++

//===- AlphaRegisterInfo.cpp - Alpha Register Information -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains the Alpha implementation of the TargetRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "reginfo"
#include "Alpha.h"
#include "AlphaRegisterInfo.h"
#include "llvm/Constants.h"
#include "llvm/Type.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLocation.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include <cstdlib>
using namespace llvm;
//These describe LDAx
static const int IMM_LOW = -32768;
static const int IMM_HIGH = 32767;
static const int IMM_MULT = 65536;
static long getUpper16(long l)
{
long y = l / IMM_MULT;
if (l % IMM_MULT > IMM_HIGH)
++y;
return y;
}
static long getLower16(long l)
{
long h = getUpper16(l);
return l - h * IMM_MULT;
}
AlphaRegisterInfo::AlphaRegisterInfo(const TargetInstrInfo &tii)
: AlphaGenRegisterInfo(Alpha::ADJUSTSTACKDOWN, Alpha::ADJUSTSTACKUP),
TII(tii), curgpdist(0)
{
}
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
const {
static const unsigned CalleeSavedRegs[] = {
Alpha::R9, Alpha::R10,
Alpha::R11, Alpha::R12,
Alpha::R13, Alpha::R14,
Alpha::F2, Alpha::F3,
Alpha::F4, Alpha::F5,
Alpha::F6, Alpha::F7,
Alpha::F8, Alpha::F9, 0
};
return CalleeSavedRegs;
}
const TargetRegisterClass* const*
AlphaRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
&Alpha::GPRCRegClass, &Alpha::GPRCRegClass,
&Alpha::GPRCRegClass, &Alpha::GPRCRegClass,
&Alpha::GPRCRegClass, &Alpha::GPRCRegClass,
&Alpha::F8RCRegClass, &Alpha::F8RCRegClass,
&Alpha::F8RCRegClass, &Alpha::F8RCRegClass,
&Alpha::F8RCRegClass, &Alpha::F8RCRegClass,
&Alpha::F8RCRegClass, &Alpha::F8RCRegClass, 0
};
return CalleeSavedRegClasses;
}
BitVector AlphaRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
BitVector Reserved(getNumRegs());
Reserved.set(Alpha::R15);
Reserved.set(Alpha::R30);
Reserved.set(Alpha::R31);
return Reserved;
}
//===----------------------------------------------------------------------===//
// Stack Frame Processing methods
//===----------------------------------------------------------------------===//
// hasFP - Return true if the specified function should have a dedicated frame
// pointer register. This is true if the function has variable sized allocas or
// if frame pointer elimination is disabled.
//
bool AlphaRegisterInfo::hasFP(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
return MFI->hasVarSizedObjects();
}
void AlphaRegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
if (hasFP(MF)) {
// If we have a frame pointer, turn the adjcallstackup instruction into a
// 'sub ESP, <amt>' and the adjcallstackdown instruction into 'add ESP,
// <amt>'
MachineInstr *Old = I;
uint64_t Amount = Old->getOperand(0).getImm();
if (Amount != 0) {
// We need to keep the stack aligned properly. To do this, we round the
// amount of space needed for the outgoing arguments up to the next
// alignment boundary.
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
Amount = (Amount+Align-1)/Align*Align;
MachineInstr *New;
if (Old->getOpcode() == Alpha::ADJUSTSTACKDOWN) {
New=BuildMI(MF, Old->getDebugLoc(), TII.get(Alpha::LDA), Alpha::R30)
.addImm(-Amount).addReg(Alpha::R30);
} else {
assert(Old->getOpcode() == Alpha::ADJUSTSTACKUP);
New=BuildMI(MF, Old->getDebugLoc(), TII.get(Alpha::LDA), Alpha::R30)
.addImm(Amount).addReg(Alpha::R30);
}
// Replace the pseudo instruction with a new instruction...
MBB.insert(I, New);
}
}
MBB.erase(I);
}
//Alpha has a slightly funny stack:
//Args
//<- incoming SP
//fixed locals (and spills, callee saved, etc)
//<- FP
//variable locals
//<- SP
unsigned
AlphaRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, int *Value,
RegScavenger *RS) const {
assert(SPAdj == 0 && "Unexpected");
unsigned i = 0;
MachineInstr &MI = *II;
MachineBasicBlock &MBB = *MI.getParent();
MachineFunction &MF = *MBB.getParent();
bool FP = hasFP(MF);
while (!MI.getOperand(i).isFI()) {
++i;
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
}
int FrameIndex = MI.getOperand(i).getIndex();
// Add the base register of R30 (SP) or R15 (FP).
MI.getOperand(i + 1).ChangeToRegister(FP ? Alpha::R15 : Alpha::R30, false);
// Now add the frame object offset to the offset from the virtual frame index.
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex);
DEBUG(errs() << "FI: " << FrameIndex << " Offset: " << Offset << "\n");
Offset += MF.getFrameInfo()->getStackSize();
DEBUG(errs() << "Corrected Offset " << Offset
<< " for stack size: " << MF.getFrameInfo()->getStackSize() << "\n");
if (Offset > IMM_HIGH || Offset < IMM_LOW) {
DEBUG(errs() << "Unconditionally using R28 for evil purposes Offset: "
<< Offset << "\n");
//so in this case, we need to use a temporary register, and move the
//original inst off the SP/FP
//fix up the old:
MI.getOperand(i + 1).ChangeToRegister(Alpha::R28, false);
MI.getOperand(i).ChangeToImmediate(getLower16(Offset));
//insert the new
MachineInstr* nMI=BuildMI(MF, MI.getDebugLoc(),
TII.get(Alpha::LDAH), Alpha::R28)
.addImm(getUpper16(Offset)).addReg(FP ? Alpha::R15 : Alpha::R30);
MBB.insert(II, nMI);
} else {
MI.getOperand(i).ChangeToImmediate(Offset);
}
return 0;
}
void AlphaRegisterInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
MachineBasicBlock::iterator MBBI = MBB.begin();
MachineFrameInfo *MFI = MF.getFrameInfo();
DebugLoc dl = (MBBI != MBB.end() ?
MBBI->getDebugLoc() : DebugLoc::getUnknownLoc());
bool FP = hasFP(MF);
//handle GOP offset
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAHg), Alpha::R29)
.addGlobalAddress(const_cast<Function*>(MF.getFunction()))
.addReg(Alpha::R27).addImm(++curgpdist);
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAg), Alpha::R29)
.addGlobalAddress(const_cast<Function*>(MF.getFunction()))
.addReg(Alpha::R29).addImm(curgpdist);
//evil const_cast until MO stuff setup to handle const
BuildMI(MBB, MBBI, dl, TII.get(Alpha::ALTENT))
.addGlobalAddress(const_cast<Function*>(MF.getFunction()));
// Get the number of bytes to allocate from the FrameInfo
long NumBytes = MFI->getStackSize();
if (FP)
NumBytes += 8; //reserve space for the old FP
// Do we need to allocate space on the stack?
if (NumBytes == 0) return;
unsigned Align = MF.getTarget().getFrameInfo()->getStackAlignment();
NumBytes = (NumBytes+Align-1)/Align*Align;
// Update frame info to pretend that this is part of the stack...
MFI->setStackSize(NumBytes);
// adjust stack pointer: r30 -= numbytes
NumBytes = -NumBytes;
if (NumBytes >= IMM_LOW) {
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
.addReg(Alpha::R30);
} else if (getUpper16(NumBytes) >= IMM_LOW) {
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
} else {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Too big a stack frame at " + NumBytes;
llvm_report_error(Msg.str());
}
//now if we need to, save the old FP and set the new
if (FP)
{
BuildMI(MBB, MBBI, dl, TII.get(Alpha::STQ))
.addReg(Alpha::R15).addImm(0).addReg(Alpha::R30);
//this must be the last instr in the prolog
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R15)
.addReg(Alpha::R30).addReg(Alpha::R30);
}
}
void AlphaRegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
MachineBasicBlock::iterator MBBI = prior(MBB.end());
assert((MBBI->getOpcode() == Alpha::RETDAG ||
MBBI->getOpcode() == Alpha::RETDAGp)
&& "Can only insert epilog into returning blocks");
DebugLoc dl = MBBI->getDebugLoc();
bool FP = hasFP(MF);
// Get the number of bytes allocated from the FrameInfo...
long NumBytes = MFI->getStackSize();
//now if we need to, restore the old FP
if (FP) {
//copy the FP into the SP (discards allocas)
BuildMI(MBB, MBBI, dl, TII.get(Alpha::BISr), Alpha::R30).addReg(Alpha::R15)
.addReg(Alpha::R15);
//restore the FP
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDQ), Alpha::R15)
.addImm(0).addReg(Alpha::R15);
}
if (NumBytes != 0) {
if (NumBytes <= IMM_HIGH) {
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30).addImm(NumBytes)
.addReg(Alpha::R30);
} else if (getUpper16(NumBytes) <= IMM_HIGH) {
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDAH), Alpha::R30)
.addImm(getUpper16(NumBytes)).addReg(Alpha::R30);
BuildMI(MBB, MBBI, dl, TII.get(Alpha::LDA), Alpha::R30)
.addImm(getLower16(NumBytes)).addReg(Alpha::R30);
} else {
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Too big a stack frame at " + NumBytes;
llvm_report_error(Msg.str());
}
}
}
unsigned AlphaRegisterInfo::getRARegister() const {
llvm_unreachable("What is the return address register");
return 0;
}
unsigned AlphaRegisterInfo::getFrameRegister(MachineFunction &MF) const {
return hasFP(MF) ? Alpha::R15 : Alpha::R30;
}
unsigned AlphaRegisterInfo::getEHExceptionRegister() const {
llvm_unreachable("What is the exception register");
return 0;
}
unsigned AlphaRegisterInfo::getEHHandlerRegister() const {
llvm_unreachable("What is the exception handler register");
return 0;
}
int AlphaRegisterInfo::getDwarfRegNum(unsigned RegNum, bool isEH) const {
llvm_unreachable("What is the dwarf register number");
return -1;
}
#include "AlphaGenRegisterInfo.inc"
std::string AlphaRegisterInfo::getPrettyName(unsigned reg)
{
std::string s(RegisterDescriptors[reg].Name);
return s;
}