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