
Note: I do not implement a base pointer, so it's still impossible to have dynamic realignment AND dynamic alloca in the same function. This also moves the code for determining the frame index reference into getFrameIndexReference, where it belongs, instead of inline in eliminateFrameIndex. [Begin long-winded screed] Now, stack realignment for Sparc is actually a silly thing to support, because the Sparc ABI has no need for it -- unlike the situation on x86, the stack is ALWAYS aligned to the required alignment for the CPU instructions: 8 bytes on sparcv8, and 16 bytes on sparcv9. However, LLVM unfortunately implements user-specified overalignment using stack realignment support, so for now, I'm going to go along with that tradition. GCC instead treats objects which have alignment specification greater than the maximum CPU-required alignment for the target as a separate block of stack memory, with their own virtual base pointer (which gets aligned). Doing it that way avoids needing to implement per-target support for stack realignment, except for the targets which *actually* have an ABI-specified stack alignment which is too small for the CPU's requirements. Further unfortunately in LLVM, the default canRealignStack for all targets effectively returns true, despite that implementing that is something a target needs to do specifically. So, the previous behavior on Sparc was to silently ignore the user's specified stack alignment. Ugh. Yet MORE unfortunate, if a target actually does return false from canRealignStack, that also causes the user-specified alignment to be *silently ignored*, rather than emitting an error. (I started looking into fixing that last, but it broke a bunch of tests, because LLVM actually *depends* on having it silently ignored: some architectures (e.g. non-linux i386) have smaller stack alignment than spilled-register alignment. But, the fact that a register needs spilling is not known until within the register allocator. And by that point, the decision to not reserve the frame pointer has been frozen in place. And without a frame pointer, stack realignment is not possible. So, canRealignStack() returns false, and needsStackRealignment() then returns false, assuming everyone can just go on their merry way assuming the alignment requirements were probably just suggestions after-all. Sigh...) Differential Revision: http://reviews.llvm.org/D12208 llvm-svn: 245668
339 lines
12 KiB
C++
339 lines
12 KiB
C++
//===-- SparcFrameLowering.cpp - Sparc Frame Information ------------------===//
|
|
//
|
|
// 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 Sparc implementation of TargetFrameLowering class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "SparcFrameLowering.h"
|
|
#include "SparcInstrInfo.h"
|
|
#include "SparcMachineFunctionInfo.h"
|
|
#include "SparcSubtarget.h"
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
#include "llvm/IR/DataLayout.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/Support/CommandLine.h"
|
|
#include "llvm/Target/TargetOptions.h"
|
|
|
|
using namespace llvm;
|
|
|
|
static cl::opt<bool>
|
|
DisableLeafProc("disable-sparc-leaf-proc",
|
|
cl::init(false),
|
|
cl::desc("Disable Sparc leaf procedure optimization."),
|
|
cl::Hidden);
|
|
|
|
SparcFrameLowering::SparcFrameLowering(const SparcSubtarget &ST)
|
|
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown,
|
|
ST.is64Bit() ? 16 : 8, 0, ST.is64Bit() ? 16 : 8) {}
|
|
|
|
void SparcFrameLowering::emitSPAdjustment(MachineFunction &MF,
|
|
MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator MBBI,
|
|
int NumBytes,
|
|
unsigned ADDrr,
|
|
unsigned ADDri) const {
|
|
|
|
DebugLoc dl = (MBBI != MBB.end()) ? MBBI->getDebugLoc() : DebugLoc();
|
|
const SparcInstrInfo &TII =
|
|
*static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
|
|
|
if (NumBytes >= -4096 && NumBytes < 4096) {
|
|
BuildMI(MBB, MBBI, dl, TII.get(ADDri), SP::O6)
|
|
.addReg(SP::O6).addImm(NumBytes);
|
|
return;
|
|
}
|
|
|
|
// Emit this the hard way. This clobbers G1 which we always know is
|
|
// available here.
|
|
if (NumBytes >= 0) {
|
|
// Emit nonnegative numbers with sethi + or.
|
|
// sethi %hi(NumBytes), %g1
|
|
// or %g1, %lo(NumBytes), %g1
|
|
// add %sp, %g1, %sp
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
|
|
.addImm(HI22(NumBytes));
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::ORri), SP::G1)
|
|
.addReg(SP::G1).addImm(LO10(NumBytes));
|
|
BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
|
|
.addReg(SP::O6).addReg(SP::G1);
|
|
return ;
|
|
}
|
|
|
|
// Emit negative numbers with sethi + xor.
|
|
// sethi %hix(NumBytes), %g1
|
|
// xor %g1, %lox(NumBytes), %g1
|
|
// add %sp, %g1, %sp
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::SETHIi), SP::G1)
|
|
.addImm(HIX22(NumBytes));
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::XORri), SP::G1)
|
|
.addReg(SP::G1).addImm(LOX10(NumBytes));
|
|
BuildMI(MBB, MBBI, dl, TII.get(ADDrr), SP::O6)
|
|
.addReg(SP::O6).addReg(SP::G1);
|
|
}
|
|
|
|
void SparcFrameLowering::emitPrologue(MachineFunction &MF,
|
|
MachineBasicBlock &MBB) const {
|
|
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
|
|
|
|
assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
const SparcInstrInfo &TII =
|
|
*static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
|
const SparcRegisterInfo &RegInfo =
|
|
*static_cast<const SparcRegisterInfo *>(MF.getSubtarget().getRegisterInfo());
|
|
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
|
|
bool NeedsStackRealignment = RegInfo.needsStackRealignment(MF);
|
|
|
|
// FIXME: unfortunately, returning false from canRealignStack
|
|
// actually just causes needsStackRealignment to return false,
|
|
// rather than reporting an error, as would be sensible. This is
|
|
// poor, but fixing that bogosity is going to be a large project.
|
|
// For now, just see if it's lied, and report an error here.
|
|
if (!NeedsStackRealignment && MFI->getMaxAlignment() > getStackAlignment())
|
|
report_fatal_error("Function \"" + Twine(MF.getName()) + "\" required "
|
|
"stack re-alignment, but LLVM couldn't handle it "
|
|
"(probably because it has a dynamic alloca).");
|
|
|
|
// Get the number of bytes to allocate from the FrameInfo
|
|
int NumBytes = (int) MFI->getStackSize();
|
|
|
|
unsigned SAVEri = SP::SAVEri;
|
|
unsigned SAVErr = SP::SAVErr;
|
|
if (FuncInfo->isLeafProc()) {
|
|
if (NumBytes == 0)
|
|
return;
|
|
SAVEri = SP::ADDri;
|
|
SAVErr = SP::ADDrr;
|
|
}
|
|
|
|
NumBytes = MF.getSubtarget<SparcSubtarget>().getAdjustedFrameSize(NumBytes);
|
|
MFI->setStackSize(NumBytes); // Update stack size with corrected value.
|
|
|
|
emitSPAdjustment(MF, MBB, MBBI, -NumBytes, SAVErr, SAVEri);
|
|
|
|
MachineModuleInfo &MMI = MF.getMMI();
|
|
unsigned regFP = RegInfo.getDwarfRegNum(SP::I6, true);
|
|
|
|
// Emit ".cfi_def_cfa_register 30".
|
|
unsigned CFIIndex =
|
|
MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(nullptr, regFP));
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
.addCFIIndex(CFIIndex);
|
|
|
|
// Emit ".cfi_window_save".
|
|
CFIIndex = MMI.addFrameInst(MCCFIInstruction::createWindowSave(nullptr));
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
.addCFIIndex(CFIIndex);
|
|
|
|
unsigned regInRA = RegInfo.getDwarfRegNum(SP::I7, true);
|
|
unsigned regOutRA = RegInfo.getDwarfRegNum(SP::O7, true);
|
|
// Emit ".cfi_register 15, 31".
|
|
CFIIndex = MMI.addFrameInst(
|
|
MCCFIInstruction::createRegister(nullptr, regOutRA, regInRA));
|
|
BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
.addCFIIndex(CFIIndex);
|
|
|
|
if (NeedsStackRealignment) {
|
|
// andn %o6, MaxAlign-1, %o6
|
|
int MaxAlign = MFI->getMaxAlignment();
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::ANDNri), SP::O6).addReg(SP::O6).addImm(MaxAlign - 1);
|
|
}
|
|
}
|
|
|
|
void SparcFrameLowering::
|
|
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
MachineBasicBlock::iterator I) const {
|
|
if (!hasReservedCallFrame(MF)) {
|
|
MachineInstr &MI = *I;
|
|
int Size = MI.getOperand(0).getImm();
|
|
if (MI.getOpcode() == SP::ADJCALLSTACKDOWN)
|
|
Size = -Size;
|
|
|
|
if (Size)
|
|
emitSPAdjustment(MF, MBB, I, Size, SP::ADDrr, SP::ADDri);
|
|
}
|
|
MBB.erase(I);
|
|
}
|
|
|
|
|
|
void SparcFrameLowering::emitEpilogue(MachineFunction &MF,
|
|
MachineBasicBlock &MBB) const {
|
|
SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
|
|
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
|
|
const SparcInstrInfo &TII =
|
|
*static_cast<const SparcInstrInfo *>(MF.getSubtarget().getInstrInfo());
|
|
DebugLoc dl = MBBI->getDebugLoc();
|
|
assert(MBBI->getOpcode() == SP::RETL &&
|
|
"Can only put epilog before 'retl' instruction!");
|
|
if (!FuncInfo->isLeafProc()) {
|
|
BuildMI(MBB, MBBI, dl, TII.get(SP::RESTORErr), SP::G0).addReg(SP::G0)
|
|
.addReg(SP::G0);
|
|
return;
|
|
}
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
int NumBytes = (int) MFI->getStackSize();
|
|
if (NumBytes == 0)
|
|
return;
|
|
|
|
emitSPAdjustment(MF, MBB, MBBI, NumBytes, SP::ADDrr, SP::ADDri);
|
|
}
|
|
|
|
bool SparcFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
|
|
// Reserve call frame if there are no variable sized objects on the stack.
|
|
return !MF.getFrameInfo()->hasVarSizedObjects();
|
|
}
|
|
|
|
// 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 SparcFrameLowering::hasFP(const MachineFunction &MF) const {
|
|
const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
|
|
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
return MF.getTarget().Options.DisableFramePointerElim(MF) ||
|
|
RegInfo->needsStackRealignment(MF) ||
|
|
MFI->hasVarSizedObjects() ||
|
|
MFI->isFrameAddressTaken();
|
|
}
|
|
|
|
|
|
int SparcFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
|
|
unsigned &FrameReg) const {
|
|
const SparcSubtarget &Subtarget = MF.getSubtarget<SparcSubtarget>();
|
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
const SparcRegisterInfo *RegInfo = Subtarget.getRegisterInfo();
|
|
const SparcMachineFunctionInfo *FuncInfo = MF.getInfo<SparcMachineFunctionInfo>();
|
|
bool isFixed = MFI->isFixedObjectIndex(FI);
|
|
|
|
// Addressable stack objects are accessed using neg. offsets from
|
|
// %fp, or positive offsets from %sp.
|
|
bool UseFP;
|
|
|
|
// Sparc uses FP-based references in general, even when "hasFP" is
|
|
// false. That function is rather a misnomer, because %fp is
|
|
// actually always available, unless isLeafProc.
|
|
if (FuncInfo->isLeafProc()) {
|
|
// If there's a leaf proc, all offsets need to be %sp-based,
|
|
// because we haven't caused %fp to actually point to our frame.
|
|
UseFP = false;
|
|
} else if (isFixed) {
|
|
// Otherwise, argument access should always use %fp.
|
|
UseFP = true;
|
|
} else if (RegInfo->needsStackRealignment(MF)) {
|
|
// If there is dynamic stack realignment, all local object
|
|
// references need to be via %sp, to take account of the
|
|
// re-alignment.
|
|
UseFP = false;
|
|
} else {
|
|
// Finally, default to using %fp.
|
|
UseFP = true;
|
|
}
|
|
|
|
int64_t FrameOffset = MF.getFrameInfo()->getObjectOffset(FI) +
|
|
Subtarget.getStackPointerBias();
|
|
|
|
if (UseFP) {
|
|
FrameReg = RegInfo->getFrameRegister(MF);
|
|
return FrameOffset;
|
|
} else {
|
|
FrameReg = SP::O6; // %sp
|
|
return FrameOffset + MF.getFrameInfo()->getStackSize();
|
|
}
|
|
}
|
|
|
|
static bool LLVM_ATTRIBUTE_UNUSED verifyLeafProcRegUse(MachineRegisterInfo *MRI)
|
|
{
|
|
|
|
for (unsigned reg = SP::I0; reg <= SP::I7; ++reg)
|
|
if (!MRI->reg_nodbg_empty(reg))
|
|
return false;
|
|
|
|
for (unsigned reg = SP::L0; reg <= SP::L7; ++reg)
|
|
if (!MRI->reg_nodbg_empty(reg))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool SparcFrameLowering::isLeafProc(MachineFunction &MF) const
|
|
{
|
|
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
|
|
|
return !(MFI->hasCalls() // has calls
|
|
|| !MRI.reg_nodbg_empty(SP::L0) // Too many registers needed
|
|
|| !MRI.reg_nodbg_empty(SP::O6) // %SP is used
|
|
|| hasFP(MF)); // need %FP
|
|
}
|
|
|
|
void SparcFrameLowering::remapRegsForLeafProc(MachineFunction &MF) const {
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
// Remap %i[0-7] to %o[0-7].
|
|
for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
|
|
if (MRI.reg_nodbg_empty(reg))
|
|
continue;
|
|
|
|
unsigned mapped_reg = reg - SP::I0 + SP::O0;
|
|
assert(MRI.reg_nodbg_empty(mapped_reg));
|
|
|
|
// Replace I register with O register.
|
|
MRI.replaceRegWith(reg, mapped_reg);
|
|
|
|
// Also replace register pair super-registers.
|
|
if ((reg - SP::I0) % 2 == 0) {
|
|
unsigned preg = (reg - SP::I0) / 2 + SP::I0_I1;
|
|
unsigned mapped_preg = preg - SP::I0_I1 + SP::O0_O1;
|
|
MRI.replaceRegWith(preg, mapped_preg);
|
|
}
|
|
}
|
|
|
|
// Rewrite MBB's Live-ins.
|
|
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
|
|
MBB != E; ++MBB) {
|
|
for (unsigned reg = SP::I0_I1; reg <= SP::I6_I7; ++reg) {
|
|
if (!MBB->isLiveIn(reg))
|
|
continue;
|
|
MBB->removeLiveIn(reg);
|
|
MBB->addLiveIn(reg - SP::I0_I1 + SP::O0_O1);
|
|
}
|
|
for (unsigned reg = SP::I0; reg <= SP::I7; ++reg) {
|
|
if (!MBB->isLiveIn(reg))
|
|
continue;
|
|
MBB->removeLiveIn(reg);
|
|
MBB->addLiveIn(reg - SP::I0 + SP::O0);
|
|
}
|
|
}
|
|
|
|
assert(verifyLeafProcRegUse(&MRI));
|
|
#ifdef XDEBUG
|
|
MF.verify(0, "After LeafProc Remapping");
|
|
#endif
|
|
}
|
|
|
|
void SparcFrameLowering::determineCalleeSaves(MachineFunction &MF,
|
|
BitVector &SavedRegs,
|
|
RegScavenger *RS) const {
|
|
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS);
|
|
if (!DisableLeafProc && isLeafProc(MF)) {
|
|
SparcMachineFunctionInfo *MFI = MF.getInfo<SparcMachineFunctionInfo>();
|
|
MFI->setLeafProc(true);
|
|
|
|
remapRegsForLeafProc(MF);
|
|
}
|
|
|
|
}
|