From 06aab08788f708b5787e37f22059911148def458 Mon Sep 17 00:00:00 2001 From: Michael Zolotukhin Date: Tue, 17 Mar 2015 19:22:30 +0000 Subject: [PATCH] TLI: Add interface for querying whether a function is vectorizable. Review: http://reviews.llvm.org/D8093 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@232523 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/TargetLibraryInfo.h | 55 ++++++++++++++++++ lib/Analysis/TargetLibraryInfo.cpp | 70 +++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/include/llvm/Analysis/TargetLibraryInfo.h b/include/llvm/Analysis/TargetLibraryInfo.h index b82a67570ba..c2ece8cf3ba 100644 --- a/include/llvm/Analysis/TargetLibraryInfo.h +++ b/include/llvm/Analysis/TargetLibraryInfo.h @@ -11,6 +11,7 @@ #define LLVM_ANALYSIS_TARGETLIBRARYINFO_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/Triple.h" #include "llvm/IR/Function.h" @@ -18,6 +19,14 @@ #include "llvm/Pass.h" namespace llvm { +/// VecDesc - Describes a possible vectorization of a function. +/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized +/// by a factor 'VectorizationFactor'. +struct VecDesc { + const char *ScalarFnName; + const char *VectorFnName; + unsigned VectorizationFactor; +}; class PreservedAnalyses; namespace LibFunc { @@ -55,6 +64,12 @@ class TargetLibraryInfoImpl { return static_cast((AvailableArray[F/4] >> 2*(F&3)) & 3); } + /// Vectorization descriptors - sorted by ScalarFnName. + std::vector VectorDescs; + /// Scalarization descriptors - same content as VectorDescs but sorted based + /// on VectorFnName rather than ScalarFnName. + std::vector ScalarDescs; + public: TargetLibraryInfoImpl(); explicit TargetLibraryInfoImpl(const Triple &T); @@ -97,6 +112,37 @@ public: /// /// This can be used for options like -fno-builtin. void disableAllFunctions(); + + /// addVectorizableFunctions - Add a set of scalar -> vector mappings, + /// queryable via getVectorizedFunction and getScalarizedFunction. + void addVectorizableFunctions(ArrayRef Fns); + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with vectorization factor VF. + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return !getVectorizedFunction(F, VF).empty(); + } + + /// isFunctionVectorizable - Return true if the function F has a + /// vector equivalent with any vectorization factor. + bool isFunctionVectorizable(StringRef F) const; + + /// getVectorizedFunction - Return the name of the equivalent of + /// F, vectorized with factor VF. If no such mapping exists, + /// return the empty string. + StringRef getVectorizedFunction(StringRef F, unsigned VF) const; + + /// isFunctionScalarizable - Return true if the function F has a + /// scalar equivalent, and set VF to be the vectorization factor. + bool isFunctionScalarizable(StringRef F, unsigned &VF) const { + return !getScalarizedFunction(F, VF).empty(); + } + + /// getScalarizedFunction - Return the name of the equivalent of + /// F, scalarized. If no such mapping exists, return the empty string. + /// + /// Set VF to the vectorization factor. + StringRef getScalarizedFunction(StringRef F, unsigned &VF) const; }; /// \brief Provides information about what library functions are available for @@ -137,6 +183,15 @@ public: bool has(LibFunc::Func F) const { return Impl->getState(F) != TargetLibraryInfoImpl::Unavailable; } + bool isFunctionVectorizable(StringRef F, unsigned VF) const { + return Impl->isFunctionVectorizable(F, VF); + }; + bool isFunctionVectorizable(StringRef F) const { + return Impl->isFunctionVectorizable(F); + }; + StringRef getVectorizedFunction(StringRef F, unsigned VF) const { + return Impl->getVectorizedFunction(F, VF); + }; /// \brief Tests if the function is both available and a candidate for /// optimized code generation. diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp index 8b57ba39c27..c8f193f0299 100644 --- a/lib/Analysis/TargetLibraryInfo.cpp +++ b/lib/Analysis/TargetLibraryInfo.cpp @@ -364,12 +364,16 @@ TargetLibraryInfoImpl::TargetLibraryInfoImpl(const Triple &T) { TargetLibraryInfoImpl::TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI) : CustomNames(TLI.CustomNames) { memcpy(AvailableArray, TLI.AvailableArray, sizeof(AvailableArray)); + VectorDescs = TLI.VectorDescs; + ScalarDescs = TLI.ScalarDescs; } TargetLibraryInfoImpl::TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI) : CustomNames(std::move(TLI.CustomNames)) { std::move(std::begin(TLI.AvailableArray), std::end(TLI.AvailableArray), AvailableArray); + VectorDescs = TLI.VectorDescs; + ScalarDescs = TLI.ScalarDescs; } TargetLibraryInfoImpl &TargetLibraryInfoImpl::operator=(const TargetLibraryInfoImpl &TLI) { @@ -422,6 +426,72 @@ void TargetLibraryInfoImpl::disableAllFunctions() { memset(AvailableArray, 0, sizeof(AvailableArray)); } +static bool compareByScalarFnName(const VecDesc &LHS, const VecDesc &RHS) { + return std::strncmp(LHS.ScalarFnName, RHS.ScalarFnName, + std::strlen(RHS.ScalarFnName)) < 0; +} + +static bool compareByVectorFnName(const VecDesc &LHS, const VecDesc &RHS) { + return std::strncmp(LHS.VectorFnName, RHS.VectorFnName, + std::strlen(RHS.VectorFnName)) < 0; +} + +static bool compareWithScalarFnName(const VecDesc &LHS, StringRef S) { + return std::strncmp(LHS.ScalarFnName, S.data(), S.size()) < 0; +} + +static bool compareWithVectorFnName(const VecDesc &LHS, StringRef S) { + return std::strncmp(LHS.VectorFnName, S.data(), S.size()) < 0; +} + +void TargetLibraryInfoImpl::addVectorizableFunctions(ArrayRef Fns) { + VectorDescs.insert(VectorDescs.end(), Fns.begin(), Fns.end()); + std::sort(VectorDescs.begin(), VectorDescs.end(), compareByScalarFnName); + + ScalarDescs.insert(ScalarDescs.end(), Fns.begin(), Fns.end()); + std::sort(ScalarDescs.begin(), ScalarDescs.end(), compareByVectorFnName); +} + +bool TargetLibraryInfoImpl::isFunctionVectorizable(StringRef funcName) const { + funcName = sanitizeFunctionName(funcName); + if (funcName.empty()) + return false; + + std::vector::const_iterator I = std::lower_bound( + VectorDescs.begin(), VectorDescs.end(), funcName, + compareWithScalarFnName); + return I != VectorDescs.end() && StringRef(I->ScalarFnName) == funcName; +} + +StringRef TargetLibraryInfoImpl::getVectorizedFunction(StringRef F, + unsigned VF) const { + F = sanitizeFunctionName(F); + if (F.empty()) + return F; + std::vector::const_iterator I = std::lower_bound( + VectorDescs.begin(), VectorDescs.end(), F, compareWithScalarFnName); + while (I != VectorDescs.end() && StringRef(I->ScalarFnName) == F) { + if (I->VectorizationFactor == VF) + return I->VectorFnName; + ++I; + } + return StringRef(); +} + +StringRef TargetLibraryInfoImpl::getScalarizedFunction(StringRef F, + unsigned &VF) const { + F = sanitizeFunctionName(F); + if (F.empty()) + return F; + + std::vector::const_iterator I = std::lower_bound( + ScalarDescs.begin(), ScalarDescs.end(), F, compareWithVectorFnName); + if (I == VectorDescs.end() || StringRef(I->VectorFnName) != F) + return StringRef(); + VF = I->VectorizationFactor; + return I->ScalarFnName; +} + TargetLibraryInfo TargetLibraryAnalysis::run(Module &M) { if (PresetInfoImpl) return TargetLibraryInfo(*PresetInfoImpl);