From 05a13f0bd0824ce83adaedc569ed6fa84c4c44f3 Mon Sep 17 00:00:00 2001 From: Sasa Stankovic Date: Wed, 1 Oct 2014 08:22:21 +0000 Subject: [PATCH] [mips] For indirect calls we don't need $gp to point to .got. Mips linker doesn't generate lazy binding stub for a function whose address is taken in the program. Differential Revision: http://reviews.llvm.org/D5067 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218744 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/Mips16ISelLowering.cpp | 6 ++++-- lib/Target/Mips/Mips16ISelLowering.h | 2 +- lib/Target/Mips/MipsISelLowering.cpp | 28 ++++++++++++++++++------- lib/Target/Mips/MipsISelLowering.h | 3 ++- lib/Target/Mips/MipsSEISelLowering.cpp | 6 ++++-- lib/Target/Mips/MipsSEISelLowering.h | 2 +- test/CodeGen/Mips/gpreg-lazy-binding.ll | 8 +++++++ test/CodeGen/Mips/prevent-hoisting.ll | 11 ++++++---- 8 files changed, 47 insertions(+), 19 deletions(-) diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index 68259f0a4ee..58f2d74f36a 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -424,7 +424,8 @@ void Mips16TargetLowering:: getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { SelectionDAG &DAG = CLI.DAG; MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *FuncInfo = MF.getInfo(); @@ -514,7 +515,8 @@ getOpndList(SmallVectorImpl &Ops, Ops.push_back(JumpTarget); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, CLI, Callee, Chain); + InternalLinkage, IsCallReloc, CLI, Callee, + Chain); } MachineBasicBlock *Mips16TargetLowering:: diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index 47ae652e2aa..4c21a919e71 100644 --- a/lib/Target/Mips/Mips16ISelLowering.h +++ b/lib/Target/Mips/Mips16ISelLowering.h @@ -47,7 +47,7 @@ namespace llvm { getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const override; MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr *MI, diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 95af1ff4b8c..50b8512bc18 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -2466,13 +2466,19 @@ void MipsTargetLowering:: getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { // Insert node "GP copy globalreg" before call to function. // // R_MIPS_CALL* operators (emitted when non-internal functions are called // in PIC mode) allow symbols to be resolved via lazy binding. // The lazy binding stub requires GP to point to the GOT. - if (IsPICCall && !InternalLinkage) { + // Note that we don't need GP to point to the GOT for indirect calls + // (when R_MIPS_CALL* is not used for the call) because Mips linker generates + // lazy binding stub for a function only when R_MIPS_CALL* are the only relocs + // used for the function (that is, Mips linker doesn't generate lazy binding + // stub for a function whose address is taken in the program). + if (IsPICCall && !InternalLinkage && IsCallReloc) { unsigned GPReg = Subtarget.isABI_N64() ? Mips::GP_64 : Mips::GP; EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); @@ -2667,7 +2673,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, bool IsPICCall = (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to // jalr $25 - bool GlobalOrExternal = false, InternalLinkage = false; + bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; SDValue CalleeLo; EVT Ty = Callee.getValueType(); @@ -2679,13 +2685,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, if (InternalLinkage) Callee = getAddrLocal(G, Ty, DAG, Subtarget.isABI_N32() || Subtarget.isABI_N64()); - else if (LargeGOT) + else if (LargeGOT) { Callee = getAddrGlobalLargeGOT(G, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Val)); - else + IsCallReloc = true; + } else { Callee = getAddrGlobal(G, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Val)); + IsCallReloc = true; + } } else Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, getPointerTy(), 0, MipsII::MO_NO_FLAG); @@ -2697,13 +2706,16 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), MipsII::MO_NO_FLAG); - else if (LargeGOT) + else if (LargeGOT) { Callee = getAddrGlobalLargeGOT(S, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, FuncInfo->callPtrInfo(Sym)); - else // N64 || PIC + IsCallReloc = true; + } else { // N64 || PIC Callee = getAddrGlobal(S, Ty, DAG, MipsII::MO_GOT_CALL, Chain, FuncInfo->callPtrInfo(Sym)); + IsCallReloc = true; + } GlobalOrExternal = true; } @@ -2712,7 +2724,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, InternalLinkage, - CLI, Callee, Chain); + IsCallReloc, CLI, Callee, Chain); if (IsTailCall) return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 24bc47f458f..3cb7f69d8fb 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -336,7 +336,8 @@ namespace llvm { getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const; + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const; /// ByValArgInfo - Byval argument information. struct ByValArgInfo { diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index 1bf21cbc1fd..9e7c63cdeb7 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -1187,10 +1187,12 @@ void MipsSETargetLowering:: getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const { + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, + SDValue Chain) const { Ops.push_back(Callee); MipsTargetLowering::getOpndList(Ops, RegsToPass, IsPICCall, GlobalOrExternal, - InternalLinkage, CLI, Callee, Chain); + InternalLinkage, IsCallReloc, CLI, Callee, + Chain); } SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 1cf6eebf65f..4ca94addf2c 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -59,7 +59,7 @@ namespace llvm { getOpndList(SmallVectorImpl &Ops, std::deque< std::pair > &RegsToPass, bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage, - CallLoweringInfo &CLI, SDValue Callee, + bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const override; SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const; diff --git a/test/CodeGen/Mips/gpreg-lazy-binding.ll b/test/CodeGen/Mips/gpreg-lazy-binding.ll index 88e596b3bb0..3a636d82533 100644 --- a/test/CodeGen/Mips/gpreg-lazy-binding.ll +++ b/test/CodeGen/Mips/gpreg-lazy-binding.ll @@ -25,3 +25,11 @@ entry: ret void } +define void @no_lazy(void (i32)* %pf) { + +; CHECK-LABEL: no_lazy +; CHECK-NOT: gp_disp + + tail call void %pf(i32 1) + ret void +} diff --git a/test/CodeGen/Mips/prevent-hoisting.ll b/test/CodeGen/Mips/prevent-hoisting.ll index da665c21090..210fe3b0f6d 100644 --- a/test/CodeGen/Mips/prevent-hoisting.ll +++ b/test/CodeGen/Mips/prevent-hoisting.ll @@ -10,16 +10,19 @@ ; CHECK-LABEL: readLumaCoeff8x8_CABAC -; The check for "addiu" instruction is added so that we can match the correct "b" instruction. +; The check for first "addiu" instruction is added so that we can match the correct "b" instruction. ; CHECK: addiu ${{[0-9]+}}, $zero, -1 ; CHECK: b $[[BB0:BB[0-9_]+]] +; CHECK-NEXT: addiu ${{[0-9]+}}, $zero, 0 -; Check that sll instruction that writes to $1 starts basic block. -; CHECK: {{BB[0-9_#]+}}: +; Check that at the start of a fallthrough block there is a instruction that writes to $1. +; CHECK-NEXT: {{BB[0-9_#]+}}: +; CHECK-NEXT: lw $[[R1:[0-9]+]], %got(assignSE2partition)($[[R2:[0-9]+]]) ; CHECK-NEXT: sll $1, $[[R0:[0-9]+]], 4 -; Check that identical sll instruction starts another basic block. +; Check that identical instructions are at the start of a target block. ; CHECK: [[BB0]]: +; CHECK-NEXT: lw $[[R1]], %got(assignSE2partition)($[[R2]]) ; CHECK-NEXT: sll $1, $[[R0]], 4 -- 2.34.1