diff options
-rw-r--r-- | include/llvm/Attributes.h | 5 | ||||
-rw-r--r-- | lib/AsmParser/LLLexer.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLParser.cpp | 1 | ||||
-rw-r--r-- | lib/AsmParser/LLToken.h | 1 | ||||
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 20 | ||||
-rw-r--r-- | lib/VMCore/Attributes.cpp | 2 | ||||
-rw-r--r-- | test/CodeGen/X86/non-lazy-bind.ll | 27 | ||||
-rw-r--r-- | test/Feature/paramattrs.ll | 2 | ||||
-rw-r--r-- | utils/llvm.grm | 2 |
9 files changed, 60 insertions, 1 deletions
diff --git a/include/llvm/Attributes.h b/include/llvm/Attributes.h index 8b69d6ecc1..233eab8bf1 100644 --- a/include/llvm/Attributes.h +++ b/include/llvm/Attributes.h @@ -69,6 +69,9 @@ const Attributes Hotpatch = 1<<29; ///< Function should have special ///'hotpatch' sequence in prologue const Attributes UWTable = 1<<30; ///< Function must be in a unwind ///table +const Attributes NonLazyBind = 1U<<31; ///< Function is called early and/or + /// often, so lazy binding isn't + /// worthwhile. /// Note that uwtable is about the ABI or the user mandating an entry in the /// unwind table. The nounwind attribute is about an exception passing by the @@ -90,7 +93,7 @@ const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture; const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly | NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq | NoRedZone | NoImplicitFloat | Naked | InlineHint | StackAlignment | - Hotpatch | UWTable; + Hotpatch | UWTable | NonLazyBind; /// @brief Parameter attributes that do not apply to vararg call arguments. const Attributes VarArgsIncompatible = StructRet; diff --git a/lib/AsmParser/LLLexer.cpp b/lib/AsmParser/LLLexer.cpp index a363a653b2..a298c6af09 100644 --- a/lib/AsmParser/LLLexer.cpp +++ b/lib/AsmParser/LLLexer.cpp @@ -572,6 +572,7 @@ lltok::Kind LLLexer::LexIdentifier() { KEYWORD(noimplicitfloat); KEYWORD(naked); KEYWORD(hotpatch); + KEYWORD(nonlazybind); KEYWORD(type); KEYWORD(opaque); diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 81e0747266..0260a7f639 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -985,6 +985,7 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) { case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break; case lltok::kw_naked: Attrs |= Attribute::Naked; break; case lltok::kw_hotpatch: Attrs |= Attribute::Hotpatch; break; + case lltok::kw_nonlazybind: Attrs |= Attribute::NonLazyBind; break; case lltok::kw_alignstack: { unsigned Alignment; diff --git a/lib/AsmParser/LLToken.h b/lib/AsmParser/LLToken.h index 02f97a3d3d..3b193dc8dc 100644 --- a/lib/AsmParser/LLToken.h +++ b/lib/AsmParser/LLToken.h @@ -99,6 +99,7 @@ namespace lltok { kw_noimplicitfloat, kw_naked, kw_hotpatch, + kw_nonlazybind, kw_type, kw_opaque, diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 294a6a74cc..1cdf2b6aa6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2271,6 +2271,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, const GlobalValue *GV = G->getGlobal(); if (!GV->hasDLLImportLinkage()) { unsigned char OpFlags = 0; + bool ExtraLoad = false; + unsigned WrapperKind = ISD::DELETED_NODE; // On ELF targets, in both X86-64 and X86-32 mode, direct calls to // external symbols most go through the PLT in PIC mode. If the symbol @@ -2288,10 +2290,28 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee, // unless we're building with the leopard linker or later, which // automatically synthesizes these stubs. OpFlags = X86II::MO_DARWIN_STUB; + } else if (Subtarget->isPICStyleRIPRel() && + isa<Function>(GV) && + cast<Function>(GV)->hasFnAttr(Attribute::NonLazyBind)) { + // If the function is marked as non-lazy, generate an indirect call + // which loads from the GOT directly. This avoids runtime overhead + // at the cost of eager binding (and one extra byte of encoding). + OpFlags = X86II::MO_GOTPCREL; + WrapperKind = X86ISD::WrapperRIP; + ExtraLoad = true; } Callee = DAG.getTargetGlobalAddress(GV, dl, getPointerTy(), G->getOffset(), OpFlags); + + // Add a wrapper if needed. + if (WrapperKind != ISD::DELETED_NODE) + Callee = DAG.getNode(X86ISD::WrapperRIP, dl, getPointerTy(), Callee); + // Add extra indirection if needed. + if (ExtraLoad) + Callee = DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), Callee, + MachinePointerInfo::getGOT(), + false, false, 0); } } else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { unsigned char OpFlags = 0; diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index ee257dbde5..bf6efa1645 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -74,6 +74,8 @@ std::string Attribute::getAsString(Attributes Attrs) { Result += "naked "; if (Attrs & Attribute::Hotpatch) Result += "hotpatch "; + if (Attrs & Attribute::NonLazyBind) + Result += "nonlazybind "; if (Attrs & Attribute::StackAlignment) { Result += "alignstack("; Result += utostr(Attribute::getStackAlignmentFromAttrs(Attrs)); diff --git a/test/CodeGen/X86/non-lazy-bind.ll b/test/CodeGen/X86/non-lazy-bind.ll new file mode 100644 index 0000000000..f72965877d --- /dev/null +++ b/test/CodeGen/X86/non-lazy-bind.ll @@ -0,0 +1,27 @@ +; RUN: llc -mtriple=x86_64-apple-darwin < %s | FileCheck %s + +declare void @lazy() nonlazybind +declare void @not() + +; CHECK: foo: +; CHECK: callq _not +; CHECK: callq *_lazy@GOTPCREL(%rip) +define void @foo() nounwind { + call void @not() + call void @lazy() + ret void +} + +; CHECK: tail_call_regular: +; CHECK: jmp _not +define void @tail_call_regular() nounwind { + tail call void @not() + ret void +} + +; CHECK: tail_call_eager: +; CHECK: jmpq *_lazy@GOTPCREL(%rip) +define void @tail_call_eager() nounwind { + tail call void @lazy() + ret void +} diff --git a/test/Feature/paramattrs.ll b/test/Feature/paramattrs.ll index 3bee6177e0..d686257e79 100644 --- a/test/Feature/paramattrs.ll +++ b/test/Feature/paramattrs.ll @@ -20,3 +20,5 @@ define i32 @main(i32 inreg %argc, i8 ** inreg %argv) nounwind { %retVal = sext i16 %two to i32 ret i32 %retVal } + +declare void @function_to_resolve_eagerly() nonlazybind diff --git a/utils/llvm.grm b/utils/llvm.grm index 9d6bdf79f5..3f33702d2a 100644 --- a/utils/llvm.grm +++ b/utils/llvm.grm @@ -172,6 +172,8 @@ FuncAttr ::= noreturn | optsize | ssp | sspreq + | hotpatch + | nonlazybind ; OptFuncAttrs ::= + _ | OptFuncAttrs FuncAttr ; |