fix most of remaining issues with large frames.

these patches are tested a lot by test-suite but
make check tests are forthcoming once the next
few patches that complete this are committed.
with the next few patches the pass rate for mips16 is
near 100%



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@170656 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Reed Kotler 2012-12-20 04:07:42 +00:00
parent 68fe665b9a
commit cef95f702a
5 changed files with 197 additions and 20 deletions

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "Mips16FrameLowering.h"
#include "Mips16InstrInfo.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsInstrInfo.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@ -29,8 +30,8 @@ using namespace llvm;
void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front();
MachineFrameInfo *MFI = MF.getFrameInfo();
const MipsInstrInfo &TII =
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
const Mips16InstrInfo &TII =
*static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
MachineBasicBlock::iterator MBBI = MBB.begin();
DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
uint64_t StackSize = MFI->getStackSize();
@ -39,8 +40,7 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
if (StackSize == 0 && !MFI->adjustsStack()) return;
// Adjust stack.
if (isInt<16>(-StackSize))
BuildMI(MBB, MBBI, dl, TII.get(Mips::SaveRaF16)).addImm(StackSize);
TII.makeFrame(Mips::SP, StackSize, MBB, MBBI);
if (hasFP(MF))
BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
@ -52,8 +52,8 @@ void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
MachineFrameInfo *MFI = MF.getFrameInfo();
const MipsInstrInfo &TII =
*static_cast<const MipsInstrInfo*>(MF.getTarget().getInstrInfo());
const Mips16InstrInfo &TII =
*static_cast<const Mips16InstrInfo*>(MF.getTarget().getInstrInfo());
DebugLoc dl = MBBI->getDebugLoc();
uint64_t StackSize = MFI->getStackSize();
@ -65,9 +65,8 @@ void Mips16FrameLowering::emitEpilogue(MachineFunction &MF,
.addReg(Mips::S0);
// Adjust stack.
if (isInt<16>(StackSize))
// assumes stacksize multiple of 8
BuildMI(MBB, MBBI, dl, TII.get(Mips::RestoreRaF16)).addImm(StackSize);
// assumes stacksize multiple of 8
TII.restoreFrame(Mips::SP, StackSize, MBB, MBBI);
}
bool Mips16FrameLowering::

View File

@ -19,11 +19,19 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
static cl::opt<bool> NeverUseSaveRestore(
"mips16-never-use-save-restore",
cl::init(false),
cl::desc("For testing ability to adjust stack pointer without save/restore instruction"),
cl::Hidden);
Mips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm)
: MipsInstrInfo(tm, Mips::BimmX16),
RI(*tm.getSubtargetImpl(), *this) {}
@ -160,20 +168,135 @@ unsigned Mips16InstrInfo::GetOppositeBranchOpc(unsigned Opc) const {
return 0;
}
// Adjust SP by FrameSize bytes. Save RA, S0, S1
void Mips16InstrInfo::makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
if (!NeverUseSaveRestore) {
if (isUInt<11>(FrameSize))
BuildMI(MBB, I, DL, get(Mips::SaveRaF16)).addImm(FrameSize);
else {
int Base = 2040; // should create template function like isUInt that returns largest
// possible n bit unsigned integer
int64_t Remainder = FrameSize - Base;
BuildMI(MBB, I, DL, get(Mips::SaveRaF16)). addImm(Base);
if (isInt<16>(-Remainder))
BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(-Remainder);
else
adjustStackPtrBig(SP, -Remainder, MBB, I, Mips::V0, Mips::V1);
}
}
else {
//
// sw ra, -4[sp]
// sw s1, -8[sp]
// sw s0, -12[sp]
MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16), Mips::RA);
MIB1.addReg(Mips::SP);
MIB1.addImm(-4);
MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16), Mips::S1);
MIB2.addReg(Mips::SP);
MIB2.addImm(-8);
MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::SwRxSpImmX16), Mips::S0);
MIB3.addReg(Mips::SP);
MIB3.addImm(-12);
adjustStackPtrBig(SP, -FrameSize, MBB, I, Mips::V0, Mips::V1);
}
}
// Adjust SP by FrameSize bytes. Restore RA, S0, S1
void Mips16InstrInfo::restoreFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
if (!NeverUseSaveRestore) {
if (isUInt<11>(FrameSize))
BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)).addImm(FrameSize);
else {
int Base = 2040; // should create template function like isUInt that returns largest
// possible n bit unsigned integer
int64_t Remainder = FrameSize - Base;
if (isInt<16>(Remainder))
BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(Remainder);
else
adjustStackPtrBig(SP, Remainder, MBB, I, Mips::A0, Mips::A1);
BuildMI(MBB, I, DL, get(Mips::RestoreRaF16)). addImm(Base);
}
}
else {
adjustStackPtrBig(SP, FrameSize, MBB, I, Mips::A0, Mips::A1);
// lw ra, -4[sp]
// lw s1, -8[sp]
// lw s0, -12[sp]
MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16), Mips::A0);
MIB1.addReg(Mips::SP);
MIB1.addImm(-4);
MachineInstrBuilder MIB0 = BuildMI(MBB, I, DL, get(Mips::Move32R16), Mips::RA);
MIB0.addReg(Mips::A0);
MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16), Mips::S1);
MIB2.addReg(Mips::SP);
MIB2.addImm(-8);
MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::LwRxSpImmX16), Mips::S0);
MIB3.addReg(Mips::SP);
MIB3.addImm(-12);
}
}
// Adjust SP by Amount bytes where bytes can be up to 32bit number.
// This can only be called at times that we know that there is at least one free register.
// This is clearly safe at prologue and epilogue.
//
void Mips16InstrInfo::adjustStackPtrBig(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned Reg1, unsigned Reg2) const {
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
// MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
// unsigned Reg1 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
// unsigned Reg2 = RegInfo.createVirtualRegister(&Mips::CPU16RegsRegClass);
//
// li reg1, constant
// move reg2, sp
// add reg1, reg1, reg2
// move sp, reg1
//
//
MachineInstrBuilder MIB1 = BuildMI(MBB, I, DL, get(Mips::LwConstant32), Reg1);
MIB1.addImm(Amount);
MachineInstrBuilder MIB2 = BuildMI(MBB, I, DL, get(Mips::MoveR3216), Reg2);
MIB2.addReg(Mips::SP, RegState::Kill);
MachineInstrBuilder MIB3 = BuildMI(MBB, I, DL, get(Mips::AdduRxRyRz16), Reg1);
MIB3.addReg(Reg1);
MIB3.addReg(Reg2, RegState::Kill);
MachineInstrBuilder MIB4 = BuildMI(MBB, I, DL, get(Mips::Move32R16), Mips::SP);
MIB4.addReg(Reg1, RegState::Kill);
}
void Mips16InstrInfo::adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
assert(false && "adjust stack pointer amount exceeded");
}
/// Adjust SP by Amount bytes.
void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
if (isInt<16>(Amount)) {
if (Amount < 0)
BuildMI(MBB, I, DL, get(Mips::SaveDecSpF16)). addImm(-Amount);
else if (Amount > 0)
BuildMI(MBB, I, DL, get(Mips::RestoreIncSpF16)).addImm(Amount);
}
if (isInt<16>(Amount)) // need to change to addiu sp, ....and isInt<16>
BuildMI(MBB, I, DL, get(Mips::AddiuSpImmX16)). addImm(Amount);
else
// not implemented for large values yet
assert(false && "adjust stack pointer amount exceeded");
adjustStackPtrBigUnrestricted(SP, Amount, MBB, I);
}
/// This function generates the sequence of instructions needed to get the
/// result of adding register REG and immediate IMM.
unsigned
Mips16InstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
unsigned *NewImm) const {
return 0;
}
unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {

View File

@ -64,15 +64,42 @@ public:
virtual unsigned GetOppositeBranchOpc(unsigned Opc) const;
// Adjust SP by FrameSize bytes. Save RA, S0, S1
void makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
// Adjust SP by FrameSize bytes. Restore RA, S0, S1
void restoreFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
/// Adjust SP by Amount bytes.
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
/// Emit a series of instructions to load an immediate. If NewImm is a
/// non-NULL parameter, the last instruction is not emitted, but instead
/// its immediate operand is returned in NewImm.
unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
unsigned *NewImm) const;
private:
virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
// Adjust SP by Amount bytes where bytes can be up to 32bit number.
void adjustStackPtrBig(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned Reg1, unsigned Reg2) const;
// Adjust SP by Amount bytes where bytes can be up to 32bit number.
void adjustStackPtrBigUnrestricted(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
};
}

View File

@ -57,13 +57,17 @@ class FEXT_I16_ins<bits<5> eop, string asmstr, InstrItinClass itin> :
class FEXT_I816_ins_base<bits<3> _func, string asmstr,
string asmstr2, InstrItinClass itin>:
FEXT_I816<_func, (outs), (ins uimm16:$imm), !strconcat(asmstr, asmstr2),
FEXT_I816<_func, (outs), (ins simm16:$imm), !strconcat(asmstr, asmstr2),
[], itin>;
class FEXT_I816_ins<bits<3> _func, string asmstr,
InstrItinClass itin>:
FEXT_I816_ins_base<_func, asmstr, "\t$imm", itin>;
class FEXT_I816_SP_ins<bits<3> _func, string asmstr,
InstrItinClass itin>:
FEXT_I816_ins_base<_func, asmstr, "\t$$sp, $imm", itin>;
//
// Assembler formats in alphabetical order.
// Natural and pseudos are mixed together.
@ -352,6 +356,18 @@ class SelT<bits<5> f1, string op1, bits<5> f2, string op2,
let Constraints = "$rd = $rd_";
}
//
// 32 bit constant
//
def imm32: Operand<i32>;
def Constant32:
MipsPseudo16<(outs), (ins imm32:$imm), "\t.word $imm", []>;
def LwConstant32:
MipsPseudo16<(outs), (ins CPU16Regs:$rx, imm32:$imm),
"lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>;
//
// Some general instruction class info
@ -404,6 +420,18 @@ def AddiuRxRyOffMemX16:
// To add a constant to the program counter.
//
def AddiuRxPcImmX16: FEXT_RI16_PC_ins<0b00001, "addiu", IIAlu>;
//
// Format: ADDIU sp, immediate MIPS16e
// Purpose: Add Immediate Unsigned Word (2-Operand, SP-Relative, Extended)
// To add a constant to the stack pointer.
//
def AddiuSpImmX16
: FEXT_I816_SP_ins<0b011, "addiu", IIAlu> {
let Defs = [SP];
let Uses = [SP];
}
//
// Format: ADDU rz, rx, ry MIPS16e
// Purpose: Add Unsigned Word (3-Operand)

View File

@ -68,8 +68,8 @@ entry:
%21 = load i32** %ip, align 4
%arrayidx6 = getelementptr inbounds i32* %21, i32 %20
%22 = load i32* %arrayidx6, align 4
; 16: save 16
; 16: addiu $sp, -16
call void @temp(i32 %22)
; 16: restore 16
; 16: addiu $sp, 16
ret void
}