1 //===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H
10 #define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
11 
12 #include "llvm/ADT/BitVector.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/IR/InstrTypes.h"
15 #include "llvm/IR/PassManager.h"
16 #include "llvm/Pass.h"
17 #include "llvm/TargetParser/Triple.h"
18 #include <optional>
19 
20 namespace llvm {
21 
22 template <typename T> class ArrayRef;
23 class Function;
24 class Module;
25 class Triple;
26 
27 /// Describes a possible vectorization of a function.
28 /// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
29 /// by a factor 'VectorizationFactor'.
30 struct VecDesc {
31   StringRef ScalarFnName;
32   StringRef VectorFnName;
33   ElementCount VectorizationFactor;
34   bool Masked;
35 };
36 
37   enum LibFunc : unsigned {
38 #define TLI_DEFINE_ENUM
39 #include "llvm/Analysis/TargetLibraryInfo.def"
40 
41     NumLibFuncs,
42     NotLibFunc
43   };
44 
45 /// Implementation of the target library information.
46 ///
47 /// This class constructs tables that hold the target library information and
48 /// make it available. However, it is somewhat expensive to compute and only
49 /// depends on the triple. So users typically interact with the \c
50 /// TargetLibraryInfo wrapper below.
51 class TargetLibraryInfoImpl {
52   friend class TargetLibraryInfo;
53 
54   unsigned char AvailableArray[(NumLibFuncs+3)/4];
55   DenseMap<unsigned, std::string> CustomNames;
56   static StringLiteral const StandardNames[NumLibFuncs];
57   bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param, ShouldSignExtI32Return;
58   unsigned SizeOfInt;
59 
60   enum AvailabilityState {
61     StandardName = 3, // (memset to all ones)
62     CustomName = 1,
63     Unavailable = 0  // (memset to all zeros)
64   };
65   void setState(LibFunc F, AvailabilityState State) {
66     AvailableArray[F/4] &= ~(3 << 2*(F&3));
67     AvailableArray[F/4] |= State << 2*(F&3);
68   }
69   AvailabilityState getState(LibFunc F) const {
70     return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
71   }
72 
73   /// Vectorization descriptors - sorted by ScalarFnName.
74   std::vector<VecDesc> VectorDescs;
75   /// Scalarization descriptors - same content as VectorDescs but sorted based
76   /// on VectorFnName rather than ScalarFnName.
77   std::vector<VecDesc> ScalarDescs;
78 
79   /// Return true if the function type FTy is valid for the library function
80   /// F, regardless of whether the function is available.
81   bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
82                               const Module &M) const;
83 
84 public:
85   /// List of known vector-functions libraries.
86   ///
87   /// The vector-functions library defines, which functions are vectorizable
88   /// and with which factor. The library can be specified by either frontend,
89   /// or a commandline option, and then used by
90   /// addVectorizableFunctionsFromVecLib for filling up the tables of
91   /// vectorizable functions.
92   enum VectorLibrary {
93     NoLibrary,        // Don't use any vector library.
94     Accelerate,       // Use Accelerate framework.
95     DarwinLibSystemM, // Use Darwin's libsystem_m.
96     LIBMVEC_X86,      // GLIBC Vector Math library.
97     MASSV,            // IBM MASS vector library.
98     SVML,             // Intel short vector math library.
99     SLEEFGNUABI, // SLEEF - SIMD Library for Evaluating Elementary Functions.
100     ArmPL        // Arm Performance Libraries.
101   };
102 
103   TargetLibraryInfoImpl();
104   explicit TargetLibraryInfoImpl(const Triple &T);
105 
106   // Provide value semantics.
107   TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
108   TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
109   TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
110   TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
111 
112   /// Searches for a particular function name.
113   ///
114   /// If it is one of the known library functions, return true and set F to the
115   /// corresponding value.
116   bool getLibFunc(StringRef funcName, LibFunc &F) const;
117 
118   /// Searches for a particular function name, also checking that its type is
119   /// valid for the library function matching that name.
120   ///
121   /// If it is one of the known library functions, return true and set F to the
122   /// corresponding value.
123   ///
124   /// FDecl is assumed to have a parent Module when using this function.
125   bool getLibFunc(const Function &FDecl, LibFunc &F) const;
126 
127   /// Forces a function to be marked as unavailable.
128   void setUnavailable(LibFunc F) {
129     setState(F, Unavailable);
130   }
131 
132   /// Forces a function to be marked as available.
133   void setAvailable(LibFunc F) {
134     setState(F, StandardName);
135   }
136 
137   /// Forces a function to be marked as available and provide an alternate name
138   /// that must be used.
139   void setAvailableWithName(LibFunc F, StringRef Name) {
140     if (StandardNames[F] != Name) {
141       setState(F, CustomName);
142       CustomNames[F] = std::string(Name);
143       assert(CustomNames.contains(F));
144     } else {
145       setState(F, StandardName);
146     }
147   }
148 
149   /// Disables all builtins.
150   ///
151   /// This can be used for options like -fno-builtin.
152   void disableAllFunctions();
153 
154   /// Add a set of scalar -> vector mappings, queryable via
155   /// getVectorizedFunction and getScalarizedFunction.
156   void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
157 
158   /// Calls addVectorizableFunctions with a known preset of functions for the
159   /// given vector library.
160   void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib,
161                                           const llvm::Triple &TargetTriple);
162 
163   /// Return true if the function F has a vector equivalent with vectorization
164   /// factor VF.
165   bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
166     return !(getVectorizedFunction(F, VF, false).empty() &&
167              getVectorizedFunction(F, VF, true).empty());
168   }
169 
170   /// Return true if the function F has a vector equivalent with any
171   /// vectorization factor.
172   bool isFunctionVectorizable(StringRef F) const;
173 
174   /// Return the name of the equivalent of F, vectorized with factor VF. If no
175   /// such mapping exists, return the empty string.
176   StringRef getVectorizedFunction(StringRef F, const ElementCount &VF,
177                                   bool Masked) const;
178 
179   /// Set to true iff i32 parameters to library functions should have signext
180   /// or zeroext attributes if they correspond to C-level int or unsigned int,
181   /// respectively.
182   void setShouldExtI32Param(bool Val) {
183     ShouldExtI32Param = Val;
184   }
185 
186   /// Set to true iff i32 results from library functions should have signext
187   /// or zeroext attributes if they correspond to C-level int or unsigned int,
188   /// respectively.
189   void setShouldExtI32Return(bool Val) {
190     ShouldExtI32Return = Val;
191   }
192 
193   /// Set to true iff i32 parameters to library functions should have signext
194   /// attribute if they correspond to C-level int or unsigned int.
195   void setShouldSignExtI32Param(bool Val) {
196     ShouldSignExtI32Param = Val;
197   }
198 
199   /// Set to true iff i32 results from library functions should have signext
200   /// attribute if they correspond to C-level int or unsigned int.
201   void setShouldSignExtI32Return(bool Val) {
202     ShouldSignExtI32Return = Val;
203   }
204 
205   /// Returns the size of the wchar_t type in bytes or 0 if the size is unknown.
206   /// This queries the 'wchar_size' metadata.
207   unsigned getWCharSize(const Module &M) const;
208 
209   /// Returns the size of the size_t type in bits.
210   unsigned getSizeTSize(const Module &M) const;
211 
212   /// Get size of a C-level int or unsigned int, in bits.
213   unsigned getIntSize() const {
214     return SizeOfInt;
215   }
216 
217   /// Initialize the C-level size of an integer.
218   void setIntSize(unsigned Bits) {
219     SizeOfInt = Bits;
220   }
221 
222   /// Returns the largest vectorization factor used in the list of
223   /// vector functions.
224   void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
225                    ElementCount &Scalable) const;
226 
227   /// Returns true if call site / callee has cdecl-compatible calling
228   /// conventions.
229   static bool isCallingConvCCompatible(CallBase *CI);
230   static bool isCallingConvCCompatible(Function *Callee);
231 };
232 
233 /// Provides information about what library functions are available for
234 /// the current target.
235 ///
236 /// This both allows optimizations to handle them specially and frontends to
237 /// disable such optimizations through -fno-builtin etc.
238 class TargetLibraryInfo {
239   friend class TargetLibraryAnalysis;
240   friend class TargetLibraryInfoWrapperPass;
241 
242   /// The global (module level) TLI info.
243   const TargetLibraryInfoImpl *Impl;
244 
245   /// Support for -fno-builtin* options as function attributes, overrides
246   /// information in global TargetLibraryInfoImpl.
247   BitVector OverrideAsUnavailable;
248 
249 public:
250   explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
251                              std::optional<const Function *> F = std::nullopt)
252       : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) {
253     if (!F)
254       return;
255     if ((*F)->hasFnAttribute("no-builtins"))
256       disableAllFunctions();
257     else {
258       // Disable individual libc/libm calls in TargetLibraryInfo.
259       LibFunc LF;
260       AttributeSet FnAttrs = (*F)->getAttributes().getFnAttrs();
261       for (const Attribute &Attr : FnAttrs) {
262         if (!Attr.isStringAttribute())
263           continue;
264         auto AttrStr = Attr.getKindAsString();
265         if (!AttrStr.consume_front("no-builtin-"))
266           continue;
267         if (getLibFunc(AttrStr, LF))
268           setUnavailable(LF);
269       }
270     }
271   }
272 
273   // Provide value semantics.
274   TargetLibraryInfo(const TargetLibraryInfo &TLI) = default;
275   TargetLibraryInfo(TargetLibraryInfo &&TLI)
276       : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
277   TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) = default;
278   TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
279     Impl = TLI.Impl;
280     OverrideAsUnavailable = TLI.OverrideAsUnavailable;
281     return *this;
282   }
283 
284   /// Determine whether a callee with the given TLI can be inlined into
285   /// caller with this TLI, based on 'nobuiltin' attributes. When requested,
286   /// allow inlining into a caller with a superset of the callee's nobuiltin
287   /// attributes, which is conservatively correct.
288   bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI,
289                            bool AllowCallerSuperset) const {
290     if (!AllowCallerSuperset)
291       return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
292     BitVector B = OverrideAsUnavailable;
293     B |= CalleeTLI.OverrideAsUnavailable;
294     // We can inline if the union of the caller and callee's nobuiltin
295     // attributes is no stricter than the caller's nobuiltin attributes.
296     return B == OverrideAsUnavailable;
297   }
298 
299   /// Return true if the function type FTy is valid for the library function
300   /// F, regardless of whether the function is available.
301   bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
302                               const Module &M) const {
303     return Impl->isValidProtoForLibFunc(FTy, F, M);
304   }
305 
306   /// Searches for a particular function name.
307   ///
308   /// If it is one of the known library functions, return true and set F to the
309   /// corresponding value.
310   bool getLibFunc(StringRef funcName, LibFunc &F) const {
311     return Impl->getLibFunc(funcName, F);
312   }
313 
314   bool getLibFunc(const Function &FDecl, LibFunc &F) const {
315     return Impl->getLibFunc(FDecl, F);
316   }
317 
318   /// If a callbase does not have the 'nobuiltin' attribute, return if the
319   /// called function is a known library function and set F to that function.
320   bool getLibFunc(const CallBase &CB, LibFunc &F) const {
321     return !CB.isNoBuiltin() && CB.getCalledFunction() &&
322            getLibFunc(*(CB.getCalledFunction()), F);
323   }
324 
325   /// Disables all builtins.
326   ///
327   /// This can be used for options like -fno-builtin.
328   void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED {
329     OverrideAsUnavailable.set();
330   }
331 
332   /// Forces a function to be marked as unavailable.
333   void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED {
334     OverrideAsUnavailable.set(F);
335   }
336 
337   TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const {
338     if (OverrideAsUnavailable[F])
339       return TargetLibraryInfoImpl::Unavailable;
340     return Impl->getState(F);
341   }
342 
343   /// Tests whether a library function is available.
344   bool has(LibFunc F) const {
345     return getState(F) != TargetLibraryInfoImpl::Unavailable;
346   }
347   bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const {
348     return Impl->isFunctionVectorizable(F, VF);
349   }
350   bool isFunctionVectorizable(StringRef F) const {
351     return Impl->isFunctionVectorizable(F);
352   }
353   StringRef getVectorizedFunction(StringRef F, const ElementCount &VF,
354                                   bool Masked = false) const {
355     return Impl->getVectorizedFunction(F, VF, Masked);
356   }
357 
358   /// Tests if the function is both available and a candidate for optimized code
359   /// generation.
360   bool hasOptimizedCodeGen(LibFunc F) const {
361     if (getState(F) == TargetLibraryInfoImpl::Unavailable)
362       return false;
363     switch (F) {
364     default: break;
365     case LibFunc_copysign:     case LibFunc_copysignf:  case LibFunc_copysignl:
366     case LibFunc_fabs:         case LibFunc_fabsf:      case LibFunc_fabsl:
367     case LibFunc_sin:          case LibFunc_sinf:       case LibFunc_sinl:
368     case LibFunc_cos:          case LibFunc_cosf:       case LibFunc_cosl:
369     case LibFunc_sqrt:         case LibFunc_sqrtf:      case LibFunc_sqrtl:
370     case LibFunc_sqrt_finite:  case LibFunc_sqrtf_finite:
371                                                    case LibFunc_sqrtl_finite:
372     case LibFunc_fmax:         case LibFunc_fmaxf:      case LibFunc_fmaxl:
373     case LibFunc_fmin:         case LibFunc_fminf:      case LibFunc_fminl:
374     case LibFunc_floor:        case LibFunc_floorf:     case LibFunc_floorl:
375     case LibFunc_nearbyint:    case LibFunc_nearbyintf: case LibFunc_nearbyintl:
376     case LibFunc_ceil:         case LibFunc_ceilf:      case LibFunc_ceill:
377     case LibFunc_rint:         case LibFunc_rintf:      case LibFunc_rintl:
378     case LibFunc_round:        case LibFunc_roundf:     case LibFunc_roundl:
379     case LibFunc_trunc:        case LibFunc_truncf:     case LibFunc_truncl:
380     case LibFunc_log2:         case LibFunc_log2f:      case LibFunc_log2l:
381     case LibFunc_exp2:         case LibFunc_exp2f:      case LibFunc_exp2l:
382     case LibFunc_ldexp:        case LibFunc_ldexpf:     case LibFunc_ldexpl:
383     case LibFunc_memcpy:       case LibFunc_memset:     case LibFunc_memmove:
384     case LibFunc_memcmp:       case LibFunc_bcmp:       case LibFunc_strcmp:
385     case LibFunc_strcpy:       case LibFunc_stpcpy:     case LibFunc_strlen:
386     case LibFunc_strnlen:      case LibFunc_memchr:     case LibFunc_mempcpy:
387       return true;
388     }
389     return false;
390   }
391 
392   StringRef getName(LibFunc F) const {
393     auto State = getState(F);
394     if (State == TargetLibraryInfoImpl::Unavailable)
395       return StringRef();
396     if (State == TargetLibraryInfoImpl::StandardName)
397       return Impl->StandardNames[F];
398     assert(State == TargetLibraryInfoImpl::CustomName);
399     return Impl->CustomNames.find(F)->second;
400   }
401 
402   static void initExtensionsForTriple(bool &ShouldExtI32Param,
403                                       bool &ShouldExtI32Return,
404                                       bool &ShouldSignExtI32Param,
405                                       bool &ShouldSignExtI32Return,
406                                       const Triple &T) {
407     ShouldExtI32Param     = ShouldExtI32Return     = false;
408     ShouldSignExtI32Param = ShouldSignExtI32Return = false;
409 
410     // PowerPC64, Sparc64, SystemZ need signext/zeroext on i32 parameters and
411     // returns corresponding to C-level ints and unsigned ints.
412     if (T.isPPC64() || T.getArch() == Triple::sparcv9 ||
413         T.getArch() == Triple::systemz) {
414       ShouldExtI32Param = true;
415       ShouldExtI32Return = true;
416     }
417     // LoongArch, Mips, and riscv64, on the other hand, need signext on i32
418     // parameters corresponding to both signed and unsigned ints.
419     if (T.isLoongArch() || T.isMIPS() || T.isRISCV64()) {
420       ShouldSignExtI32Param = true;
421     }
422     // LoongArch and riscv64 need signext on i32 returns corresponding to both
423     // signed and unsigned ints.
424     if (T.isLoongArch() || T.isRISCV64()) {
425       ShouldSignExtI32Return = true;
426     }
427   }
428 
429   /// Returns extension attribute kind to be used for i32 parameters
430   /// corresponding to C-level int or unsigned int.  May be zeroext, signext,
431   /// or none.
432 private:
433   static Attribute::AttrKind getExtAttrForI32Param(bool ShouldExtI32Param_,
434                                                    bool ShouldSignExtI32Param_,
435                                                    bool Signed = true) {
436     if (ShouldExtI32Param_)
437       return Signed ? Attribute::SExt : Attribute::ZExt;
438     if (ShouldSignExtI32Param_)
439       return Attribute::SExt;
440     return Attribute::None;
441   }
442 
443 public:
444   static Attribute::AttrKind getExtAttrForI32Param(const Triple &T,
445                                                    bool Signed = true) {
446     bool ShouldExtI32Param, ShouldExtI32Return;
447     bool ShouldSignExtI32Param, ShouldSignExtI32Return;
448     initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return,
449                             ShouldSignExtI32Param, ShouldSignExtI32Return, T);
450     return getExtAttrForI32Param(ShouldExtI32Param, ShouldSignExtI32Param,
451                                  Signed);
452   }
453 
454   Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
455     return getExtAttrForI32Param(Impl->ShouldExtI32Param,
456                                  Impl->ShouldSignExtI32Param, Signed);
457   }
458 
459   /// Returns extension attribute kind to be used for i32 return values
460   /// corresponding to C-level int or unsigned int.  May be zeroext, signext,
461   /// or none.
462 private:
463   static Attribute::AttrKind getExtAttrForI32Return(bool ShouldExtI32Return_,
464                                                     bool ShouldSignExtI32Return_,
465                                                     bool Signed) {
466     if (ShouldExtI32Return_)
467       return Signed ? Attribute::SExt : Attribute::ZExt;
468     if (ShouldSignExtI32Return_)
469       return Attribute::SExt;
470     return Attribute::None;
471   }
472 
473 public:
474   static Attribute::AttrKind getExtAttrForI32Return(const Triple &T,
475                                                    bool Signed = true) {
476     bool ShouldExtI32Param, ShouldExtI32Return;
477     bool ShouldSignExtI32Param, ShouldSignExtI32Return;
478     initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return,
479                             ShouldSignExtI32Param, ShouldSignExtI32Return, T);
480     return getExtAttrForI32Return(ShouldExtI32Return, ShouldSignExtI32Return,
481                                   Signed);
482   }
483 
484   Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
485     return getExtAttrForI32Return(Impl->ShouldExtI32Return,
486                                   Impl->ShouldSignExtI32Return, Signed);
487   }
488 
489   // Helper to create an AttributeList for args (and ret val) which all have
490   // the same signedness. Attributes in AL may be passed in to include them
491   // as well in the returned AttributeList.
492   AttributeList getAttrList(LLVMContext *C, ArrayRef<unsigned> ArgNos,
493                             bool Signed, bool Ret = false,
494                             AttributeList AL = AttributeList()) const {
495     if (auto AK = getExtAttrForI32Param(Signed))
496       for (auto ArgNo : ArgNos)
497         AL = AL.addParamAttribute(*C, ArgNo, AK);
498     if (Ret)
499       if (auto AK = getExtAttrForI32Return(Signed))
500         AL = AL.addRetAttribute(*C, AK);
501     return AL;
502   }
503 
504   /// \copydoc TargetLibraryInfoImpl::getWCharSize()
505   unsigned getWCharSize(const Module &M) const {
506     return Impl->getWCharSize(M);
507   }
508 
509   /// \copydoc TargetLibraryInfoImpl::getSizeTSize()
510   unsigned getSizeTSize(const Module &M) const { return Impl->getSizeTSize(M); }
511 
512   /// \copydoc TargetLibraryInfoImpl::getIntSize()
513   unsigned getIntSize() const {
514     return Impl->getIntSize();
515   }
516 
517   /// Handle invalidation from the pass manager.
518   ///
519   /// If we try to invalidate this info, just return false. It cannot become
520   /// invalid even if the module or function changes.
521   bool invalidate(Module &, const PreservedAnalyses &,
522                   ModuleAnalysisManager::Invalidator &) {
523     return false;
524   }
525   bool invalidate(Function &, const PreservedAnalyses &,
526                   FunctionAnalysisManager::Invalidator &) {
527     return false;
528   }
529   /// Returns the largest vectorization factor used in the list of
530   /// vector functions.
531   void getWidestVF(StringRef ScalarF, ElementCount &FixedVF,
532                    ElementCount &ScalableVF) const {
533     Impl->getWidestVF(ScalarF, FixedVF, ScalableVF);
534   }
535 
536   /// Check if the function "F" is listed in a library known to LLVM.
537   bool isKnownVectorFunctionInLibrary(StringRef F) const {
538     return this->isFunctionVectorizable(F);
539   }
540 };
541 
542 /// Analysis pass providing the \c TargetLibraryInfo.
543 ///
544 /// Note that this pass's result cannot be invalidated, it is immutable for the
545 /// life of the module.
546 class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
547 public:
548   typedef TargetLibraryInfo Result;
549 
550   /// Default construct the library analysis.
551   ///
552   /// This will use the module's triple to construct the library info for that
553   /// module.
554   TargetLibraryAnalysis() = default;
555 
556   /// Construct a library analysis with baseline Module-level info.
557   ///
558   /// This will be supplemented with Function-specific info in the Result.
559   TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl)
560       : BaselineInfoImpl(std::move(BaselineInfoImpl)) {}
561 
562   TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &);
563 
564 private:
565   friend AnalysisInfoMixin<TargetLibraryAnalysis>;
566   static AnalysisKey Key;
567 
568   std::optional<TargetLibraryInfoImpl> BaselineInfoImpl;
569 };
570 
571 class TargetLibraryInfoWrapperPass : public ImmutablePass {
572   TargetLibraryAnalysis TLA;
573   std::optional<TargetLibraryInfo> TLI;
574 
575   virtual void anchor();
576 
577 public:
578   static char ID;
579   TargetLibraryInfoWrapperPass();
580   explicit TargetLibraryInfoWrapperPass(const Triple &T);
581   explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
582 
583   TargetLibraryInfo &getTLI(const Function &F) {
584     FunctionAnalysisManager DummyFAM;
585     TLI = TLA.run(F, DummyFAM);
586     return *TLI;
587   }
588 };
589 
590 } // end namespace llvm
591 
592 #endif
593