Index: lib/Target/X86/X86ISelLowering.h =================================================================== --- lib/Target/X86/X86ISelLowering.h +++ lib/Target/X86/X86ISelLowering.h @@ -1201,7 +1201,8 @@ SDValue LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; - unsigned getGlobalWrapperKind(const GlobalValue *GV = nullptr) const; + unsigned getGlobalWrapperKind(const GlobalValue *GV = nullptr, + const unsigned char OpFlags = 0) const; SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(const GlobalValue *GV, const SDLoc &dl, Index: lib/Target/X86/X86ISelLowering.cpp =================================================================== --- lib/Target/X86/X86ISelLowering.cpp +++ lib/Target/X86/X86ISelLowering.cpp @@ -15497,7 +15497,8 @@ } // Returns the appropriate wrapper opcode for a global reference. -unsigned X86TargetLowering::getGlobalWrapperKind(const GlobalValue *GV) const { +unsigned X86TargetLowering::getGlobalWrapperKind( + const GlobalValue *GV, const unsigned char OpFlags) const { // References to absolute symbols are never PC-relative. if (GV && GV->isAbsoluteSymbolRef()) return X86ISD::Wrapper; @@ -15507,6 +15508,16 @@ (M == CodeModel::Small || M == CodeModel::Kernel)) return X86ISD::WrapperRIP; + // GOTPCREL references are possible without PIC when using "nonlazybind" + // attribute. Always use RIP when this is found. + if (OpFlags == X86II::MO_GOTPCREL) { + const Function *F = dyn_cast_or_null(GV); + assert(((F && F->hasFnAttribute(Attribute::NonLazyBind)) || + (!F && GV->getParent()->getRtLibUseGOT())) && + Subtarget.is64Bit()); + return X86ISD::WrapperRIP; + } + return X86ISD::Wrapper; } @@ -15630,7 +15641,7 @@ Result = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, OpFlags); } - Result = DAG.getNode(getGlobalWrapperKind(GV), dl, PtrVT, Result); + Result = DAG.getNode(getGlobalWrapperKind(GV, OpFlags), dl, PtrVT, Result); // With PIC, the address is actually $g + Offset. if (isGlobalRelativeToPICBase(OpFlags)) { Index: test/CodeGen/X86/no-plt.ll =================================================================== --- test/CodeGen/X86/no-plt.ll +++ test/CodeGen/X86/no-plt.ll @@ -3,6 +3,13 @@ ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux-gnu \ ; RUN: | FileCheck -check-prefix=X64 --check-prefix=STATIC %s +define dso_local i32 @fp_weakfunc() local_unnamed_addr #0 { +entry: +; X64: weakfunc@GOTPCREL(%rip) + ret i32 select (i1 icmp ne (i32 ()* @weakfunc, i32 ()* null), i32 1, i32 0) +} +declare extern_weak i32 @weakfunc() nonlazybind + define void @memset_call(i8* nocapture %a, i8 %c, i32 %n) { ; X64: callq *memset@GOTPCREL(%rip) call void @llvm.memset.p0i8.i32(i8* %a, i8 %c, i32 %n, i1 false)