// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
bool IsPICCall = (IsN64 || IsPIC); // true if calls are translated to jalr $25
- bool GlobalOrExternal = false;
+ bool GlobalOrExternal = false, InternalLinkage = false;
SDValue CalleeLo;
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
if (IsPICCall) {
- if (G->getGlobal()->hasInternalLinkage())
+ InternalLinkage = G->getGlobal()->hasInternalLinkage();
+
+ if (InternalLinkage)
Callee = getAddrLocal(Callee, DAG, HasMips64);
else if (LargeGOT)
Callee = getAddrGlobalLargeGOT(Callee, DAG, MipsII::MO_CALL_HI16,
}
// Insert node "GP copy globalreg" before call to function.
- // Lazy-binding stubs require GP to point to the GOT.
- if (IsPICCall) {
+ //
+ // 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) {
unsigned GPReg = IsN64 ? Mips::GP_64 : Mips::GP;
EVT Ty = IsN64 ? MVT::i64 : MVT::i32;
RegsToPass.push_back(std::make_pair(GPReg, GetGlobalReg(DAG, Ty)));
--- /dev/null
+; RUN: llc -march=mipsel -disable-mips-delay-filler < %s | FileCheck %s
+
+@g = external global i32
+
+; CHECK: addu $gp
+; CHECK: jalr $25
+; CHECK: nop
+; CHECK-NOT: addu $gp
+; CHECK: jalr $25
+
+define void @f0() nounwind {
+entry:
+ tail call void @externalFunc() nounwind
+ tail call fastcc void @internalFunc()
+ ret void
+}
+
+declare void @externalFunc()
+
+define internal fastcc void @internalFunc() nounwind noinline {
+entry:
+ %0 = load i32* @g, align 4
+ %inc = add nsw i32 %0, 1
+ store i32 %inc, i32* @g, align 4
+ ret void
+}
+