Modify MipsFrameLowering::emitPrologue and emitEpilogue.

- Use MipsAnalyzeImmediate to expand immediates that do not fit in 16-bit.
- Change the types of variables so that they are sufficiently large to handle
  64-bit pointers.
- Emit instructions to set register $28 in a function prologue after
  instructions which store callee-saved registers have been emitted. 
 

llvm-svn: 148917
This commit is contained in:
Akira Hatanaka 2012-01-25 04:12:04 +00:00
parent 9a829c1762
commit 175341c860
2 changed files with 70 additions and 80 deletions

View File

@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
#include "MipsAnalyzeImmediate.h"
#include "MipsFrameLowering.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
@ -93,47 +94,40 @@ bool MipsFrameLowering::targetHandlesStackFrameRounding() const {
return true;
}
static unsigned AlignOffset(unsigned Offset, unsigned Align) {
return (Offset + Align - 1) / Align * Align;
}
// expand pair of register and immediate if the immediate doesn't fit in the
// 16-bit offset field.
// e.g.
// if OrigImm = 0x10000, OrigReg = $sp:
// generate the following sequence of instrs:
// lui $at, hi(0x10000)
// addu $at, $sp, $at
//
// (NewReg, NewImm) = ($at, lo(Ox10000))
// return true
static bool expandRegLargeImmPair(unsigned OrigReg, int OrigImm,
unsigned& NewReg, int& NewImm,
MachineBasicBlock& MBB,
MachineBasicBlock::iterator I) {
// OrigImm fits in the 16-bit field
if (OrigImm < 0x8000 && OrigImm >= -0x8000) {
NewReg = OrigReg;
NewImm = OrigImm;
return false;
}
MachineFunction* MF = MBB.getParent();
const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
DebugLoc DL = I->getDebugLoc();
int ImmLo = (short)(OrigImm & 0xffff);
int ImmHi = (((unsigned)OrigImm & 0xffff0000) >> 16) +
((OrigImm & 0x8000) != 0);
// Build an instruction sequence to load an immediate that is too large to fit
// in 16-bit and add the result to Reg.
static void expandLargeImm(unsigned Reg, int64_t Imm, bool IsN64,
const MipsInstrInfo &TII, MachineBasicBlock& MBB,
MachineBasicBlock::iterator II, DebugLoc DL) {
unsigned LUi = IsN64 ? Mips::LUi64 : Mips::LUi;
unsigned ADDu = IsN64 ? Mips::DADDu : Mips::ADDu;
unsigned ZEROReg = IsN64 ? Mips::ZERO_64 : Mips::ZERO;
unsigned ATReg = IsN64 ? Mips::AT_64 : Mips::AT;
MipsAnalyzeImmediate AnalyzeImm;
const MipsAnalyzeImmediate::InstSeq &Seq =
AnalyzeImm.Analyze(Imm, IsN64 ? 64 : 32, false /* LastInstrIsADDiu */);
MipsAnalyzeImmediate::InstSeq::const_iterator Inst = Seq.begin();
// FIXME: change this when mips goes MC".
BuildMI(MBB, I, DL, TII->get(Mips::NOAT));
BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::AT).addImm(ImmHi);
BuildMI(MBB, I, DL, TII->get(Mips::ADDu), Mips::AT).addReg(OrigReg)
.addReg(Mips::AT);
NewReg = Mips::AT;
NewImm = ImmLo;
BuildMI(MBB, II, DL, TII.get(Mips::NOAT));
return true;
// The first instruction can be a LUi, which is different from other
// instructions (ADDiu, ORI and SLL) in that it does not have a register
// operand.
if (Inst->Opc == LUi)
BuildMI(MBB, II, DL, TII.get(LUi), ATReg)
.addImm(SignExtend64<16>(Inst->ImmOpnd));
else
BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ZEROReg)
.addImm(SignExtend64<16>(Inst->ImmOpnd));
// Build the remaining instructions in Seq.
for (++Inst; Inst != Seq.end(); ++Inst)
BuildMI(MBB, II, DL, TII.get(Inst->Opc), ATReg).addReg(ATReg)
.addImm(SignExtend64<16>(Inst->ImmOpnd));
BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(Reg).addReg(ATReg);
BuildMI(MBB, II, DL, TII.get(Mips::ATMACRO));
}
void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
@ -142,14 +136,12 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
const MipsRegisterInfo *RegInfo =
static_cast<const MipsRegisterInfo*>(MF.getTarget().getRegisterInfo());
MachineRegisterInfo& MRI = MF.getRegInfo();
const MipsInstrInfo &TII =
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
bool isPIC = (MF.getTarget().getRelocationModel() == Reloc::PIC_);
unsigned NewReg = 0;
int NewImm = 0;
bool ATUsed;
unsigned GP = STI.isABI_N64() ? Mips::GP_64 : Mips::GP;
unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9;
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
@ -165,33 +157,23 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
unsigned LocalVarAreaOffset = MipsFI->needGPSaveRestore() ?
(MFI->getObjectOffset(MipsFI->getGPFI()) + RegSize) :
MipsFI->getMaxCallFrameSize();
unsigned StackSize = AlignOffset(LocalVarAreaOffset, StackAlign) +
AlignOffset(MFI->getStackSize(), StackAlign);
uint64_t StackSize = RoundUpToAlignment(LocalVarAreaOffset, StackAlign) +
RoundUpToAlignment(MFI->getStackSize(), StackAlign);
// Update stack size
MFI->setStackSize(StackSize);
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
// Emit instructions that set $gp using the the value of $t9.
// O32 uses the directive .cpload while N32/64 requires three instructions to
// do this.
// TODO: Do not emit these instructions if no instructions use $gp.
if (isPIC && STI.isABI_O32())
BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD))
BuildMI(MBB, MBBI, dl, TII.get(Mips::CPLOAD))
.addReg(RegInfo->getPICCallReg());
else if (STI.isABI_N64() || (isPIC && STI.isABI_N32())) {
// lui $28,%hi(%neg(%gp_rel(fname)))
// addu $28,$28,$25
// addiu $28,$28,%lo(%neg(%gp_rel(fname)))
const GlobalValue *FName = MF.getFunction();
BuildMI(MBB, MBBI, dl, TII.get(LUi), GP)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
BuildMI(MBB, MBBI, dl, TII.get(ADDu), GP).addReg(GP).addReg(T9);
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), GP).addReg(GP)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
}
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
// No need to allocate space on the stack.
if (StackSize == 0 && !MFI->adjustsStack()) return;
@ -200,13 +182,11 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
std::vector<MachineMove> &Moves = MMI.getFrameMoves();
MachineLocation DstML, SrcML;
// Adjust stack : addi sp, sp, (-imm)
ATUsed = expandRegLargeImmPair(SP, -StackSize, NewReg, NewImm, MBB, MBBI);
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm);
// FIXME: change this when mips goes MC".
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
// Adjust stack.
if (isInt<16>(-StackSize)) // addi sp, sp, (-stacksize)
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(-StackSize);
else // Expand immediate that doesn't fit in 16-bit.
expandLargeImm(SP, -StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl);
// emit ".cfi_def_cfa_offset StackSize"
MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol();
@ -259,6 +239,21 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
}
}
if ((STI.isABI_N64() || (isPIC && STI.isABI_N32())) &&
MRI.isPhysRegUsed(GP)) {
// lui $28,%hi(%neg(%gp_rel(fname)))
// addu $28,$28,$25
// addiu $28,$28,%lo(%neg(%gp_rel(fname)))
MachineBasicBlock::iterator InsPos = llvm::prior(MBBI);
const GlobalValue *FName = MF.getFunction();
BuildMI(MBB, MBBI, dl, TII.get(LUi), GP)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
BuildMI(MBB, MBBI, dl, TII.get(ADDu), GP).addReg(GP).addReg(T9);
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), GP).addReg(GP)
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
MBBI = ++InsPos;
}
// if framepointer enabled, set it to point to the stack pointer.
if (hasFP(MF)) {
// Insert instruction "move $fp, $sp" at this location.
@ -298,13 +293,6 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
// Get the number of bytes from FrameInfo
unsigned StackSize = MFI->getStackSize();
unsigned NewReg = 0;
int NewImm = 0;
bool ATUsed = false;
// if framepointer enabled, restore the stack pointer.
if (hasFP(MF)) {
// Find the first instruction that restores a callee-saved register.
@ -317,15 +305,17 @@ void MipsFrameLowering::emitEpilogue(MachineFunction &MF,
BuildMI(MBB, I, dl, TII.get(ADDu), SP).addReg(FP).addReg(ZERO);
}
// adjust stack : insert addi sp, sp, (imm)
if (StackSize) {
ATUsed = expandRegLargeImmPair(SP, StackSize, NewReg, NewImm, MBB, MBBI);
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(NewReg).addImm(NewImm);
// Get the number of bytes from FrameInfo
uint64_t StackSize = MFI->getStackSize();
// FIXME: change this when mips goes MC".
if (ATUsed)
BuildMI(MBB, MBBI, dl, TII.get(Mips::ATMACRO));
}
if (!StackSize)
return;
// Adjust stack.
if (isInt<16>(StackSize)) // addi sp, sp, (-stacksize)
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), SP).addReg(SP).addImm(StackSize);
else // Expand immediate that doesn't fit in 16-bit.
expandLargeImm(SP, StackSize, STI.isABI_N64(), TII, MBB, MBBI, dl);
}
void MipsFrameLowering::

View File

@ -7,8 +7,8 @@
define void @f() nounwind {
entry:
; CHECK: lui $at, 65534
; CHECK: addu $at, $sp, $at
; CHECK: addiu $sp, $at, -24
; CHECK: addiu $at, $at, -24
; CHECK: addu $sp, $sp, $at
; CHECK: .cprestore 65536
%agg.tmp = alloca %struct.S1, align 1