mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 23:18:58 +00:00
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:
parent
68fe665b9a
commit
cef95f702a
@ -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::
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user