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