Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2193,11 +2193,14 @@ if (GlobalAddressSDNode *S = dyn_cast(Callee)) { const GlobalValue *GV = S->getGlobal(); - unsigned OpFlags = RISCVII::MO_CALL; - if (!getTargetMachine().shouldAssumeDSOLocal(*GV->getParent(), GV)) - OpFlags = RISCVII::MO_PLT; + unsigned OpFlags = + Subtarget.classifyGlobalFunctionReference(GV, getTargetMachine()); + + if (OpFlags == RISCVII::MO_GOT_HI) + Callee = getAddr(S, DAG, 0); + else + Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags); - Callee = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, OpFlags); } else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) { unsigned OpFlags = RISCVII::MO_CALL; Index: llvm/lib/Target/RISCV/RISCVSubtarget.h =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.h +++ llvm/lib/Target/RISCV/RISCVSubtarget.h @@ -62,6 +62,11 @@ // definition of this function is auto-generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + /// Return how the function given by GV should be invoked: + /// via PLT, by taking its address from GOT, or with a direct call. + unsigned char classifyGlobalFunctionReference(const GlobalValue *GV, + const TargetMachine &TM) const; + const RISCVFrameLowering *getFrameLowering() const override { return &FrameLowering; } Index: llvm/lib/Target/RISCV/RISCVSubtarget.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVSubtarget.cpp +++ llvm/lib/Target/RISCV/RISCVSubtarget.cpp @@ -48,3 +48,14 @@ : RISCVGenSubtargetInfo(TT, CPU, FS), FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)), InstrInfo(), RegInfo(getHwMode()), TLInfo(TM, *this) {} + +unsigned char RISCVSubtarget::classifyGlobalFunctionReference( + const GlobalValue *GV, const TargetMachine &TM) const { + auto *F = dyn_cast(GV); + if (F && !TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) { + if (F->hasFnAttribute(Attribute::NonLazyBind)) + return RISCVII::MO_GOT_HI; + return RISCVII::MO_PLT; + } + return RISCVII::MO_CALL; +} Index: llvm/test/CodeGen/RISCV/no-plt.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/no-plt.ll @@ -0,0 +1,23 @@ +; RUN: llc -mtriple=riscv64-linux-gnu --relocation-model=pic < %s | FileCheck %s + +declare void @global() nonlazybind + +define void @no_PLT_call() nounwind { + ;CHECK-LABEL: no_PLT_call: + + ;CHECK: # %bb.0: + + ;CHECK-NEXT: addi sp, sp, -16 + ;CHECK-NEXT: sd ra, 8(sp) + + ;CHECK-NEXT: .LBB0_1: # Label of block must be emitted + + ;CHECK-NEXT: auipc a0, %got_pcrel_hi(global) + ;CHECK-NEXT: ld a0, %pcrel_lo(.LBB0_1)(a0) + ;CHECK-NEXT: jalr a0 + + ;CHECK-NEXT: ld ra, 8(sp) + + call void @global() + ret void +}