Add an option to use a virtual register as the global base register instead of
authorAkira Hatanaka <ahatanaka@mips.com>
Fri, 24 Feb 2012 22:34:47 +0000 (22:34 +0000)
committerAkira Hatanaka <ahatanaka@mips.com>
Fri, 24 Feb 2012 22:34:47 +0000 (22:34 +0000)
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

18 files changed:
lib/Target/Mips/Mips64InstrInfo.td
lib/Target/Mips/MipsAsmPrinter.cpp
lib/Target/Mips/MipsEmitGPRestore.cpp
lib/Target/Mips/MipsExpandPseudo.cpp
lib/Target/Mips/MipsFrameLowering.cpp
lib/Target/Mips/MipsISelDAGToDAG.cpp
lib/Target/Mips/MipsISelLowering.cpp
lib/Target/Mips/MipsInstrInfo.cpp
lib/Target/Mips/MipsInstrInfo.h
lib/Target/Mips/MipsInstrInfo.td
lib/Target/Mips/MipsMCInstLower.cpp
lib/Target/Mips/MipsMCInstLower.h
lib/Target/Mips/MipsMachineFunction.cpp
lib/Target/Mips/MipsMachineFunction.h
lib/Target/Mips/MipsRegisterInfo.cpp
lib/Target/Mips/MipsTargetMachine.cpp
test/CodeGen/Mips/global-pointer-reg.ll [new file with mode: 0644]
test/CodeGen/Mips/tls.ll

index 1a577569dfda1a8d3fbfe87b49d91e4a7ae88cd4..6484fdc394336512efcf341a6f9a917f1f4d4c58 100644 (file)
@@ -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>;
index 9ddc08a9e093712cec045a52e9006bb50791ae52..f83cb9a33a6eb09b6a75949d0f38c98ddf4d9623 100644 (file)
@@ -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);
 }
 
index 41d75dbf024c32da82633be0ab2397ffb1e2d846..df0e59198b782f75a3467280f33012771438a245 100644 (file)
@@ -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) {
index d3b0fae8b16467ca84f3319d422068378d24efc8..b85a3b2c27e144931eac89ca9063f428a0ff0f63 100644 (file)
@@ -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;
index fd12b9c09f70dc6c178bf86539d608b356ce8f8f..b06d27fe5e676e71adbb11afaae6b18ab2b3bdb1 100644 (file)
@@ -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.    
index 73533eb0edfcb70330ef9b001c40645ae3abdcd2..281399e84eeed50c8c4a7fb3c0bca0302e2702ab 100644 (file)
@@ -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;
   }
 
index a93e0ac5a682e16f9ecd8a7e6a9c9312f2f066c8..968a78b1f2ad1c3d1191015aa303b46482398b84 100644 (file)
@@ -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);
index 4dbd29e7d5ed4653785968f9b8fe8a091205aa76..573b31a51b2cfacbd66db94b756718707ea14202 100644 (file)
@@ -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;
-}
index 70cc2cfb1ae6ded5b322be086e234dc480544601..8a83685eb58372848dcce3e7aacaef5fcfc4bd88 100644 (file)
@@ -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;
 };
 
 }
index 39007c6c715fe8aec7263ed37cdefbdde88f02c5..ac1261068c40e8a812b3f8af9f2d2d0a03944b49 100644 (file)
@@ -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),
index 6143eaad26f0faf99f89aba4b5466c18bb0d33aa..37662e9f2bc5931e83b9f1057177d7e69b463a87 100644 (file)
@@ -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));
+}
index 83ea2ced14e9a0082f485ab5fcf96cd507697476..4e3339c313dd7372e85526cef05fa9cee003fe4a 100644 (file)
@@ -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;
index 229dd02118b70bd02e08e3ffb1874c28b062784c..ebbafc3fee14a766eba6119be16f3d154480d873 100644 (file)
@@ -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() { }
index 7f5130be4dd92ebc233a1133f9d299018ef7344c..a6e40283f747e8775f76ae5f15efa346b0c86cd7 100644 (file)
@@ -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; }
index f55ef4e581f1d274dba2181875272384ab182da5..aa921bc8d1e116c0c4f57bb64e200f9fc6cb1ab9 100644 (file)
@@ -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;
 }
 
index ff766faad6806973d7ad038c47a7d88eabb66e97..8806aafe21829b402feab7d274d0d9c1bb003629 100644 (file)
@@ -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 (file)
index 0000000..174d1f9
--- /dev/null
@@ -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*)
index 8f97793c18a9feff726e692379e90131df3f96b3..a3c4768bb4b52368b2bb7d6c34ed0b999abb5610 100644 (file)
@@ -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]]