diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index 1a577569dfd..6484fdc3943 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; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; defm : BrcondPats; diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 9ddc08a9e09..f83cb9a33a6 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::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 41d75dbf024..df0e59198b7 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(); + + if ((TM.getRelocationModel() != Reloc::PIC_) || + (!MipsFI->globalBaseRegFixed())) return false; bool Changed = false; - int FI = F.getInfo()->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 d3b0fae8b16..b85a3b2c27e 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 fd12b9c09f7..b06d27fe5e6 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(); const MipsRegisterInfo *RegInfo = static_cast(MF.getTarget().getRegisterInfo()); - MachineRegisterInfo& MRI = MF.getRegInfo(); const MipsInstrInfo &TII = *static_cast(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 73533eb0edf..281399e84ee 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 &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(); + + 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()->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(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 a93e0ac5a68..968a78b1f2a 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(); + 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 4dbd29e7d5e..573b31a51b2 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -454,30 +454,3 @@ ReverseBranchCondition(SmallVectorImpl &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(); - 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 70cc2cfb1ae..8a83685eb58 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 39007c6c715..ac1261068c4 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; defm ATOMIC_LOAD_ADD_I16 : Atomic2Ops32; @@ -995,16 +1011,16 @@ def : Pat<(add CPURegs:$gp, (MipsGPRel tconstpool:$in)), (ADDiu CPURegs:$gp, tconstpool:$in)>; // wrapper_pic -class WrapperPat: - Pat<(MipsWrapper node:$in), - (ADDiuOp GPReg, node:$in)>; +class WrapperPat: + Pat<(MipsWrapper RC:$gp, node:$in), + (ADDiuOp RC:$gp, node:$in)>; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; -def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; +def : WrapperPat; // 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 6143eaad26f..37662e9f2bc 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& 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 83ea2ced14e..4e3339c313d 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -39,6 +39,7 @@ public: void LowerCPRESTORE(const MachineInstr *MI, SmallVector& MCInsts); void LowerUnalignedLoadStore(const MachineInstr *MI, SmallVector& MCInsts); + void LowerSETGP01(const MachineInstr *MI, SmallVector& 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 229dd02118b..ebbafc3fee1 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 +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(); + + 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 7f5130be4dd..a6e40283f74 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 f55ef4e581f..aa921bc8d1e 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()->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 ff766faad68..8806aafe218 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 00000000000..174d1f9cbe9 --- /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 8f97793c18a..a3c4768bb4b 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]]