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