Index: include/llvm/Analysis/TargetLibraryInfo.h =================================================================== --- include/llvm/Analysis/TargetLibraryInfo.h +++ include/llvm/Analysis/TargetLibraryInfo.h @@ -9,6 +9,7 @@ #ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H #define LLVM_ANALYSIS_TARGETLIBRARYINFO_H +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/Triple.h" @@ -47,7 +48,11 @@ class TargetLibraryInfoImpl { friend class TargetLibraryInfo; + // TODO: Move this to TargetLibraryInfo (and remove OverrideAsUnavailable) + // once -fno-builtin* options are translated to function attributes (and + // therefore the code setting it from clang options can be removed). unsigned char AvailableArray[(NumLibFuncs+3)/4]; + llvm::DenseMap CustomNames; static StringLiteral const StandardNames[NumLibFuncs]; bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param; @@ -65,6 +70,14 @@ return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); } + // TODO: If we ever want to support setting these on a per-function basis + // (e.g. for LTO), the clang options will need to be converted to function + // attributes, and we will need to restructure these members. Either: + // 1) These vectors are moved into the TargetLibraryInfo; or + // 2) Set up vectors here for all 3 vector libraries, and save the veclib + // type in the TargetLibraryInfo to select between them for a given + // Function. This saves space overall, since only one copy of the Impl is + // created, but the TargetLibraryInfo will be per-Function. /// Vectorization descriptors - sorted by ScalarFnName. std::vector VectorDescs; /// Scalarization descriptors - same content as VectorDescs but sorted based @@ -208,20 +221,48 @@ friend class TargetLibraryAnalysis; friend class TargetLibraryInfoWrapperPass; + /// The global (module level) TLI info. const TargetLibraryInfoImpl *Impl; + /// Support for -fno-builtin* options as function attributes, overrides + /// information in global TargetLibraryInfoImpl. + BitVector OverrideAsUnavailable; + public: - explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl) : Impl(&Impl) {} + explicit TargetLibraryInfo( + const TargetLibraryInfoImpl &Impl, + LLVM_ATTRIBUTE_UNUSED Optional F = None) + : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) { + // TODO: Implement the following once the corresponding attributes are + // implemented. +#if 0 + if (F) { + if (F.getNoBuiltin()) + disableAllFunctions(); + else { + // Disable individual libc/libm calls in TargetLibraryInfo. + LibFunc LF; + for (auto &FuncName : F.getNoBuiltinFuncs()) + if (getLibFunc(FuncName, LF)) + setUnavailable(LF); + } + } +#endif + } // Provide value semantics. - TargetLibraryInfo(const TargetLibraryInfo &TLI) : Impl(TLI.Impl) {} - TargetLibraryInfo(TargetLibraryInfo &&TLI) : Impl(TLI.Impl) {} + TargetLibraryInfo(const TargetLibraryInfo &TLI) + : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} + TargetLibraryInfo(TargetLibraryInfo &&TLI) + : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {} TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) { Impl = TLI.Impl; + OverrideAsUnavailable = TLI.OverrideAsUnavailable; return *this; } TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) { Impl = TLI.Impl; + OverrideAsUnavailable = TLI.OverrideAsUnavailable; return *this; } @@ -244,9 +285,27 @@ getLibFunc(*(CS.getCalledFunction()), F); } + /// Disables all builtins. + /// + /// This can be used for options like -fno-builtin. + void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED { + OverrideAsUnavailable.set(); + } + + /// Forces a function to be marked as unavailable. + void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED { + OverrideAsUnavailable.set(F); + } + + TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const { + if (OverrideAsUnavailable[F]) + return TargetLibraryInfoImpl::Unavailable; + return Impl->getState(F); + } + /// Tests whether a library function is available. bool has(LibFunc F) const { - return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; + return getState(F) != TargetLibraryInfoImpl::Unavailable; } bool isFunctionVectorizable(StringRef F, unsigned VF) const { return Impl->isFunctionVectorizable(F, VF); @@ -261,7 +320,7 @@ /// Tests if the function is both available and a candidate for optimized code /// generation. bool hasOptimizedCodeGen(LibFunc F) const { - if (Impl->getState(F) == TargetLibraryInfoImpl::Unavailable) + if (getState(F) == TargetLibraryInfoImpl::Unavailable) return false; switch (F) { default: break; @@ -291,7 +350,7 @@ } StringRef getName(LibFunc F) const { - auto State = Impl->getState(F); + auto State = getState(F); if (State == TargetLibraryInfoImpl::Unavailable) return StringRef(); if (State == TargetLibraryInfoImpl::StandardName) @@ -353,29 +412,24 @@ /// module. TargetLibraryAnalysis() {} - /// Construct a library analysis with preset info. + /// Construct a library analysis with baseline Module-level info. /// - /// This will directly copy the preset info into the result without - /// consulting the module's triple. - TargetLibraryAnalysis(TargetLibraryInfoImpl PresetInfoImpl) - : PresetInfoImpl(std::move(PresetInfoImpl)) {} + /// This will be supplemented with Function-specific info in the Result. + TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl) + : BaselineInfoImpl(std::move(BaselineInfoImpl)) {} - TargetLibraryInfo run(Function &F, FunctionAnalysisManager &); + TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &); private: friend AnalysisInfoMixin; static AnalysisKey Key; - Optional PresetInfoImpl; - - StringMap> Impls; - - TargetLibraryInfoImpl &lookupInfoImpl(const Triple &T); + Optional BaselineInfoImpl; }; class TargetLibraryInfoWrapperPass : public ImmutablePass { - TargetLibraryInfoImpl TLIImpl; - TargetLibraryInfo TLI; + TargetLibraryAnalysis TLA; + Optional TLI; virtual void anchor(); @@ -385,12 +439,10 @@ explicit TargetLibraryInfoWrapperPass(const Triple &T); explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); - TargetLibraryInfo &getTLI(const Function &F LLVM_ATTRIBUTE_UNUSED) { - return TLI; - } - const TargetLibraryInfo & - getTLI(const Function &F LLVM_ATTRIBUTE_UNUSED) const { - return TLI; + TargetLibraryInfo &getTLI(const Function &F) { + FunctionAnalysisManager DummyFAM; + TLI = TLA.run(F, DummyFAM); + return *TLI; } }; Index: lib/Analysis/TargetLibraryInfo.cpp =================================================================== --- lib/Analysis/TargetLibraryInfo.cpp +++ lib/Analysis/TargetLibraryInfo.cpp @@ -1587,22 +1587,12 @@ return I->ScalarFnName; } -TargetLibraryInfo TargetLibraryAnalysis::run(Function &F, +TargetLibraryInfo TargetLibraryAnalysis::run(const Function &F, FunctionAnalysisManager &) { - if (PresetInfoImpl) - return TargetLibraryInfo(*PresetInfoImpl); - - return TargetLibraryInfo( - lookupInfoImpl(Triple(F.getParent()->getTargetTriple()))); -} - -TargetLibraryInfoImpl &TargetLibraryAnalysis::lookupInfoImpl(const Triple &T) { - std::unique_ptr &Impl = - Impls[T.normalize()]; - if (!Impl) - Impl.reset(new TargetLibraryInfoImpl(T)); - - return *Impl; + if (!BaselineInfoImpl) + BaselineInfoImpl = + TargetLibraryInfoImpl(Triple(F.getParent()->getTargetTriple())); + return TargetLibraryInfo(*BaselineInfoImpl, &F); } unsigned TargetLibraryInfoImpl::getWCharSize(const Module &M) const { @@ -1613,18 +1603,18 @@ } TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass() - : ImmutablePass(ID), TLIImpl(), TLI(TLIImpl) { + : ImmutablePass(ID), TLA(TargetLibraryInfoImpl()) { initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); } TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass(const Triple &T) - : ImmutablePass(ID), TLIImpl(T), TLI(TLIImpl) { + : ImmutablePass(ID), TLA(TargetLibraryInfoImpl(T)) { initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); } TargetLibraryInfoWrapperPass::TargetLibraryInfoWrapperPass( const TargetLibraryInfoImpl &TLIImpl) - : ImmutablePass(ID), TLIImpl(TLIImpl), TLI(this->TLIImpl) { + : ImmutablePass(ID), TLA(TLIImpl) { initializeTargetLibraryInfoWrapperPassPass(*PassRegistry::getPassRegistry()); }