File indexing completed on 2026-05-10 08:43:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H
0010 #define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
0011
0012 #include "llvm/ADT/DenseMap.h"
0013 #include "llvm/IR/Constants.h"
0014 #include "llvm/IR/InstrTypes.h"
0015 #include "llvm/IR/Module.h"
0016 #include "llvm/IR/PassManager.h"
0017 #include "llvm/Pass.h"
0018 #include "llvm/TargetParser/Triple.h"
0019 #include <bitset>
0020 #include <optional>
0021
0022 namespace llvm {
0023
0024 template <typename T> class ArrayRef;
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 class VecDesc {
0043 StringRef ScalarFnName;
0044 StringRef VectorFnName;
0045 ElementCount VectorizationFactor;
0046 bool Masked;
0047 StringRef VABIPrefix;
0048
0049 public:
0050 VecDesc() = delete;
0051 VecDesc(StringRef ScalarFnName, StringRef VectorFnName,
0052 ElementCount VectorizationFactor, bool Masked, StringRef VABIPrefix)
0053 : ScalarFnName(ScalarFnName), VectorFnName(VectorFnName),
0054 VectorizationFactor(VectorizationFactor), Masked(Masked),
0055 VABIPrefix(VABIPrefix) {}
0056
0057 StringRef getScalarFnName() const { return ScalarFnName; }
0058 StringRef getVectorFnName() const { return VectorFnName; }
0059 ElementCount getVectorizationFactor() const { return VectorizationFactor; }
0060 bool isMasked() const { return Masked; }
0061 StringRef getVABIPrefix() const { return VABIPrefix; }
0062
0063
0064
0065 std::string getVectorFunctionABIVariantString() const;
0066 };
0067
0068 enum LibFunc : unsigned {
0069 #define TLI_DEFINE_ENUM
0070 #include "llvm/Analysis/TargetLibraryInfo.def"
0071
0072 NumLibFuncs,
0073 NotLibFunc
0074 };
0075
0076
0077
0078
0079
0080
0081
0082 class TargetLibraryInfoImpl {
0083 friend class TargetLibraryInfo;
0084
0085 unsigned char AvailableArray[(NumLibFuncs+3)/4];
0086 DenseMap<unsigned, std::string> CustomNames;
0087 static StringLiteral const StandardNames[NumLibFuncs];
0088 bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param, ShouldSignExtI32Return;
0089 unsigned SizeOfInt;
0090
0091 enum AvailabilityState {
0092 StandardName = 3,
0093 CustomName = 1,
0094 Unavailable = 0
0095 };
0096 void setState(LibFunc F, AvailabilityState State) {
0097 AvailableArray[F/4] &= ~(3 << 2*(F&3));
0098 AvailableArray[F/4] |= State << 2*(F&3);
0099 }
0100 AvailabilityState getState(LibFunc F) const {
0101 return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
0102 }
0103
0104
0105 std::vector<VecDesc> VectorDescs;
0106
0107
0108 std::vector<VecDesc> ScalarDescs;
0109
0110
0111
0112 bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
0113 const Module &M) const;
0114
0115 public:
0116
0117
0118
0119
0120
0121
0122
0123 enum VectorLibrary {
0124 NoLibrary,
0125 Accelerate,
0126 DarwinLibSystemM,
0127 LIBMVEC_X86,
0128 MASSV,
0129 SVML,
0130 SLEEFGNUABI,
0131 ArmPL,
0132 AMDLIBM
0133 };
0134
0135 TargetLibraryInfoImpl();
0136 explicit TargetLibraryInfoImpl(const Triple &T);
0137
0138
0139 TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
0140 TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
0141 TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
0142 TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
0143
0144
0145
0146
0147
0148 bool getLibFunc(StringRef funcName, LibFunc &F) const;
0149
0150
0151
0152
0153
0154
0155
0156
0157 bool getLibFunc(const Function &FDecl, LibFunc &F) const;
0158
0159
0160
0161 bool getLibFunc(unsigned int Opcode, Type *Ty, LibFunc &F) const;
0162
0163
0164 void setUnavailable(LibFunc F) {
0165 setState(F, Unavailable);
0166 }
0167
0168
0169 void setAvailable(LibFunc F) {
0170 setState(F, StandardName);
0171 }
0172
0173
0174
0175 void setAvailableWithName(LibFunc F, StringRef Name) {
0176 if (StandardNames[F] != Name) {
0177 setState(F, CustomName);
0178 CustomNames[F] = std::string(Name);
0179 assert(CustomNames.contains(F));
0180 } else {
0181 setState(F, StandardName);
0182 }
0183 }
0184
0185
0186
0187
0188 void disableAllFunctions();
0189
0190
0191
0192 void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
0193
0194
0195
0196 void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib,
0197 const llvm::Triple &TargetTriple);
0198
0199
0200
0201 bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
0202 return !(getVectorizedFunction(F, VF, false).empty() &&
0203 getVectorizedFunction(F, VF, true).empty());
0204 }
0205
0206
0207
0208 bool isFunctionVectorizable(StringRef F) const;
0209
0210
0211
0212 StringRef getVectorizedFunction(StringRef F, const ElementCount &VF,
0213 bool Masked) const;
0214
0215
0216
0217
0218 const VecDesc *getVectorMappingInfo(StringRef F, const ElementCount &VF,
0219 bool Masked) const;
0220
0221
0222
0223
0224 void setShouldExtI32Param(bool Val) {
0225 ShouldExtI32Param = Val;
0226 }
0227
0228
0229
0230
0231 void setShouldExtI32Return(bool Val) {
0232 ShouldExtI32Return = Val;
0233 }
0234
0235
0236
0237 void setShouldSignExtI32Param(bool Val) {
0238 ShouldSignExtI32Param = Val;
0239 }
0240
0241
0242
0243 void setShouldSignExtI32Return(bool Val) {
0244 ShouldSignExtI32Return = Val;
0245 }
0246
0247
0248
0249 unsigned getWCharSize(const Module &M) const;
0250
0251
0252 unsigned getSizeTSize(const Module &M) const;
0253
0254
0255 unsigned getIntSize() const {
0256 return SizeOfInt;
0257 }
0258
0259
0260 void setIntSize(unsigned Bits) {
0261 SizeOfInt = Bits;
0262 }
0263
0264
0265
0266 void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
0267 ElementCount &Scalable) const;
0268
0269
0270
0271 static bool isCallingConvCCompatible(CallBase *CI);
0272 static bool isCallingConvCCompatible(Function *Callee);
0273 };
0274
0275
0276
0277
0278
0279
0280 class TargetLibraryInfo {
0281 friend class TargetLibraryAnalysis;
0282 friend class TargetLibraryInfoWrapperPass;
0283
0284
0285 const TargetLibraryInfoImpl *Impl;
0286
0287
0288
0289 std::bitset<NumLibFuncs> OverrideAsUnavailable;
0290
0291 public:
0292 explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
0293 std::optional<const Function *> F = std::nullopt)
0294 : Impl(&Impl) {
0295 if (!F)
0296 return;
0297 if ((*F)->hasFnAttribute("no-builtins"))
0298 disableAllFunctions();
0299 else {
0300
0301 LibFunc LF;
0302 AttributeSet FnAttrs = (*F)->getAttributes().getFnAttrs();
0303 for (const Attribute &Attr : FnAttrs) {
0304 if (!Attr.isStringAttribute())
0305 continue;
0306 auto AttrStr = Attr.getKindAsString();
0307 if (!AttrStr.consume_front("no-builtin-"))
0308 continue;
0309 if (getLibFunc(AttrStr, LF))
0310 setUnavailable(LF);
0311 }
0312 }
0313 }
0314
0315
0316 TargetLibraryInfo(const TargetLibraryInfo &TLI) = default;
0317 TargetLibraryInfo(TargetLibraryInfo &&TLI) = default;
0318 TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) = default;
0319 TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) = default;
0320
0321
0322
0323
0324
0325 bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI,
0326 bool AllowCallerSuperset) const {
0327 if (!AllowCallerSuperset)
0328 return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
0329
0330
0331 return (CalleeTLI.OverrideAsUnavailable & ~OverrideAsUnavailable).none();
0332 }
0333
0334
0335
0336 bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
0337 const Module &M) const {
0338 return Impl->isValidProtoForLibFunc(FTy, F, M);
0339 }
0340
0341
0342
0343
0344
0345 bool getLibFunc(StringRef funcName, LibFunc &F) const {
0346 return Impl->getLibFunc(funcName, F);
0347 }
0348
0349 bool getLibFunc(const Function &FDecl, LibFunc &F) const {
0350 return Impl->getLibFunc(FDecl, F);
0351 }
0352
0353
0354
0355 bool getLibFunc(const CallBase &CB, LibFunc &F) const {
0356 return !CB.isNoBuiltin() && CB.getCalledFunction() &&
0357 getLibFunc(*(CB.getCalledFunction()), F);
0358 }
0359
0360
0361
0362 bool getLibFunc(unsigned int Opcode, Type *Ty, LibFunc &F) const {
0363 return Impl->getLibFunc(Opcode, Ty, F);
0364 }
0365
0366
0367
0368
0369 void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED {
0370 OverrideAsUnavailable.set();
0371 }
0372
0373
0374 void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED {
0375 assert(F < OverrideAsUnavailable.size() && "out-of-bounds LibFunc");
0376 OverrideAsUnavailable.set(F);
0377 }
0378
0379 TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const {
0380 assert(F < OverrideAsUnavailable.size() && "out-of-bounds LibFunc");
0381 if (OverrideAsUnavailable[F])
0382 return TargetLibraryInfoImpl::Unavailable;
0383 return Impl->getState(F);
0384 }
0385
0386
0387 bool has(LibFunc F) const {
0388 return getState(F) != TargetLibraryInfoImpl::Unavailable;
0389 }
0390 bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
0391 return Impl->isFunctionVectorizable(F, VF);
0392 }
0393 bool isFunctionVectorizable(StringRef F) const {
0394 return Impl->isFunctionVectorizable(F);
0395 }
0396 StringRef getVectorizedFunction(StringRef F, const ElementCount &VF,
0397 bool Masked = false) const {
0398 return Impl->getVectorizedFunction(F, VF, Masked);
0399 }
0400 const VecDesc *getVectorMappingInfo(StringRef F, const ElementCount &VF,
0401 bool Masked) const {
0402 return Impl->getVectorMappingInfo(F, VF, Masked);
0403 }
0404
0405
0406
0407 bool hasOptimizedCodeGen(LibFunc F) const {
0408 if (getState(F) == TargetLibraryInfoImpl::Unavailable)
0409 return false;
0410 switch (F) {
0411 default: break;
0412
0413 case LibFunc_acos: case LibFunc_acosf: case LibFunc_acosl:
0414 case LibFunc_asin: case LibFunc_asinf: case LibFunc_asinl:
0415 case LibFunc_atan2: case LibFunc_atan2f: case LibFunc_atan2l:
0416 case LibFunc_atan: case LibFunc_atanf: case LibFunc_atanl:
0417 case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill:
0418 case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl:
0419 case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl:
0420 case LibFunc_cosh: case LibFunc_coshf: case LibFunc_coshl:
0421 case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l:
0422 case LibFunc_exp10: case LibFunc_exp10f: case LibFunc_exp10l:
0423 case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl:
0424 case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl:
0425 case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl:
0426 case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl:
0427 case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl:
0428 case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l:
0429 case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp:
0430 case LibFunc_memcpy: case LibFunc_memset: case LibFunc_memmove:
0431 case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl:
0432 case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl:
0433 case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl:
0434 case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl:
0435 case LibFunc_sinh: case LibFunc_sinhf: case LibFunc_sinhl:
0436 case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl:
0437 case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite:
0438 case LibFunc_sqrtl_finite:
0439 case LibFunc_strcpy: case LibFunc_stpcpy: case LibFunc_strlen:
0440 case LibFunc_strnlen: case LibFunc_memchr: case LibFunc_mempcpy:
0441 case LibFunc_tan: case LibFunc_tanf: case LibFunc_tanl:
0442 case LibFunc_tanh: case LibFunc_tanhf: case LibFunc_tanhl:
0443 case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl:
0444
0445 return true;
0446 }
0447 return false;
0448 }
0449
0450 StringRef getName(LibFunc F) const {
0451 auto State = getState(F);
0452 if (State == TargetLibraryInfoImpl::Unavailable)
0453 return StringRef();
0454 if (State == TargetLibraryInfoImpl::StandardName)
0455 return Impl->StandardNames[F];
0456 assert(State == TargetLibraryInfoImpl::CustomName);
0457 return Impl->CustomNames.find(F)->second;
0458 }
0459
0460 static void initExtensionsForTriple(bool &ShouldExtI32Param,
0461 bool &ShouldExtI32Return,
0462 bool &ShouldSignExtI32Param,
0463 bool &ShouldSignExtI32Return,
0464 const Triple &T) {
0465 ShouldExtI32Param = ShouldExtI32Return = false;
0466 ShouldSignExtI32Param = ShouldSignExtI32Return = false;
0467
0468
0469
0470 if (T.isPPC64() || T.getArch() == Triple::sparcv9 ||
0471 T.getArch() == Triple::systemz) {
0472 ShouldExtI32Param = true;
0473 ShouldExtI32Return = true;
0474 }
0475
0476
0477 if (T.isLoongArch() || T.isMIPS() || T.isRISCV64()) {
0478 ShouldSignExtI32Param = true;
0479 }
0480
0481
0482 if (T.isLoongArch() || T.isRISCV64()) {
0483 ShouldSignExtI32Return = true;
0484 }
0485 }
0486
0487
0488
0489
0490 private:
0491 static Attribute::AttrKind getExtAttrForI32Param(bool ShouldExtI32Param_,
0492 bool ShouldSignExtI32Param_,
0493 bool Signed = true) {
0494 if (ShouldExtI32Param_)
0495 return Signed ? Attribute::SExt : Attribute::ZExt;
0496 if (ShouldSignExtI32Param_)
0497 return Attribute::SExt;
0498 return Attribute::None;
0499 }
0500
0501 public:
0502 static Attribute::AttrKind getExtAttrForI32Param(const Triple &T,
0503 bool Signed = true) {
0504 bool ShouldExtI32Param, ShouldExtI32Return;
0505 bool ShouldSignExtI32Param, ShouldSignExtI32Return;
0506 initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return,
0507 ShouldSignExtI32Param, ShouldSignExtI32Return, T);
0508 return getExtAttrForI32Param(ShouldExtI32Param, ShouldSignExtI32Param,
0509 Signed);
0510 }
0511
0512 Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
0513 return getExtAttrForI32Param(Impl->ShouldExtI32Param,
0514 Impl->ShouldSignExtI32Param, Signed);
0515 }
0516
0517
0518
0519
0520 private:
0521 static Attribute::AttrKind getExtAttrForI32Return(bool ShouldExtI32Return_,
0522 bool ShouldSignExtI32Return_,
0523 bool Signed) {
0524 if (ShouldExtI32Return_)
0525 return Signed ? Attribute::SExt : Attribute::ZExt;
0526 if (ShouldSignExtI32Return_)
0527 return Attribute::SExt;
0528 return Attribute::None;
0529 }
0530
0531 public:
0532 static Attribute::AttrKind getExtAttrForI32Return(const Triple &T,
0533 bool Signed = true) {
0534 bool ShouldExtI32Param, ShouldExtI32Return;
0535 bool ShouldSignExtI32Param, ShouldSignExtI32Return;
0536 initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return,
0537 ShouldSignExtI32Param, ShouldSignExtI32Return, T);
0538 return getExtAttrForI32Return(ShouldExtI32Return, ShouldSignExtI32Return,
0539 Signed);
0540 }
0541
0542 Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
0543 return getExtAttrForI32Return(Impl->ShouldExtI32Return,
0544 Impl->ShouldSignExtI32Return, Signed);
0545 }
0546
0547
0548
0549
0550 AttributeList getAttrList(LLVMContext *C, ArrayRef<unsigned> ArgNos,
0551 bool Signed, bool Ret = false,
0552 AttributeList AL = AttributeList()) const {
0553 if (auto AK = getExtAttrForI32Param(Signed))
0554 for (auto ArgNo : ArgNos)
0555 AL = AL.addParamAttribute(*C, ArgNo, AK);
0556 if (Ret)
0557 if (auto AK = getExtAttrForI32Return(Signed))
0558 AL = AL.addRetAttribute(*C, AK);
0559 return AL;
0560 }
0561
0562
0563 unsigned getWCharSize(const Module &M) const {
0564 return Impl->getWCharSize(M);
0565 }
0566
0567
0568 unsigned getSizeTSize(const Module &M) const { return Impl->getSizeTSize(M); }
0569
0570
0571 IntegerType *getSizeTType(const Module &M) const {
0572 return IntegerType::get(M.getContext(), getSizeTSize(M));
0573 }
0574
0575
0576 ConstantInt *getAsSizeT(uint64_t V, const Module &M) const {
0577 return ConstantInt::get(getSizeTType(M), V);
0578 }
0579
0580
0581 unsigned getIntSize() const {
0582 return Impl->getIntSize();
0583 }
0584
0585
0586
0587
0588
0589 bool invalidate(Module &, const PreservedAnalyses &,
0590 ModuleAnalysisManager::Invalidator &) {
0591 return false;
0592 }
0593 bool invalidate(Function &, const PreservedAnalyses &,
0594 FunctionAnalysisManager::Invalidator &) {
0595 return false;
0596 }
0597
0598
0599 void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
0600 ElementCount &ScalableVF) const {
0601 Impl->getWidestVF(ScalarF, FixedVF, ScalableVF);
0602 }
0603
0604
0605 bool isKnownVectorFunctionInLibrary(StringRef F) const {
0606 return this->isFunctionVectorizable(F);
0607 }
0608 };
0609
0610
0611
0612
0613
0614 class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
0615 public:
0616 typedef TargetLibraryInfo Result;
0617
0618
0619
0620
0621
0622 TargetLibraryAnalysis() = default;
0623
0624
0625
0626
0627 TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl)
0628 : BaselineInfoImpl(std::move(BaselineInfoImpl)) {}
0629
0630 TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &);
0631
0632 private:
0633 friend AnalysisInfoMixin<TargetLibraryAnalysis>;
0634 static AnalysisKey Key;
0635
0636 std::optional<TargetLibraryInfoImpl> BaselineInfoImpl;
0637 };
0638
0639 class TargetLibraryInfoWrapperPass : public ImmutablePass {
0640 TargetLibraryAnalysis TLA;
0641 std::optional<TargetLibraryInfo> TLI;
0642
0643 virtual void anchor();
0644
0645 public:
0646 static char ID;
0647 TargetLibraryInfoWrapperPass();
0648 explicit TargetLibraryInfoWrapperPass(const Triple &T);
0649 explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
0650
0651
0652
0653 explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfo &TLI);
0654
0655 TargetLibraryInfo &getTLI(const Function &F) {
0656 FunctionAnalysisManager DummyFAM;
0657 TLI = TLA.run(F, DummyFAM);
0658 return *TLI;
0659 }
0660 };
0661
0662 }
0663
0664 #endif