mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-08 21:32:39 +00:00
Add an option to use a virtual register as the global base register instead of
reserving a physical register ($gp or $28) for that purpose. This will completely eliminate loads that restore the value of $gp after every function call, if the register allocator assigns a callee-saved register, or eliminate unnecessary loads if it assigns a temporary register. example: .cpload $25 // set $gp. ... .cprestore 16 // store $gp to stack slot 16($sp). ... jalr $25 // function call. clobbers $gp. lw $gp, 16($sp) // not emitted if callee-saved reg is chosen. ... lw $2, 4($gp) ... jalr $25 // function call. lw $gp, 16($sp) // not emitted if $gp is not live after this instruction. ... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151402 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
120cfdf0e0
commit
648f00c2f0
@ -244,12 +244,12 @@ def : Pat<(add CPU64Regs:$hi, (MipsLo tconstpool:$lo)),
|
||||
def : Pat<(add CPU64Regs:$hi, (MipsLo tglobaltlsaddr:$lo)),
|
||||
(DADDiu CPU64Regs:$hi, tglobaltlsaddr:$lo)>;
|
||||
|
||||
def : WrapperPat<tglobaladdr, DADDiu, GP_64>;
|
||||
def : WrapperPat<tconstpool, DADDiu, GP_64>;
|
||||
def : WrapperPat<texternalsym, DADDiu, GP_64>;
|
||||
def : WrapperPat<tblockaddress, DADDiu, GP_64>;
|
||||
def : WrapperPat<tjumptable, DADDiu, GP_64>;
|
||||
def : WrapperPat<tglobaltlsaddr, DADDiu, GP_64>;
|
||||
def : WrapperPat<tglobaladdr, DADDiu, CPU64Regs>;
|
||||
def : WrapperPat<tconstpool, DADDiu, CPU64Regs>;
|
||||
def : WrapperPat<texternalsym, DADDiu, CPU64Regs>;
|
||||
def : WrapperPat<tblockaddress, DADDiu, CPU64Regs>;
|
||||
def : WrapperPat<tjumptable, DADDiu, CPU64Regs>;
|
||||
def : WrapperPat<tglobaltlsaddr, DADDiu, CPU64Regs>;
|
||||
|
||||
defm : BrcondPats<CPU64Regs, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
|
||||
ZERO_64>;
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/MC/MCStreamer.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
@ -116,6 +118,16 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Opc == Mips::SETGP01) {
|
||||
MCInstLowering.LowerSETGP01(MI, MCInsts);
|
||||
|
||||
for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin();
|
||||
I != MCInsts.end(); ++I)
|
||||
OutStreamer.EmitInstruction(*I);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OutStreamer.EmitInstruction(TmpInst0);
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,14 @@ namespace {
|
||||
} // end of anonymous namespace
|
||||
|
||||
bool Inserter::runOnMachineFunction(MachineFunction &F) {
|
||||
if (TM.getRelocationModel() != Reloc::PIC_)
|
||||
MipsFunctionInfo *MipsFI = F.getInfo<MipsFunctionInfo>();
|
||||
|
||||
if ((TM.getRelocationModel() != Reloc::PIC_) ||
|
||||
(!MipsFI->globalBaseRegFixed()))
|
||||
return false;
|
||||
|
||||
bool Changed = false;
|
||||
int FI = F.getInfo<MipsFunctionInfo>()->getGPFI();
|
||||
int FI = MipsFI->getGPFI();
|
||||
|
||||
for (MachineFunction::iterator MFI = F.begin(), MFE = F.end();
|
||||
MFI != MFE; ++MFI) {
|
||||
|
@ -67,6 +67,12 @@ bool MipsExpandPseudo::runOnMachineBasicBlock(MachineBasicBlock& MBB) {
|
||||
default:
|
||||
++I;
|
||||
continue;
|
||||
case Mips::SETGP2:
|
||||
// Convert "setgp2 $globalreg, $t9" to "addu $globalreg, $v0, $t9"
|
||||
BuildMI(MBB, I, I->getDebugLoc(), TII->get(Mips::ADDu),
|
||||
I->getOperand(0).getReg())
|
||||
.addReg(Mips::V0).addReg(I->getOperand(1).getReg());
|
||||
break;
|
||||
case Mips::BuildPairF64:
|
||||
ExpandBuildPairF64(MBB, I);
|
||||
break;
|
||||
|
@ -136,20 +136,16 @@ 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 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;
|
||||
unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP;
|
||||
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
|
||||
unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu;
|
||||
unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu;
|
||||
unsigned LUi = STI.isABI_N64() ? Mips::LUi64 : Mips::LUi;
|
||||
|
||||
// First, compute final stack size.
|
||||
unsigned RegSize = STI.isGP32bit() ? 4 : 8;
|
||||
@ -164,17 +160,19 @@ void MipsFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
MFI->setStackSize(StackSize);
|
||||
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOREORDER));
|
||||
|
||||
// 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, MBBI, dl, TII.get(Mips::CPLOAD))
|
||||
.addReg(RegInfo->getPICCallReg());
|
||||
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips::NOMACRO));
|
||||
|
||||
// Emit instructions that set the global base register if the target ABI is
|
||||
// O32.
|
||||
if (isPIC && MipsFI->globalBaseRegSet() && STI.isABI_O32()) {
|
||||
if (MipsFI->globalBaseRegFixed())
|
||||
BuildMI(MBB, llvm::prior(MBBI), dl, TII.get(Mips::CPLOAD))
|
||||
.addReg(RegInfo->getPICCallReg());
|
||||
else
|
||||
// See MipsInstrInfo.td for explanation.
|
||||
BuildMI(MBB, MBBI, dl, TII.get(Mips:: SETGP01), Mips::V0);
|
||||
}
|
||||
|
||||
// No need to allocate space on the stack.
|
||||
if (StackSize == 0 && !MFI->adjustsStack()) return;
|
||||
|
||||
@ -239,21 +237,6 @@ 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.
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "MipsRegisterInfo.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/Instructions.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
@ -64,6 +65,7 @@ public:
|
||||
return "MIPS DAG->DAG Pattern Instruction Selection";
|
||||
}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
private:
|
||||
// Include the pieces autogenerated from the target description.
|
||||
@ -96,6 +98,8 @@ private:
|
||||
return CurDAG->getTargetConstant(Imm, Node->getValueType(0));
|
||||
}
|
||||
|
||||
void InitGlobalBaseReg(MachineFunction &MF);
|
||||
|
||||
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
|
||||
char ConstraintCode,
|
||||
std::vector<SDValue> &OutOps);
|
||||
@ -103,11 +107,90 @@ private:
|
||||
|
||||
}
|
||||
|
||||
// Insert instructions to initialize the global base register in the
|
||||
// first MBB of the function. When the ABI is O32 and the relocation model is
|
||||
// PIC, the necessary instructions are emitted later to prevent optimization
|
||||
// passes from moving them.
|
||||
void MipsDAGToDAGISel::InitGlobalBaseReg(MachineFunction &MF) {
|
||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||
|
||||
if (!MipsFI->globalBaseRegSet())
|
||||
return;
|
||||
|
||||
MachineBasicBlock &MBB = MF.front();
|
||||
MachineBasicBlock::iterator I = MBB.begin();
|
||||
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
|
||||
unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg();
|
||||
bool FixGlobalBaseReg = MipsFI->globalBaseRegFixed();
|
||||
|
||||
if (FixGlobalBaseReg) // $gp is the global base register.
|
||||
V0 = V1 = GlobalBaseReg;
|
||||
else {
|
||||
const TargetRegisterClass *RC;
|
||||
RC = Subtarget.isABI_N64() ?
|
||||
Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass;
|
||||
|
||||
V0 = RegInfo.createVirtualRegister(RC);
|
||||
V1 = RegInfo.createVirtualRegister(RC);
|
||||
}
|
||||
|
||||
if (Subtarget.isABI_N64()) {
|
||||
MF.getRegInfo().addLiveIn(Mips::T9_64);
|
||||
|
||||
// lui $v0, %hi(%neg(%gp_rel(fname)))
|
||||
// daddu $v1, $v0, $t9
|
||||
// daddiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
|
||||
const GlobalValue *FName = MF.getFunction();
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::LUi64), V0)
|
||||
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::DADDu), V1).addReg(V0).addReg(Mips::T9_64);
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::DADDiu), GlobalBaseReg).addReg(V1)
|
||||
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
|
||||
} else if (MF.getTarget().getRelocationModel() == Reloc::Static) {
|
||||
// Set global register to __gnu_local_gp.
|
||||
//
|
||||
// lui $v0, %hi(__gnu_local_gp)
|
||||
// addiu $globalbasereg, $v0, %lo(__gnu_local_gp)
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
|
||||
.addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_HI);
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V0)
|
||||
.addExternalSymbol("__gnu_local_gp", MipsII::MO_ABS_LO);
|
||||
} else {
|
||||
MF.getRegInfo().addLiveIn(Mips::T9);
|
||||
|
||||
if (Subtarget.isABI_N32()) {
|
||||
// lui $v0, %hi(%neg(%gp_rel(fname)))
|
||||
// addu $v1, $v0, $t9
|
||||
// addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname)))
|
||||
const GlobalValue *FName = MF.getFunction();
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::LUi), V0)
|
||||
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_HI);
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::ADDu), V1).addReg(V0).addReg(Mips::T9);
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::ADDiu), GlobalBaseReg).addReg(V1)
|
||||
.addGlobalAddress(FName, 0, MipsII::MO_GPOFF_LO);
|
||||
} else if (!MipsFI->globalBaseRegFixed()) {
|
||||
assert(Subtarget.isABI_O32());
|
||||
|
||||
BuildMI(MBB, I, DL, TII.get(Mips::SETGP2), GlobalBaseReg)
|
||||
.addReg(Mips::T9);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool Ret = SelectionDAGISel::runOnMachineFunction(MF);
|
||||
|
||||
InitGlobalBaseReg(MF);
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - Output the instructions required to put the
|
||||
/// GOT address into a register.
|
||||
SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
|
||||
unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
|
||||
unsigned GlobalBaseReg = MF->getInfo<MipsFunctionInfo>()->getGlobalBaseReg();
|
||||
return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
|
||||
}
|
||||
|
||||
@ -116,7 +199,6 @@ SDNode *MipsDAGToDAGISel::getGlobalBaseReg() {
|
||||
bool MipsDAGToDAGISel::
|
||||
SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
|
||||
EVT ValTy = Addr.getValueType();
|
||||
unsigned GPReg = ValTy == MVT::i32 ? Mips::GP : Mips::GP_64;
|
||||
|
||||
// if Address is FI, get the TargetFrameIndex.
|
||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
|
||||
@ -127,8 +209,8 @@ SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
|
||||
|
||||
// on PIC code Load GA
|
||||
if (Addr.getOpcode() == MipsISD::Wrapper) {
|
||||
Base = CurDAG->getRegister(GPReg, ValTy);
|
||||
Offset = Addr.getOperand(0);
|
||||
Base = Addr.getOperand(0);
|
||||
Offset = Addr.getOperand(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,11 @@ static bool IsShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static SDValue GetGlobalReg(SelectionDAG &DAG, EVT Ty) {
|
||||
MipsFunctionInfo *FI = DAG.getMachineFunction().getInfo<MipsFunctionInfo>();
|
||||
return DAG.getRegister(FI->getGlobalBaseReg(), Ty);
|
||||
}
|
||||
|
||||
const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
switch (Opcode) {
|
||||
case MipsISD::JmpLink: return "MipsISD::JmpLink";
|
||||
@ -1496,7 +1501,7 @@ SDValue MipsTargetLowering::LowerGlobalAddress(SDValue Op,
|
||||
(HasGotOfst ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT_DISP) :
|
||||
(HasGotOfst ? MipsII::MO_GOT : MipsII::MO_GOT16);
|
||||
SDValue GA = DAG.getTargetGlobalAddress(GV, dl, ValTy, 0, GotFlag);
|
||||
GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GA);
|
||||
GA = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), GA);
|
||||
SDValue ResNode = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), GA,
|
||||
MachinePointerInfo(), false, false, false, 0);
|
||||
// On functions and global targets not internal linked only
|
||||
@ -1529,7 +1534,8 @@ SDValue MipsTargetLowering::LowerBlockAddress(SDValue Op,
|
||||
unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
|
||||
unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
|
||||
SDValue BAGOTOffset = DAG.getBlockAddress(BA, ValTy, true, GOTFlag);
|
||||
BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy, BAGOTOffset);
|
||||
BAGOTOffset = DAG.getNode(MipsISD::Wrapper, dl, ValTy,
|
||||
GetGlobalReg(DAG, ValTy), BAGOTOffset);
|
||||
SDValue BALOOffset = DAG.getBlockAddress(BA, ValTy, true, OFSTFlag);
|
||||
SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), BAGOTOffset,
|
||||
MachinePointerInfo(), false, false, false, 0);
|
||||
@ -1554,7 +1560,8 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
|
||||
bool LocalDynamic = GV->hasInternalLinkage();
|
||||
unsigned Flag = LocalDynamic ? MipsII::MO_TLSLDM :MipsII::MO_TLSGD;
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, Flag);
|
||||
SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA);
|
||||
SDValue Argument = DAG.getNode(MipsISD::Wrapper, dl, PtrVT,
|
||||
GetGlobalReg(DAG, PtrVT), TGA);
|
||||
unsigned PtrSize = PtrVT.getSizeInBits();
|
||||
IntegerType *PtrTy = Type::getIntNTy(*DAG.getContext(), PtrSize);
|
||||
|
||||
@ -1591,7 +1598,8 @@ LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
|
||||
// Initial Exec TLS Model
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0,
|
||||
MipsII::MO_GOTTPREL);
|
||||
TGA = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, TGA);
|
||||
TGA = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT),
|
||||
TGA);
|
||||
Offset = DAG.getLoad(PtrVT, dl,
|
||||
DAG.getEntryNode(), TGA, MachinePointerInfo(),
|
||||
false, false, false, 0);
|
||||
@ -1628,7 +1636,8 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG) const
|
||||
unsigned GOTFlag = IsN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
|
||||
unsigned OfstFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
|
||||
JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, GOTFlag);
|
||||
JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, JTI);
|
||||
JTI = DAG.getNode(MipsISD::Wrapper, dl, PtrVT, GetGlobalReg(DAG, PtrVT),
|
||||
JTI);
|
||||
HiPart = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), JTI,
|
||||
MachinePointerInfo(), false, false, false, 0);
|
||||
JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, OfstFlag);
|
||||
@ -1671,7 +1680,7 @@ LowerConstantPool(SDValue Op, SelectionDAG &DAG) const
|
||||
unsigned OFSTFlag = IsN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
|
||||
SDValue CP = DAG.getTargetConstantPool(C, ValTy, N->getAlignment(),
|
||||
N->getOffset(), GOTFlag);
|
||||
CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, CP);
|
||||
CP = DAG.getNode(MipsISD::Wrapper, dl, ValTy, GetGlobalReg(DAG, ValTy), CP);
|
||||
SDValue Load = DAG.getLoad(ValTy, dl, DAG.getEntryNode(), CP,
|
||||
MachinePointerInfo::getConstantPool(), false,
|
||||
false, false, 0);
|
||||
@ -2210,7 +2219,7 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee,
|
||||
|
||||
// If this is the first call, create a stack frame object that points to
|
||||
// a location to which .cprestore saves $gp.
|
||||
if (IsO32 && IsPIC && !MipsFI->getGPFI())
|
||||
if (IsO32 && IsPIC && MipsFI->globalBaseRegFixed() && !MipsFI->getGPFI())
|
||||
MipsFI->setGPFI(MFI->CreateFixedObject(4, 0, true));
|
||||
|
||||
// Get the frame index of the stack frame object that points to the location
|
||||
@ -2384,7 +2393,8 @@ MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee,
|
||||
if (IsPICCall) {
|
||||
if (GlobalOrExternal) {
|
||||
// Load callee address
|
||||
Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(), Callee);
|
||||
Callee = DAG.getNode(MipsISD::Wrapper, dl, getPointerTy(),
|
||||
GetGlobalReg(DAG, getPointerTy()), Callee);
|
||||
SDValue LoadValue = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(),
|
||||
Callee, MachinePointerInfo::getGOT(),
|
||||
false, false, false, 0);
|
||||
|
@ -454,30 +454,3 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - Return a virtual register initialized with the
|
||||
/// the global base register value. Output instructions required to
|
||||
/// initialize the register in the function entry block, if necessary.
|
||||
///
|
||||
unsigned MipsInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {
|
||||
MipsFunctionInfo *MipsFI = MF->getInfo<MipsFunctionInfo>();
|
||||
unsigned GlobalBaseReg = MipsFI->getGlobalBaseReg();
|
||||
if (GlobalBaseReg != 0)
|
||||
return GlobalBaseReg;
|
||||
|
||||
// Insert the set of GlobalBaseReg into the first MBB of the function
|
||||
MachineBasicBlock &FirstMBB = MF->front();
|
||||
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
||||
MachineRegisterInfo &RegInfo = MF->getRegInfo();
|
||||
const TargetInstrInfo *TII = MF->getTarget().getInstrInfo();
|
||||
unsigned GP = IsN64 ? Mips::GP_64 : Mips::GP;
|
||||
const TargetRegisterClass *RC
|
||||
= IsN64 ? Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass;
|
||||
|
||||
GlobalBaseReg = RegInfo.createVirtualRegister(RC);
|
||||
BuildMI(FirstMBB, MBBI, DebugLoc(), TII->get(TargetOpcode::COPY),
|
||||
GlobalBaseReg).addReg(GP);
|
||||
RegInfo.addLiveIn(GP);
|
||||
|
||||
MipsFI->setGlobalBaseReg(GlobalBaseReg);
|
||||
return GlobalBaseReg;
|
||||
}
|
||||
|
@ -103,12 +103,6 @@ public:
|
||||
/// Insert nop instruction when hazard condition is found
|
||||
virtual void insertNoop(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI) const;
|
||||
|
||||
/// getGlobalBaseReg - Return a virtual register initialized with the
|
||||
/// the global base register value. Output instructions required to
|
||||
/// initialize the register in the function entry block, if necessary.
|
||||
///
|
||||
unsigned getGlobalBaseReg(MachineFunction *MF) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
|
||||
// movn %got(d)($gp), %got(c)($gp), $4
|
||||
// This instruction is illegal since movn can take only register operands.
|
||||
|
||||
def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntUnaryOp>;
|
||||
def MipsWrapper : SDNode<"MipsISD::Wrapper", SDTIntBinOp>;
|
||||
|
||||
// Pointer to dynamically allocated stack area.
|
||||
def MipsDynAlloc : SDNode<"MipsISD::DynAlloc", SDT_MipsDynAlloc,
|
||||
@ -739,6 +739,22 @@ def ATMACRO : MipsPseudo<(outs), (ins), ".set\tat", []>;
|
||||
def CPLOAD : MipsPseudo<(outs), (ins CPURegs:$picreg), ".cpload\t$picreg", []>;
|
||||
def CPRESTORE : MipsPseudo<(outs), (ins i32imm:$loc), ".cprestore\t$loc", []>;
|
||||
|
||||
// For O32 ABI & PIC & non-fixed global base register, the following instruction
|
||||
// seqeunce is emitted to set the global base register:
|
||||
//
|
||||
// 0. lui $2, %hi(_gp_disp)
|
||||
// 1. addiu $2, $2, %lo(_gp_disp)
|
||||
// 2. addu $globalbasereg, $2, $t9
|
||||
//
|
||||
// SETGP01 is emitted during Prologue/Epilogue insertion and then converted to
|
||||
// instructions 0 and 1 in the sequence above during MC lowering.
|
||||
// SETGP2 is emitted just before register allocation and converted to
|
||||
// instruction 2 just prior to post-RA scheduling.
|
||||
|
||||
def SETGP01 : MipsPseudo<(outs CPURegs:$dst), (ins), "", []>;
|
||||
def SETGP2 : MipsPseudo<(outs CPURegs:$globalreg), (ins CPURegs:$picreg), "",
|
||||
[]>;
|
||||
|
||||
let usesCustomInserter = 1 in {
|
||||
defm ATOMIC_LOAD_ADD_I8 : Atomic2Ops32<atomic_load_add_8, "load_add_8">;
|
||||
defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32<atomic_load_add_16, "load_add_16">;
|
||||
@ -995,16 +1011,16 @@ def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)),
|
||||
(ADDiu CPURegs:$gp, tconstpool:$in)>;
|
||||
|
||||
// wrapper_pic
|
||||
class WrapperPat<SDNode node, Instruction ADDiuOp, Register GPReg>:
|
||||
Pat<(MipsWrapper node:$in),
|
||||
(ADDiuOp GPReg, node:$in)>;
|
||||
class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
|
||||
Pat<(MipsWrapper RC:$gp, node:$in),
|
||||
(ADDiuOp RC:$gp, node:$in)>;
|
||||
|
||||
def : WrapperPat<tglobaladdr, ADDiu, GP>;
|
||||
def : WrapperPat<tconstpool, ADDiu, GP>;
|
||||
def : WrapperPat<texternalsym, ADDiu, GP>;
|
||||
def : WrapperPat<tblockaddress, ADDiu, GP>;
|
||||
def : WrapperPat<tjumptable, ADDiu, GP>;
|
||||
def : WrapperPat<tglobaltlsaddr, ADDiu, GP>;
|
||||
def : WrapperPat<tglobaladdr, ADDiu, CPURegs>;
|
||||
def : WrapperPat<tconstpool, ADDiu, CPURegs>;
|
||||
def : WrapperPat<texternalsym, ADDiu, CPURegs>;
|
||||
def : WrapperPat<tblockaddress, ADDiu, CPURegs>;
|
||||
def : WrapperPat<tjumptable, ADDiu, CPURegs>;
|
||||
def : WrapperPat<tglobaltlsaddr, ADDiu, CPURegs>;
|
||||
|
||||
// Mips does not have "not", so we expand our way
|
||||
def : Pat<(not CPURegs:$in),
|
||||
|
@ -321,3 +321,29 @@ void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI,
|
||||
if (!TwoInstructions) MCInsts.push_back(Instr3);
|
||||
}
|
||||
|
||||
// Convert
|
||||
// "setgp01 $reg"
|
||||
// to
|
||||
// "lui $reg, %hi(_gp_disp)"
|
||||
// "addiu $reg, $reg, %lo(_gp_disp)"
|
||||
void MipsMCInstLower::LowerSETGP01(const MachineInstr *MI,
|
||||
SmallVector<MCInst, 4>& MCInsts) {
|
||||
const MachineOperand &MO = MI->getOperand(0);
|
||||
assert(MO.isReg());
|
||||
MCOperand RegOpnd = MCOperand::CreateReg(MO.getReg());
|
||||
StringRef SymName("_gp_disp");
|
||||
const MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName);
|
||||
const MCSymbolRefExpr *MCSym;
|
||||
|
||||
MCInsts.resize(2);
|
||||
|
||||
MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx);
|
||||
MCInsts[0].setOpcode(Mips::LUi);
|
||||
MCInsts[0].addOperand(RegOpnd);
|
||||
MCInsts[0].addOperand(MCOperand::CreateExpr(MCSym));
|
||||
MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx);
|
||||
MCInsts[1].setOpcode(Mips::ADDiu);
|
||||
MCInsts[1].addOperand(RegOpnd);
|
||||
MCInsts[1].addOperand(RegOpnd);
|
||||
MCInsts[1].addOperand(MCOperand::CreateExpr(MCSym));
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public:
|
||||
void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts);
|
||||
void LowerUnalignedLoadStore(const MachineInstr *MI,
|
||||
SmallVector<MCInst, 4>& MCInsts);
|
||||
void LowerSETGP01(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts);
|
||||
private:
|
||||
MCOperand LowerSymbolOperand(const MachineOperand &MO,
|
||||
MachineOperandType MOTy, unsigned Offset) const;
|
||||
|
@ -8,7 +8,43 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "MipsMachineFunction.h"
|
||||
#include "MipsInstrInfo.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MCTargetDesc/MipsBaseInfo.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool>
|
||||
FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
|
||||
cl::desc("Always use $gp as the global base register."));
|
||||
|
||||
bool MipsFunctionInfo::globalBaseRegFixed() const {
|
||||
return FixGlobalBaseReg;
|
||||
}
|
||||
|
||||
bool MipsFunctionInfo::globalBaseRegSet() const {
|
||||
return GlobalBaseReg;
|
||||
}
|
||||
|
||||
unsigned MipsFunctionInfo::getGlobalBaseReg() {
|
||||
// Return if it has already been initialized.
|
||||
if (GlobalBaseReg)
|
||||
return GlobalBaseReg;
|
||||
|
||||
const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>();
|
||||
|
||||
if (FixGlobalBaseReg) // $gp is the global base register.
|
||||
return GlobalBaseReg = ST.isABI_N64() ? Mips::GP_64 : Mips::GP;
|
||||
|
||||
const TargetRegisterClass *RC;
|
||||
RC = ST.isABI_N64() ?
|
||||
Mips::CPU64RegsRegisterClass : Mips::CPURegsRegisterClass;
|
||||
|
||||
return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC);
|
||||
}
|
||||
|
||||
void MipsFunctionInfo::anchor() { }
|
||||
|
@ -91,8 +91,9 @@ public:
|
||||
unsigned getSRetReturnReg() const { return SRetReturnReg; }
|
||||
void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
|
||||
|
||||
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
|
||||
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
|
||||
bool globalBaseRegFixed() const;
|
||||
bool globalBaseRegSet() const;
|
||||
unsigned getGlobalBaseReg();
|
||||
|
||||
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
|
||||
void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
|
||||
|
@ -101,12 +101,12 @@ BitVector MipsRegisterInfo::
|
||||
getReservedRegs(const MachineFunction &MF) const {
|
||||
static const unsigned ReservedCPURegs[] = {
|
||||
Mips::ZERO, Mips::AT, Mips::K0, Mips::K1,
|
||||
Mips::GP, Mips::SP, Mips::FP, Mips::RA
|
||||
Mips::SP, Mips::FP, Mips::RA
|
||||
};
|
||||
|
||||
static const unsigned ReservedCPU64Regs[] = {
|
||||
Mips::ZERO_64, Mips::AT_64, Mips::K0_64, Mips::K1_64,
|
||||
Mips::GP_64, Mips::SP_64, Mips::FP_64, Mips::RA_64
|
||||
Mips::SP_64, Mips::FP_64, Mips::RA_64
|
||||
};
|
||||
|
||||
BitVector Reserved(getNumRegs());
|
||||
@ -135,6 +135,12 @@ getReservedRegs(const MachineFunction &MF) const {
|
||||
Reserved.set(*Reg);
|
||||
}
|
||||
|
||||
// If GP is dedicated as a global base register, reserve it.
|
||||
if (MF.getInfo<MipsFunctionInfo>()->globalBaseRegFixed()) {
|
||||
Reserved.set(Mips::GP);
|
||||
Reserved.set(Mips::GP_64);
|
||||
}
|
||||
|
||||
return Reserved;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
|
||||
virtual bool addInstSelector();
|
||||
virtual bool addPreRegAlloc();
|
||||
virtual bool addPostRegAlloc();
|
||||
virtual bool addPreSched2();
|
||||
virtual bool addPreEmitPass();
|
||||
};
|
||||
} // namespace
|
||||
@ -140,7 +140,7 @@ bool MipsPassConfig::addPreRegAlloc() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MipsPassConfig::addPostRegAlloc() {
|
||||
bool MipsPassConfig::addPreSched2() {
|
||||
PM.add(createMipsExpandPseudoPass(getMipsTargetMachine()));
|
||||
return true;
|
||||
}
|
||||
|
22
test/CodeGen/Mips/global-pointer-reg.ll
Normal file
22
test/CodeGen/Mips/global-pointer-reg.ll
Normal file
@ -0,0 +1,22 @@
|
||||
; RUN: llc < %s -march=mipsel -mips-fix-global-base-reg=false | FileCheck %s
|
||||
|
||||
@g0 = external global i32
|
||||
@g1 = external global i32
|
||||
@g2 = external global i32
|
||||
|
||||
define void @foo1() nounwind {
|
||||
entry:
|
||||
; CHECK-NOT: .cpload
|
||||
; CHECK-NOT: .cprestore
|
||||
; CHECK: lui $[[R0:[0-9]+]], %hi(_gp_disp)
|
||||
; CHECK: addiu $[[R1:[0-9]+]], $[[R0]], %lo(_gp_disp)
|
||||
; CHECK: addu $[[GP:[0-9]+]], $[[R1]], $25
|
||||
; CHECK: lw ${{[0-9]+}}, %call16(foo2)($[[GP]])
|
||||
|
||||
tail call void @foo2(i32* @g0) nounwind
|
||||
tail call void @foo2(i32* @g1) nounwind
|
||||
tail call void @foo2(i32* @g2) nounwind
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @foo2(i32*)
|
@ -1,7 +1,8 @@
|
||||
; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=PIC
|
||||
; RUN: llc -march=mipsel -relocation-model=static < %s \
|
||||
; RUN: | FileCheck %s -check-prefix=STATIC
|
||||
|
||||
; RUN: llc -march=mipsel -relocation-model=static < %s \
|
||||
; RUN: -mips-fix-global-base-reg=false | FileCheck %s -check-prefix=STATICGP
|
||||
|
||||
@t1 = thread_local global i32 0, align 4
|
||||
|
||||
@ -39,6 +40,11 @@ entry:
|
||||
; PIC: jalr $25
|
||||
; PIC: lw $2, 0($2)
|
||||
|
||||
; STATICGP: lui $[[R0:[0-9]+]], %hi(__gnu_local_gp)
|
||||
; STATICGP: addiu $[[GP:[0-9]+]], $[[R0]], %lo(__gnu_local_gp)
|
||||
; STATICGP: lw ${{[0-9]+}}, %gottprel(t2)($[[GP]])
|
||||
; STATIC: lui $gp, %hi(__gnu_local_gp)
|
||||
; STATIC: addiu $gp, $gp, %lo(__gnu_local_gp)
|
||||
; STATIC: rdhwr $3, $29
|
||||
; STATIC: lw $[[R0:[0-9]+]], %gottprel(t2)($gp)
|
||||
; STATIC: addu $[[R1:[0-9]+]], $3, $[[R0]]
|
||||
|
Loading…
x
Reference in New Issue
Block a user