#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/IR/InstrTypes.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
namespace llvm {
template <typename T> class ArrayRef;
class Function;
class Module;
class Triple;
struct VecDesc {
StringRef ScalarFnName;
StringRef VectorFnName;
ElementCount VectorizationFactor;
};
enum LibFunc : unsigned {
#define TLI_DEFINE_ENUM
#include "llvm/Analysis/TargetLibraryInfo.def"
NumLibFuncs,
NotLibFunc
};
class TargetLibraryInfoImpl {
friend class TargetLibraryInfo;
unsigned char AvailableArray[(NumLibFuncs+3)/4];
DenseMap<unsigned, std::string> CustomNames;
static StringLiteral const StandardNames[NumLibFuncs];
bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param;
unsigned SizeOfInt;
enum AvailabilityState {
StandardName = 3, CustomName = 1,
Unavailable = 0 };
void setState(LibFunc F, AvailabilityState State) {
AvailableArray[F/4] &= ~(3 << 2*(F&3));
AvailableArray[F/4] |= State << 2*(F&3);
}
AvailabilityState getState(LibFunc F) const {
return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
}
std::vector<VecDesc> VectorDescs;
std::vector<VecDesc> ScalarDescs;
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
const Module &M) const;
public:
enum VectorLibrary {
NoLibrary, Accelerate, DarwinLibSystemM, LIBMVEC_X86, MASSV, SVML };
TargetLibraryInfoImpl();
explicit TargetLibraryInfoImpl(const Triple &T);
TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
bool getLibFunc(StringRef funcName, LibFunc &F) const;
bool getLibFunc(const Function &FDecl, LibFunc &F) const;
void setUnavailable(LibFunc F) {
setState(F, Unavailable);
}
void setAvailable(LibFunc F) {
setState(F, StandardName);
}
void setAvailableWithName(LibFunc F, StringRef Name) {
if (StandardNames[F] != Name) {
setState(F, CustomName);
CustomNames[F] = std::string(Name);
assert(CustomNames.find(F) != CustomNames.end());
} else {
setState(F, StandardName);
}
}
void disableAllFunctions();
void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
return !getVectorizedFunction(F, VF).empty();
}
bool isFunctionVectorizable(StringRef F) const;
StringRef getVectorizedFunction(StringRef F, const ElementCount &VF) const;
void setShouldExtI32Param(bool Val) {
ShouldExtI32Param = Val;
}
void setShouldExtI32Return(bool Val) {
ShouldExtI32Return = Val;
}
void setShouldSignExtI32Param(bool Val) {
ShouldSignExtI32Param = Val;
}
unsigned getWCharSize(const Module &M) const;
unsigned getIntSize() const {
return SizeOfInt;
}
void setIntSize(unsigned Bits) {
SizeOfInt = Bits;
}
void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
ElementCount &Scalable) const;
static bool isCallingConvCCompatible(CallBase *CI);
static bool isCallingConvCCompatible(Function *Callee);
};
class TargetLibraryInfo {
friend class TargetLibraryAnalysis;
friend class TargetLibraryInfoWrapperPass;
const TargetLibraryInfoImpl *Impl;
BitVector OverrideAsUnavailable;
public:
explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
Optional<const Function *> F = None)
: Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) {
if (!F)
return;
if ((*F)->hasFnAttribute("no-builtins"))
disableAllFunctions();
else {
LibFunc LF;
AttributeSet FnAttrs = (*F)->getAttributes().getFnAttrs();
for (const Attribute &Attr : FnAttrs) {
if (!Attr.isStringAttribute())
continue;
auto AttrStr = Attr.getKindAsString();
if (!AttrStr.consume_front("no-builtin-"))
continue;
if (getLibFunc(AttrStr, LF))
setUnavailable(LF);
}
}
}
TargetLibraryInfo(const TargetLibraryInfo &TLI) = default;
TargetLibraryInfo(TargetLibraryInfo &&TLI)
: Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) = default;
TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
Impl = TLI.Impl;
OverrideAsUnavailable = TLI.OverrideAsUnavailable;
return *this;
}
bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI,
bool AllowCallerSuperset) const {
if (!AllowCallerSuperset)
return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
BitVector B = OverrideAsUnavailable;
B |= CalleeTLI.OverrideAsUnavailable;
return B == OverrideAsUnavailable;
}
bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
const Module &M) const {
return Impl->isValidProtoForLibFunc(FTy, F, M);
}
bool getLibFunc(StringRef funcName, LibFunc &F) const {
return Impl->getLibFunc(funcName, F);
}
bool getLibFunc(const Function &FDecl, LibFunc &F) const {
return Impl->getLibFunc(FDecl, F);
}
bool getLibFunc(const CallBase &CB, LibFunc &F) const {
return !CB.isNoBuiltin() && CB.getCalledFunction() &&
getLibFunc(*(CB.getCalledFunction()), F);
}
void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED {
OverrideAsUnavailable.set();
}
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);
}
bool has(LibFunc F) const {
return getState(F) != TargetLibraryInfoImpl::Unavailable;
}
bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
return Impl->isFunctionVectorizable(F, VF);
}
bool isFunctionVectorizable(StringRef F) const {
return Impl->isFunctionVectorizable(F);
}
StringRef getVectorizedFunction(StringRef F, const ElementCount &VF) const {
return Impl->getVectorizedFunction(F, VF);
}
bool hasOptimizedCodeGen(LibFunc F) const {
if (getState(F) == TargetLibraryInfoImpl::Unavailable)
return false;
switch (F) {
default: break;
case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl:
case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl:
case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl:
case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl:
case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl:
case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite:
case LibFunc_sqrtl_finite:
case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl:
case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl:
case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl:
case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl:
case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill:
case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl:
case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl:
case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl:
case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l:
case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l:
case LibFunc_memcpy: case LibFunc_memset: case LibFunc_memmove:
case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp:
case LibFunc_strcpy: case LibFunc_stpcpy: case LibFunc_strlen:
case LibFunc_strnlen: case LibFunc_memchr: case LibFunc_mempcpy:
return true;
}
return false;
}
StringRef getName(LibFunc F) const {
auto State = getState(F);
if (State == TargetLibraryInfoImpl::Unavailable)
return StringRef();
if (State == TargetLibraryInfoImpl::StandardName)
return Impl->StandardNames[F];
assert(State == TargetLibraryInfoImpl::CustomName);
return Impl->CustomNames.find(F)->second;
}
Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
if (Impl->ShouldExtI32Param)
return Signed ? Attribute::SExt : Attribute::ZExt;
if (Impl->ShouldSignExtI32Param)
return Attribute::SExt;
return Attribute::None;
}
Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
if (Impl->ShouldExtI32Return)
return Signed ? Attribute::SExt : Attribute::ZExt;
return Attribute::None;
}
unsigned getWCharSize(const Module &M) const {
return Impl->getWCharSize(M);
}
unsigned getIntSize() const {
return Impl->getIntSize();
}
bool invalidate(Module &, const PreservedAnalyses &,
ModuleAnalysisManager::Invalidator &) {
return false;
}
bool invalidate(Function &, const PreservedAnalyses &,
FunctionAnalysisManager::Invalidator &) {
return false;
}
void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
ElementCount &ScalableVF) const {
Impl->getWidestVF(ScalarF, FixedVF, ScalableVF);
}
bool isKnownVectorFunctionInLibrary(StringRef F) const {
return this->isFunctionVectorizable(F);
}
};
class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
public:
typedef TargetLibraryInfo Result;
TargetLibraryAnalysis() = default;
TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl)
: BaselineInfoImpl(std::move(BaselineInfoImpl)) {}
TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &);
private:
friend AnalysisInfoMixin<TargetLibraryAnalysis>;
static AnalysisKey Key;
Optional<TargetLibraryInfoImpl> BaselineInfoImpl;
};
class TargetLibraryInfoWrapperPass : public ImmutablePass {
TargetLibraryAnalysis TLA;
Optional<TargetLibraryInfo> TLI;
virtual void anchor();
public:
static char ID;
TargetLibraryInfoWrapperPass();
explicit TargetLibraryInfoWrapperPass(const Triple &T);
explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
TargetLibraryInfo &getTLI(const Function &F) {
FunctionAnalysisManager DummyFAM;
TLI = TLA.run(F, DummyFAM);
return *TLI;
}
};
}
#endif