diff options
author | Akira Hatanaka <ahatanaka@mips.com> | 2012-02-24 22:34:47 +0000 |
---|---|---|
committer | Akira Hatanaka <ahatanaka@mips.com> | 2012-02-24 22:34:47 +0000 |
commit | 648f00c2f0eb29c0ae2a333fa0bfa55970059f08 (patch) | |
tree | a9f96e31e7b7c14dad235bdb6675c9334128696a /lib/Target/Mips/MipsISelDAGToDAG.cpp | |
parent | 120cfdf0e0a53f858970874476a21cffb8069847 (diff) | |
download | external_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.cpp | 90 |
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; } |