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/ADT/Optional.h"
15 #include "llvm/ADT/Triple.h"
16 #include "llvm/IR/CallSite.h"
17 #include "llvm/IR/Function.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/IR/PassManager.h"
20 #include "llvm/Pass.h"
21 
22 namespace llvm {
23 template <typename T> class ArrayRef;
24 
25 /// Describes a possible vectorization of a function.
26 /// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
27 /// by a factor 'VectorizationFactor'.
28 struct VecDesc {
29   StringRef ScalarFnName;
30   StringRef VectorFnName;
31   unsigned VectorizationFactor;
32 };
33 
34   enum LibFunc : unsigned {
35 #define TLI_DEFINE_ENUM
36 #include "llvm/Analysis/TargetLibraryInfo.def"
37 
38     NumLibFuncs,
39     NotLibFunc
40   };
41 
42 /// Implementation of the target library information.
43 ///
44 /// This class constructs tables that hold the target library information and
45 /// make it available. However, it is somewhat expensive to compute and only
46 /// depends on the triple. So users typically interact with the \c
47 /// TargetLibraryInfo wrapper below.
48 class TargetLibraryInfoImpl {
49   friend class TargetLibraryInfo;
50 
51   unsigned char AvailableArray[(NumLibFuncs+3)/4];
52   llvm::DenseMap<unsigned, std::string> CustomNames;
53   static StringLiteral const StandardNames[NumLibFuncs];
54   bool ShouldExtI32Param, ShouldExtI32Return, ShouldSignExtI32Param;
55 
56   enum AvailabilityState {
57     StandardName = 3, // (memset to all ones)
58     CustomName = 1,
59     Unavailable = 0  // (memset to all zeros)
60   };
61   void setState(LibFunc F, AvailabilityState State) {
62     AvailableArray[F/4] &= ~(3 << 2*(F&3));
63     AvailableArray[F/4] |= State << 2*(F&3);
64   }
65   AvailabilityState getState(LibFunc F) const {
66     return static_cast<AvailabilityState>((AvailableArray[F/4] >> 2*(F&3)) & 3);
67   }
68 
69   /// Vectorization descriptors - sorted by ScalarFnName.
70   std::vector<VecDesc> VectorDescs;
71   /// Scalarization descriptors - same content as VectorDescs but sorted based
72   /// on VectorFnName rather than ScalarFnName.
73   std::vector<VecDesc> ScalarDescs;
74 
75   /// Return true if the function type FTy is valid for the library function
76   /// F, regardless of whether the function is available.
77   bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F,
78                               const DataLayout *DL) const;
79 
80 public:
81   /// List of known vector-functions libraries.
82   ///
83   /// The vector-functions library defines, which functions are vectorizable
84   /// and with which factor. The library can be specified by either frontend,
85   /// or a commandline option, and then used by
86   /// addVectorizableFunctionsFromVecLib for filling up the tables of
87   /// vectorizable functions.
88   enum VectorLibrary {
89     NoLibrary,  // Don't use any vector library.
90     Accelerate, // Use Accelerate framework.
91     MASSV,      // IBM MASS vector library.
92     SVML        // Intel short vector math library.
93   };
94 
95   TargetLibraryInfoImpl();
96   explicit TargetLibraryInfoImpl(const Triple &T);
97 
98   // Provide value semantics.
99   TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
100   TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
101   TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
102   TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
103 
104   /// Searches for a particular function name.
105   ///
106   /// If it is one of the known library functions, return true and set F to the
107   /// corresponding value.
108   bool getLibFunc(StringRef funcName, LibFunc &F) const;
109 
110   /// Searches for a particular function name, also checking that its type is
111   /// valid for the library function matching that name.
112   ///
113   /// If it is one of the known library functions, return true and set F to the
114   /// corresponding value.
115   bool getLibFunc(const Function &FDecl, LibFunc &F) const;
116 
117   /// Forces a function to be marked as unavailable.
118   void setUnavailable(LibFunc F) {
119     setState(F, Unavailable);
120   }
121 
122   /// Forces a function to be marked as available.
123   void setAvailable(LibFunc F) {
124     setState(F, StandardName);
125   }
126 
127   /// Forces a function to be marked as available and provide an alternate name
128   /// that must be used.
129   void setAvailableWithName(LibFunc F, StringRef Name) {
130     if (StandardNames[F] != Name) {
131       setState(F, CustomName);
132       CustomNames[F] = Name;
133       assert(CustomNames.find(F) != CustomNames.end());
134     } else {
135       setState(F, StandardName);
136     }
137   }
138 
139   /// Disables all builtins.
140   ///
141   /// This can be used for options like -fno-builtin.
142   void disableAllFunctions();
143 
144   /// Add a set of scalar -> vector mappings, queryable via
145   /// getVectorizedFunction and getScalarizedFunction.
146   void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
147 
148   /// Calls addVectorizableFunctions with a known preset of functions for the
149   /// given vector library.
150   void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
151 
152   /// Return true if the function F has a vector equivalent with vectorization
153   /// factor VF.
154   bool isFunctionVectorizable(StringRef F, unsigned VF) const {
155     return !getVectorizedFunction(F, VF).empty();
156   }
157 
158   /// Return true if the function F has a vector equivalent with any
159   /// vectorization factor.
160   bool isFunctionVectorizable(StringRef F) const;
161 
162   /// Return the name of the equivalent of F, vectorized with factor VF. If no
163   /// such mapping exists, return the empty string.
164   StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
165 
166   /// Return true if the function F has a scalar equivalent, and set VF to be
167   /// the vectorization factor.
168   bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
169     return !getScalarizedFunction(F, VF).empty();
170   }
171 
172   /// Return the name of the equivalent of F, scalarized. If no such mapping
173   /// exists, return the empty string.
174   ///
175   /// Set VF to the vectorization factor.
176   StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
177 
178   /// Set to true iff i32 parameters to library functions should have signext
179   /// or zeroext attributes if they correspond to C-level int or unsigned int,
180   /// respectively.
181   void setShouldExtI32Param(bool Val) {
182     ShouldExtI32Param = Val;
183   }
184 
185   /// Set to true iff i32 results from library functions should have signext
186   /// or zeroext attributes if they correspond to C-level int or unsigned int,
187   /// respectively.
188   void setShouldExtI32Return(bool Val) {
189     ShouldExtI32Return = Val;
190   }
191 
192   /// Set to true iff i32 parameters to library functions should have signext
193   /// attribute if they correspond to C-level int or unsigned int.
194   void setShouldSignExtI32Param(bool Val) {
195     ShouldSignExtI32Param = Val;
196   }
197 
198   /// Returns the size of the wchar_t type in bytes or 0 if the size is unknown.
199   /// This queries the 'wchar_size' metadata.
200   unsigned getWCharSize(const Module &M) const;
201 
202   /// Returns the largest vectorization factor used in the list of
203   /// vector functions.
204   unsigned getWidestVF(StringRef ScalarF) const;
205 };
206 
207 /// Provides information about what library functions are available for
208 /// the current target.
209 ///
210 /// This both allows optimizations to handle them specially and frontends to
211 /// disable such optimizations through -fno-builtin etc.
212 class TargetLibraryInfo {
213   friend class TargetLibraryAnalysis;
214   friend class TargetLibraryInfoWrapperPass;
215 
216   /// The global (module level) TLI info.
217   const TargetLibraryInfoImpl *Impl;
218 
219   /// Support for -fno-builtin* options as function attributes, overrides
220   /// information in global TargetLibraryInfoImpl.
221   BitVector OverrideAsUnavailable;
222 
223 public:
224   explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
225                              Optional<const Function *> F = None)
226       : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) {
227     if (!F)
228       return;
229     if ((*F)->hasFnAttribute("no-builtins"))
230       disableAllFunctions();
231     else {
232       // Disable individual libc/libm calls in TargetLibraryInfo.
233       LibFunc LF;
234       AttributeSet FnAttrs = (*F)->getAttributes().getFnAttributes();
235       for (const Attribute &Attr : FnAttrs) {
236         if (!Attr.isStringAttribute())
237           continue;
238         auto AttrStr = Attr.getKindAsString();
239         if (!AttrStr.consume_front("no-builtin-"))
240           continue;
241         if (getLibFunc(AttrStr, LF))
242           setUnavailable(LF);
243       }
244     }
245   }
246 
247   // Provide value semantics.
248   TargetLibraryInfo(const TargetLibraryInfo &TLI)
249       : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
250   TargetLibraryInfo(TargetLibraryInfo &&TLI)
251       : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
252   TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) {
253     Impl = TLI.Impl;
254     OverrideAsUnavailable = TLI.OverrideAsUnavailable;
255     return *this;
256   }
257   TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
258     Impl = TLI.Impl;
259     OverrideAsUnavailable = TLI.OverrideAsUnavailable;
260     return *this;
261   }
262 
263   /// Searches for a particular function name.
264   ///
265   /// If it is one of the known library functions, return true and set F to the
266   /// corresponding value.
267   bool getLibFunc(StringRef funcName, LibFunc &F) const {
268     return Impl->getLibFunc(funcName, F);
269   }
270 
271   bool getLibFunc(const Function &FDecl, LibFunc &F) const {
272     return Impl->getLibFunc(FDecl, F);
273   }
274 
275   /// If a callsite does not have the 'nobuiltin' attribute, return if the
276   /// called function is a known library function and set F to that function.
277   bool getLibFunc(ImmutableCallSite CS, LibFunc &F) const {
278     return !CS.isNoBuiltin() && CS.getCalledFunction() &&
279            getLibFunc(*(CS.getCalledFunction()), F);
280   }
281 
282   /// Disables all builtins.
283   ///
284   /// This can be used for options like -fno-builtin.
285   void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED {
286     OverrideAsUnavailable.set();
287   }
288 
289   /// Forces a function to be marked as unavailable.
290   void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED {
291     OverrideAsUnavailable.set(F);
292   }
293 
294   TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const {
295     if (OverrideAsUnavailable[F])
296       return TargetLibraryInfoImpl::Unavailable;
297     return Impl->getState(F);
298   }
299 
300   /// Tests whether a library function is available.
301   bool has(LibFunc F) const {
302     return getState(F) != TargetLibraryInfoImpl::Unavailable;
303   }
304   bool isFunctionVectorizable(StringRef F, unsigned VF) const {
305     return Impl->isFunctionVectorizable(F, VF);
306   }
307   bool isFunctionVectorizable(StringRef F) const {
308     return Impl->isFunctionVectorizable(F);
309   }
310   StringRef getVectorizedFunction(StringRef F, unsigned VF) const {
311     return Impl->getVectorizedFunction(F, VF);
312   }
313 
314   /// Tests if the function is both available and a candidate for optimized code
315   /// generation.
316   bool hasOptimizedCodeGen(LibFunc F) const {
317     if (getState(F) == TargetLibraryInfoImpl::Unavailable)
318       return false;
319     switch (F) {
320     default: break;
321     case LibFunc_copysign:     case LibFunc_copysignf:  case LibFunc_copysignl:
322     case LibFunc_fabs:         case LibFunc_fabsf:      case LibFunc_fabsl:
323     case LibFunc_sin:          case LibFunc_sinf:       case LibFunc_sinl:
324     case LibFunc_cos:          case LibFunc_cosf:       case LibFunc_cosl:
325     case LibFunc_sqrt:         case LibFunc_sqrtf:      case LibFunc_sqrtl:
326     case LibFunc_sqrt_finite:  case LibFunc_sqrtf_finite:
327                                                    case LibFunc_sqrtl_finite:
328     case LibFunc_fmax:         case LibFunc_fmaxf:      case LibFunc_fmaxl:
329     case LibFunc_fmin:         case LibFunc_fminf:      case LibFunc_fminl:
330     case LibFunc_floor:        case LibFunc_floorf:     case LibFunc_floorl:
331     case LibFunc_nearbyint:    case LibFunc_nearbyintf: case LibFunc_nearbyintl:
332     case LibFunc_ceil:         case LibFunc_ceilf:      case LibFunc_ceill:
333     case LibFunc_rint:         case LibFunc_rintf:      case LibFunc_rintl:
334     case LibFunc_round:        case LibFunc_roundf:     case LibFunc_roundl:
335     case LibFunc_trunc:        case LibFunc_truncf:     case LibFunc_truncl:
336     case LibFunc_log2:         case LibFunc_log2f:      case LibFunc_log2l:
337     case LibFunc_exp2:         case LibFunc_exp2f:      case LibFunc_exp2l:
338     case LibFunc_memcmp:       case LibFunc_bcmp:       case LibFunc_strcmp:
339     case LibFunc_strcpy:       case LibFunc_stpcpy:     case LibFunc_strlen:
340     case LibFunc_strnlen:      case LibFunc_memchr:     case LibFunc_mempcpy:
341       return true;
342     }
343     return false;
344   }
345 
346   StringRef getName(LibFunc F) const {
347     auto State = getState(F);
348     if (State == TargetLibraryInfoImpl::Unavailable)
349       return StringRef();
350     if (State == TargetLibraryInfoImpl::StandardName)
351       return Impl->StandardNames[F];
352     assert(State == TargetLibraryInfoImpl::CustomName);
353     return Impl->CustomNames.find(F)->second;
354   }
355 
356   /// Returns extension attribute kind to be used for i32 parameters
357   /// corresponding to C-level int or unsigned int.  May be zeroext, signext,
358   /// or none.
359   Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
360     if (Impl->ShouldExtI32Param)
361       return Signed ? Attribute::SExt : Attribute::ZExt;
362     if (Impl->ShouldSignExtI32Param)
363       return Attribute::SExt;
364     return Attribute::None;
365   }
366 
367   /// Returns extension attribute kind to be used for i32 return values
368   /// corresponding to C-level int or unsigned int.  May be zeroext, signext,
369   /// or none.
370   Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
371     if (Impl->ShouldExtI32Return)
372       return Signed ? Attribute::SExt : Attribute::ZExt;
373     return Attribute::None;
374   }
375 
376   /// \copydoc TargetLibraryInfoImpl::getWCharSize()
377   unsigned getWCharSize(const Module &M) const {
378     return Impl->getWCharSize(M);
379   }
380 
381   /// Handle invalidation from the pass manager.
382   ///
383   /// If we try to invalidate this info, just return false. It cannot become
384   /// invalid even if the module or function changes.
385   bool invalidate(Module &, const PreservedAnalyses &,
386                   ModuleAnalysisManager::Invalidator &) {
387     return false;
388   }
389   bool invalidate(Function &, const PreservedAnalyses &,
390                   FunctionAnalysisManager::Invalidator &) {
391     return false;
392   }
393 
394   /// Returns the largest vectorization factor used in the list of
395   /// vector functions.
396   unsigned getWidestVF(StringRef ScalarF) const {
397     return Impl->getWidestVF(ScalarF);
398   }
399 };
400 
401 /// Analysis pass providing the \c TargetLibraryInfo.
402 ///
403 /// Note that this pass's result cannot be invalidated, it is immutable for the
404 /// life of the module.
405 class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
406 public:
407   typedef TargetLibraryInfo Result;
408 
409   /// Default construct the library analysis.
410   ///
411   /// This will use the module's triple to construct the library info for that
412   /// module.
413   TargetLibraryAnalysis() {}
414 
415   /// Construct a library analysis with baseline Module-level info.
416   ///
417   /// This will be supplemented with Function-specific info in the Result.
418   TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl)
419       : BaselineInfoImpl(std::move(BaselineInfoImpl)) {}
420 
421   TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &);
422 
423 private:
424   friend AnalysisInfoMixin<TargetLibraryAnalysis>;
425   static AnalysisKey Key;
426 
427   Optional<TargetLibraryInfoImpl> BaselineInfoImpl;
428 };
429 
430 class TargetLibraryInfoWrapperPass : public ImmutablePass {
431   TargetLibraryAnalysis TLA;
432   Optional<TargetLibraryInfo> TLI;
433 
434   virtual void anchor();
435 
436 public:
437   static char ID;
438   TargetLibraryInfoWrapperPass();
439   explicit TargetLibraryInfoWrapperPass(const Triple &T);
440   explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
441 
442   TargetLibraryInfo &getTLI(const Function &F) {
443     FunctionAnalysisManager DummyFAM;
444     TLI = TLA.run(F, DummyFAM);
445     return *TLI;
446   }
447 };
448 
449 } // end namespace llvm
450 
451 #endif
452