summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira Hatanaka <ahatanaka@mips.com>2012-02-24 22:34:47 +0000
committerAkira Hatanaka <ahatanaka@mips.com>2012-02-24 22:34:47 +0000
commit648f00c2f0eb29c0ae2a333fa0bfa55970059f08 (patch)
treea9f96e31e7b7c14dad235bdb6675c9334128696a
parent120cfdf0e0a53f858970874476a21cffb8069847 (diff)
downloadllvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.tar.gz
llvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.tar.bz2
llvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.tar.xz
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
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td12
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp12
-rw-r--r--lib/Target/Mips/MipsEmitGPRestore.cpp7
-rw-r--r--lib/Target/Mips/MipsExpandPseudo.cpp6
-rw-r--r--lib/Target/Mips/MipsFrameLowering.cpp39
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp90
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp26
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp27
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h6
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td38
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp26
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h1
-rw-r--r--lib/Target/Mips/MipsMachineFunction.cpp36
-rw-r--r--lib/Target/Mips/MipsMachineFunction.h5
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp10
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp4
-rw-r--r--test/CodeGen/Mips/global-pointer-reg.ll22
-rw-r--r--test/CodeGen/Mips/tls.ll8
18 files changed, 276 insertions, 99 deletions
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 1a577569df..6484fdc394 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -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>;
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 9ddc08a9e0..f83cb9a33a 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -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);
}
diff --git a/lib/Target/Mips/MipsEmitGPRestore.cpp b/lib/Target/Mips/MipsEmitGPRestore.cpp
index 41d75dbf02..df0e59198b 100644
--- a/lib/Target/Mips/MipsEmitGPRestore.cpp
+++ b/lib/Target/Mips/MipsEmitGPRestore.cpp
@@ -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) {
diff --git a/lib/Target/Mips/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp
index d3b0fae8b1..b85a3b2c27 100644
--- a/lib/Target/Mips/MipsExpandPseudo.cpp
+++ b/lib/Target/Mips/MipsExpandPseudo.cpp
@@ -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;
diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp
index fd12b9c09f..b06d27fe5e 100644
--- a/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/lib/Target/Mips/MipsFrameLowering.cpp
@@ -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.
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 73533eb0ed..281399e84e 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -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;
}
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index a93e0ac5a6..968a78b1f2 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -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);
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 4dbd29e7d5..573b31a51b 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -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;
-}
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 70cc2cfb1a..8a83685eb5 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -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;
};
}
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 39007c6c71..ac1261068c 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -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)>;
-
-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>;
+class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>:
+ Pat<(MipsWrapper RC:$gp, node:$in),
+ (ADDiuOp RC:$gp, node:$in)>;
+
+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),
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index 6143eaad26..37662e9f2b 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -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));
+}
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index 83ea2ced14..4e3339c313 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -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;
diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp
index 229dd02118..ebbafc3fee 100644
--- a/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/lib/Target/Mips/MipsMachineFunction.cpp
@@ -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() { }
diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h
index 7f5130be4d..a6e40283f7 100644
--- a/lib/Target/Mips/MipsMachineFunction.h
+++ b/lib/Target/Mips/MipsMachineFunction.h
@@ -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; }
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index f55ef4e581..aa921bc8d1 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -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;
}
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index ff766faad6..8806aafe21 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -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;
}
diff --git a/test/CodeGen/Mips/global-pointer-reg.ll b/test/CodeGen/Mips/global-pointer-reg.ll
new file mode 100644
index 0000000000..174d1f9cbe
--- /dev/null
+++ b/test/CodeGen/Mips/global-pointer-reg.ll
@@ -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*)
diff --git a/test/CodeGen/Mips/tls.ll b/test/CodeGen/Mips/tls.ll
index 8f97793c18..a3c4768bb4 100644
--- a/test/CodeGen/Mips/tls.ll
+++ b/test/CodeGen/Mips/tls.ll
@@ -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]]