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; |
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 | |
58 | StringRef getScalarFnName() const { return ScalarFnName; } |
59 | StringRef getVectorFnName() const { return VectorFnName; } |
60 | ElementCount getVectorizationFactor() const { return VectorizationFactor; } |
61 | bool isMasked() const { return Masked; } |
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 | }; |
97 | void setState(LibFunc F, AvailabilityState State) { |
98 | AvailableArray[F/4] &= ~(3 << 2*(F&3)); |
99 | AvailableArray[F/4] |= State << 2*(F&3); |
100 | } |
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. |
165 | void setUnavailable(LibFunc F) { |
166 | setState(F, State: Unavailable); |
167 | } |
168 | |
169 | /// Forces a function to be marked as available. |
170 | void setAvailable(LibFunc F) { |
171 | setState(F, State: StandardName); |
172 | } |
173 | |
174 | /// Forces a function to be marked as available and provide an alternate name |
175 | /// that must be used. |
176 | void setAvailableWithName(LibFunc F, StringRef Name) { |
177 | if (StandardNames[F] != Name) { |
178 | setState(F, State: CustomName); |
179 | CustomNames[F] = std::string(Name); |
180 | assert(CustomNames.contains(F)); |
181 | } else { |
182 | setState(F, State: 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. |
202 | bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const { |
203 | return !(getVectorizedFunction(F, VF, Masked: false).empty() && |
204 | getVectorizedFunction(F, VF, Masked: 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. |
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. |
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. |
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. |
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. |
256 | unsigned getIntSize() const { |
257 | return SizeOfInt; |
258 | } |
259 | |
260 | /// Initialize the C-level size of an integer. |
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(Kind: "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(Prefix: "no-builtin-" )) |
309 | continue; |
310 | if (getLibFunc(funcName: AttrStr, F&: LF)) |
311 | setUnavailable(LF); |
312 | } |
313 | } |
314 | } |
315 | |
316 | // Provide value semantics. |
317 | TargetLibraryInfo(const TargetLibraryInfo &TLI) = default; |
318 | TargetLibraryInfo(TargetLibraryInfo &&TLI) = default; |
319 | TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) = default; |
320 | TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) = default; |
321 | |
322 | /// Determine whether a callee with the given TLI can be inlined into |
323 | /// caller with this TLI, based on 'nobuiltin' attributes. When requested, |
324 | /// allow inlining into a caller with a superset of the callee's nobuiltin |
325 | /// attributes, which is conservatively correct. |
326 | bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI, |
327 | bool AllowCallerSuperset) const { |
328 | if (!AllowCallerSuperset) |
329 | return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable; |
330 | // We can inline if the callee's nobuiltin attributes are no stricter than |
331 | // the caller's. |
332 | return !CalleeTLI.OverrideAsUnavailable.test(RHS: OverrideAsUnavailable); |
333 | } |
334 | |
335 | /// Return true if the function type FTy is valid for the library function |
336 | /// F, regardless of whether the function is available. |
337 | bool isValidProtoForLibFunc(const FunctionType &FTy, LibFunc F, |
338 | const Module &M) const { |
339 | return Impl->isValidProtoForLibFunc(FTy, F, M); |
340 | } |
341 | |
342 | /// Searches for a particular function name. |
343 | /// |
344 | /// If it is one of the known library functions, return true and set F to the |
345 | /// corresponding value. |
346 | bool getLibFunc(StringRef funcName, LibFunc &F) const { |
347 | return Impl->getLibFunc(funcName, F); |
348 | } |
349 | |
350 | bool getLibFunc(const Function &FDecl, LibFunc &F) const { |
351 | return Impl->getLibFunc(FDecl, F); |
352 | } |
353 | |
354 | /// If a callbase does not have the 'nobuiltin' attribute, return if the |
355 | /// called function is a known library function and set F to that function. |
356 | bool getLibFunc(const CallBase &CB, LibFunc &F) const { |
357 | return !CB.isNoBuiltin() && CB.getCalledFunction() && |
358 | getLibFunc(FDecl: *(CB.getCalledFunction()), F); |
359 | } |
360 | |
361 | /// Searches for a function name using an Instruction \p Opcode. |
362 | /// Currently, only the frem instruction is supported. |
363 | bool getLibFunc(unsigned int Opcode, Type *Ty, LibFunc &F) const { |
364 | return Impl->getLibFunc(Opcode, Ty, F); |
365 | } |
366 | |
367 | /// Disables all builtins. |
368 | /// |
369 | /// This can be used for options like -fno-builtin. |
370 | void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED { |
371 | OverrideAsUnavailable.set(); |
372 | } |
373 | |
374 | /// Forces a function to be marked as unavailable. |
375 | void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED { |
376 | OverrideAsUnavailable.set(F); |
377 | } |
378 | |
379 | TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const { |
380 | if (OverrideAsUnavailable[F]) |
381 | return TargetLibraryInfoImpl::Unavailable; |
382 | return Impl->getState(F); |
383 | } |
384 | |
385 | /// Tests whether a library function is available. |
386 | bool has(LibFunc F) const { |
387 | return getState(F) != TargetLibraryInfoImpl::Unavailable; |
388 | } |
389 | bool isFunctionVectorizable(StringRef F, const ElementCount &VF) const { |
390 | return Impl->isFunctionVectorizable(F, VF); |
391 | } |
392 | bool isFunctionVectorizable(StringRef F) const { |
393 | return Impl->isFunctionVectorizable(F); |
394 | } |
395 | StringRef getVectorizedFunction(StringRef F, const ElementCount &VF, |
396 | bool Masked = false) const { |
397 | return Impl->getVectorizedFunction(F, VF, Masked); |
398 | } |
399 | const VecDesc *getVectorMappingInfo(StringRef F, const ElementCount &VF, |
400 | bool Masked) const { |
401 | return Impl->getVectorMappingInfo(F, VF, Masked); |
402 | } |
403 | |
404 | /// Tests if the function is both available and a candidate for optimized code |
405 | /// generation. |
406 | bool hasOptimizedCodeGen(LibFunc F) const { |
407 | if (getState(F) == TargetLibraryInfoImpl::Unavailable) |
408 | return false; |
409 | switch (F) { |
410 | default: break; |
411 | // clang-format off |
412 | case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl: |
413 | case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl: |
414 | case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl: |
415 | case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl: |
416 | case LibFunc_tan: case LibFunc_tanf: case LibFunc_tanl: |
417 | case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl: |
418 | case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite: |
419 | case LibFunc_sqrtl_finite: |
420 | case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl: |
421 | case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl: |
422 | case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl: |
423 | case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl: |
424 | case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill: |
425 | case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl: |
426 | case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl: |
427 | case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl: |
428 | case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l: |
429 | case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l: |
430 | case LibFunc_ldexp: case LibFunc_ldexpf: case LibFunc_ldexpl: |
431 | case LibFunc_memcpy: case LibFunc_memset: case LibFunc_memmove: |
432 | case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp: |
433 | case LibFunc_strcpy: case LibFunc_stpcpy: case LibFunc_strlen: |
434 | case LibFunc_strnlen: case LibFunc_memchr: case LibFunc_mempcpy: |
435 | // clang-format on |
436 | return true; |
437 | } |
438 | return false; |
439 | } |
440 | |
441 | StringRef getName(LibFunc F) const { |
442 | auto State = getState(F); |
443 | if (State == TargetLibraryInfoImpl::Unavailable) |
444 | return StringRef(); |
445 | if (State == TargetLibraryInfoImpl::StandardName) |
446 | return Impl->StandardNames[F]; |
447 | assert(State == TargetLibraryInfoImpl::CustomName); |
448 | return Impl->CustomNames.find(Val: F)->second; |
449 | } |
450 | |
451 | static void initExtensionsForTriple(bool &ShouldExtI32Param, |
452 | bool &ShouldExtI32Return, |
453 | bool &ShouldSignExtI32Param, |
454 | bool &ShouldSignExtI32Return, |
455 | const Triple &T) { |
456 | ShouldExtI32Param = ShouldExtI32Return = false; |
457 | ShouldSignExtI32Param = ShouldSignExtI32Return = false; |
458 | |
459 | // PowerPC64, Sparc64, SystemZ need signext/zeroext on i32 parameters and |
460 | // returns corresponding to C-level ints and unsigned ints. |
461 | if (T.isPPC64() || T.getArch() == Triple::sparcv9 || |
462 | T.getArch() == Triple::systemz) { |
463 | ShouldExtI32Param = true; |
464 | ShouldExtI32Return = true; |
465 | } |
466 | // LoongArch, Mips, and riscv64, on the other hand, need signext on i32 |
467 | // parameters corresponding to both signed and unsigned ints. |
468 | if (T.isLoongArch() || T.isMIPS() || T.isRISCV64()) { |
469 | ShouldSignExtI32Param = true; |
470 | } |
471 | // LoongArch and riscv64 need signext on i32 returns corresponding to both |
472 | // signed and unsigned ints. |
473 | if (T.isLoongArch() || T.isRISCV64()) { |
474 | ShouldSignExtI32Return = true; |
475 | } |
476 | } |
477 | |
478 | /// Returns extension attribute kind to be used for i32 parameters |
479 | /// corresponding to C-level int or unsigned int. May be zeroext, signext, |
480 | /// or none. |
481 | private: |
482 | static Attribute::AttrKind getExtAttrForI32Param(bool ShouldExtI32Param_, |
483 | bool ShouldSignExtI32Param_, |
484 | bool Signed = true) { |
485 | if (ShouldExtI32Param_) |
486 | return Signed ? Attribute::SExt : Attribute::ZExt; |
487 | if (ShouldSignExtI32Param_) |
488 | return Attribute::SExt; |
489 | return Attribute::None; |
490 | } |
491 | |
492 | public: |
493 | static Attribute::AttrKind getExtAttrForI32Param(const Triple &T, |
494 | bool Signed = true) { |
495 | bool ShouldExtI32Param, ShouldExtI32Return; |
496 | bool ShouldSignExtI32Param, ShouldSignExtI32Return; |
497 | initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return, |
498 | ShouldSignExtI32Param, ShouldSignExtI32Return, T); |
499 | return getExtAttrForI32Param(ShouldExtI32Param_: ShouldExtI32Param, ShouldSignExtI32Param_: ShouldSignExtI32Param, |
500 | Signed); |
501 | } |
502 | |
503 | Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const { |
504 | return getExtAttrForI32Param(ShouldExtI32Param_: Impl->ShouldExtI32Param, |
505 | ShouldSignExtI32Param_: Impl->ShouldSignExtI32Param, Signed); |
506 | } |
507 | |
508 | /// Returns extension attribute kind to be used for i32 return values |
509 | /// corresponding to C-level int or unsigned int. May be zeroext, signext, |
510 | /// or none. |
511 | private: |
512 | static Attribute::AttrKind getExtAttrForI32Return(bool ShouldExtI32Return_, |
513 | bool ShouldSignExtI32Return_, |
514 | bool Signed) { |
515 | if (ShouldExtI32Return_) |
516 | return Signed ? Attribute::SExt : Attribute::ZExt; |
517 | if (ShouldSignExtI32Return_) |
518 | return Attribute::SExt; |
519 | return Attribute::None; |
520 | } |
521 | |
522 | public: |
523 | static Attribute::AttrKind getExtAttrForI32Return(const Triple &T, |
524 | bool Signed = true) { |
525 | bool ShouldExtI32Param, ShouldExtI32Return; |
526 | bool ShouldSignExtI32Param, ShouldSignExtI32Return; |
527 | initExtensionsForTriple(ShouldExtI32Param, ShouldExtI32Return, |
528 | ShouldSignExtI32Param, ShouldSignExtI32Return, T); |
529 | return getExtAttrForI32Return(ShouldExtI32Return_: ShouldExtI32Return, ShouldSignExtI32Return_: ShouldSignExtI32Return, |
530 | Signed); |
531 | } |
532 | |
533 | Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const { |
534 | return getExtAttrForI32Return(ShouldExtI32Return_: Impl->ShouldExtI32Return, |
535 | ShouldSignExtI32Return_: Impl->ShouldSignExtI32Return, Signed); |
536 | } |
537 | |
538 | // Helper to create an AttributeList for args (and ret val) which all have |
539 | // the same signedness. Attributes in AL may be passed in to include them |
540 | // as well in the returned AttributeList. |
541 | AttributeList getAttrList(LLVMContext *C, ArrayRef<unsigned> ArgNos, |
542 | bool Signed, bool Ret = false, |
543 | AttributeList AL = AttributeList()) const { |
544 | if (auto AK = getExtAttrForI32Param(Signed)) |
545 | for (auto ArgNo : ArgNos) |
546 | AL = AL.addParamAttribute(C&: *C, ArgNo, Kind: AK); |
547 | if (Ret) |
548 | if (auto AK = getExtAttrForI32Return(Signed)) |
549 | AL = AL.addRetAttribute(C&: *C, Kind: AK); |
550 | return AL; |
551 | } |
552 | |
553 | /// \copydoc TargetLibraryInfoImpl::getWCharSize() |
554 | unsigned getWCharSize(const Module &M) const { |
555 | return Impl->getWCharSize(M); |
556 | } |
557 | |
558 | /// \copydoc TargetLibraryInfoImpl::getSizeTSize() |
559 | unsigned getSizeTSize(const Module &M) const { return Impl->getSizeTSize(M); } |
560 | |
561 | /// \copydoc TargetLibraryInfoImpl::getIntSize() |
562 | unsigned getIntSize() const { |
563 | return Impl->getIntSize(); |
564 | } |
565 | |
566 | /// Handle invalidation from the pass manager. |
567 | /// |
568 | /// If we try to invalidate this info, just return false. It cannot become |
569 | /// invalid even if the module or function changes. |
570 | bool invalidate(Module &, const PreservedAnalyses &, |
571 | ModuleAnalysisManager::Invalidator &) { |
572 | return false; |
573 | } |
574 | bool invalidate(Function &, const PreservedAnalyses &, |
575 | FunctionAnalysisManager::Invalidator &) { |
576 | return false; |
577 | } |
578 | /// Returns the largest vectorization factor used in the list of |
579 | /// vector functions. |
580 | void getWidestVF(StringRef ScalarF, ElementCount &FixedVF, |
581 | ElementCount &ScalableVF) const { |
582 | Impl->getWidestVF(ScalarF, FixedVF, Scalable&: ScalableVF); |
583 | } |
584 | |
585 | /// Check if the function "F" is listed in a library known to LLVM. |
586 | bool isKnownVectorFunctionInLibrary(StringRef F) const { |
587 | return this->isFunctionVectorizable(F); |
588 | } |
589 | }; |
590 | |
591 | /// Analysis pass providing the \c TargetLibraryInfo. |
592 | /// |
593 | /// Note that this pass's result cannot be invalidated, it is immutable for the |
594 | /// life of the module. |
595 | class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> { |
596 | public: |
597 | typedef TargetLibraryInfo Result; |
598 | |
599 | /// Default construct the library analysis. |
600 | /// |
601 | /// This will use the module's triple to construct the library info for that |
602 | /// module. |
603 | TargetLibraryAnalysis() = default; |
604 | |
605 | /// Construct a library analysis with baseline Module-level info. |
606 | /// |
607 | /// This will be supplemented with Function-specific info in the Result. |
608 | TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl) |
609 | : BaselineInfoImpl(std::move(BaselineInfoImpl)) {} |
610 | |
611 | TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &); |
612 | |
613 | private: |
614 | friend AnalysisInfoMixin<TargetLibraryAnalysis>; |
615 | static AnalysisKey Key; |
616 | |
617 | std::optional<TargetLibraryInfoImpl> BaselineInfoImpl; |
618 | }; |
619 | |
620 | class TargetLibraryInfoWrapperPass : public ImmutablePass { |
621 | TargetLibraryAnalysis TLA; |
622 | std::optional<TargetLibraryInfo> TLI; |
623 | |
624 | virtual void anchor(); |
625 | |
626 | public: |
627 | static char ID; |
628 | TargetLibraryInfoWrapperPass(); |
629 | explicit TargetLibraryInfoWrapperPass(const Triple &T); |
630 | explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI); |
631 | |
632 | // FIXME: This should be removed when PlaceSafepoints is fixed to not create a |
633 | // PassManager inside a pass. |
634 | explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfo &TLI); |
635 | |
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 | |