aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/Mips/MipsISelDAGToDAG.cpp
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 /lib/Target/Mips/MipsISelDAGToDAG.cpp
parent120cfdf0e0a53f858970874476a21cffb8069847 (diff)
downloadexternal_llvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.zip
external_llvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.tar.gz
external_llvm-648f00c2f0eb29c0ae2a333fa0bfa55970059f08.tar.bz2
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
Diffstat (limited to 'lib/Target/Mips/MipsISelDAGToDAG.cpp')
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp90
1 files changed, 86 insertions, 4 deletions
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 73533eb..281399e 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;
}