diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 955a4fca6f86f..6ac768b51395c 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -48,9 +48,11 @@ class AssemblyAnnotationWriter; class Constant; struct DenormalMode; class DISubprogram; +enum LibFunc : unsigned; class LLVMContext; class Module; class raw_ostream; +class TargetLibraryInfoImpl; class Type; class User; class BranchProbabilityInfo; @@ -120,6 +122,15 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject, void setIsNewDbgInfoFormat(bool NewVal); private: + friend class TargetLibraryInfoImpl; + + static constexpr LibFunc UnknownLibFunc = LibFunc(-1); + + /// Cache for TLI::getLibFunc() result without prototype validation. + /// UnknownLibFunc if uninitialized. NotLibFunc if definitely not lib func. + /// Otherwise may be libfunc if prototype validation passes. + mutable LibFunc LibFuncCache = UnknownLibFunc; + void CheckLazyArguments() const { if (hasLazyArguments()) BuildLazyArguments(); @@ -239,12 +250,11 @@ class LLVM_EXTERNAL_VISIBILITY Function : public GlobalObject, static Intrinsic::ID lookupIntrinsicID(StringRef Name); - /// Recalculate the ID for this function if it is an Intrinsic defined - /// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic - /// if the name of this function does not match an intrinsic in that header. + /// Update internal caches that depend on the function name (such as the + /// intrinsic ID and libcall cache). /// Note, this method does not need to be called directly, as it is called /// from Value::setName() whenever the name of this function changes. - void recalculateIntrinsicID(); + void updateAfterNameChange(); /// getCallingConv()/setCallingConv(CC) - These method get and set the /// calling convention of this function. The enum values for the known diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index 7b38583e9bc75..20959cf6948f6 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -1138,8 +1138,15 @@ bool TargetLibraryInfoImpl::getLibFunc(const Function &FDecl, const Module *M = FDecl.getParent(); assert(M && "Expecting FDecl to be connected to a Module."); - return getLibFunc(FDecl.getName(), F) && - isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M); + if (FDecl.LibFuncCache == Function::UnknownLibFunc) + if (!getLibFunc(FDecl.getName(), FDecl.LibFuncCache)) + FDecl.LibFuncCache = NotLibFunc; + + if (FDecl.LibFuncCache == NotLibFunc) + return false; + + F = FDecl.LibFuncCache; + return isValidProtoForLibFunc(*FDecl.getFunctionType(), F, *M); } void TargetLibraryInfoImpl::disableAllFunctions() { diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index 49e0c1c5883c2..c3706dc1b02fc 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -912,7 +912,8 @@ Intrinsic::ID Function::lookupIntrinsicID(StringRef Name) { : Intrinsic::not_intrinsic; } -void Function::recalculateIntrinsicID() { +void Function::updateAfterNameChange() { + LibFuncCache = UnknownLibFunc; StringRef Name = getName(); if (!Name.startswith("llvm.")) { HasLLVMReservedName = false; diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp index c05f9ac5a0fe0..b6e25c46b514d 100644 --- a/llvm/lib/IR/Value.cpp +++ b/llvm/lib/IR/Value.cpp @@ -377,7 +377,7 @@ void Value::setNameImpl(const Twine &NewName) { void Value::setName(const Twine &NewName) { setNameImpl(NewName); if (Function *F = dyn_cast(this)) - F->recalculateIntrinsicID(); + F->updateAfterNameChange(); } void Value::takeName(Value *V) {