blob: 34a8a1e3407c29de0c945b2b664a0f3ed7e7fe40 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===-- TargetLibraryInfo.h - Library information ---------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_ANALYSIS_TARGETLIBRARYINFO_H
10#define LLVM_ANALYSIS_TARGETLIBRARYINFO_H
11
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020012#include "llvm/ADT/BitVector.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010013#include "llvm/ADT/DenseMap.h"
14#include "llvm/ADT/Optional.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010015#include "llvm/IR/Function.h"
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020016#include "llvm/IR/InstrTypes.h"
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010017#include "llvm/IR/Module.h"
18#include "llvm/IR/PassManager.h"
19#include "llvm/Pass.h"
20
21namespace llvm {
22template <typename T> class ArrayRef;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020023class Triple;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010024
25/// Describes a possible vectorization of a function.
26/// Function 'VectorFnName' is equivalent to 'ScalarFnName' vectorized
27/// by a factor 'VectorizationFactor'.
28struct VecDesc {
29 StringRef ScalarFnName;
30 StringRef VectorFnName;
31 unsigned VectorizationFactor;
32};
33
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020034 enum LibFunc : unsigned {
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035#define TLI_DEFINE_ENUM
36#include "llvm/Analysis/TargetLibraryInfo.def"
37
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020038 NumLibFuncs,
39 NotLibFunc
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010040 };
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.
48class TargetLibraryInfoImpl {
49 friend class TargetLibraryInfo;
50
51 unsigned char AvailableArray[(NumLibFuncs+3)/4];
52 llvm::DenseMap<unsigned, std::string> CustomNames;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020053 static StringLiteral const StandardNames[NumLibFuncs];
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010054 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
80public:
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.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +020091 LIBMVEC_X86,// GLIBC Vector Math library.
Andrew Walbran3d2c1972020-04-07 12:24:26 +010092 MASSV, // IBM MASS vector library.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010093 SVML // Intel short vector math library.
94 };
95
96 TargetLibraryInfoImpl();
97 explicit TargetLibraryInfoImpl(const Triple &T);
98
99 // Provide value semantics.
100 TargetLibraryInfoImpl(const TargetLibraryInfoImpl &TLI);
101 TargetLibraryInfoImpl(TargetLibraryInfoImpl &&TLI);
102 TargetLibraryInfoImpl &operator=(const TargetLibraryInfoImpl &TLI);
103 TargetLibraryInfoImpl &operator=(TargetLibraryInfoImpl &&TLI);
104
105 /// Searches for a particular function name.
106 ///
107 /// If it is one of the known library functions, return true and set F to the
108 /// corresponding value.
109 bool getLibFunc(StringRef funcName, LibFunc &F) const;
110
111 /// Searches for a particular function name, also checking that its type is
112 /// valid for the library function matching that name.
113 ///
114 /// If it is one of the known library functions, return true and set F to the
115 /// corresponding value.
116 bool getLibFunc(const Function &FDecl, LibFunc &F) const;
117
118 /// Forces a function to be marked as unavailable.
119 void setUnavailable(LibFunc F) {
120 setState(F, Unavailable);
121 }
122
123 /// Forces a function to be marked as available.
124 void setAvailable(LibFunc F) {
125 setState(F, StandardName);
126 }
127
128 /// Forces a function to be marked as available and provide an alternate name
129 /// that must be used.
130 void setAvailableWithName(LibFunc F, StringRef Name) {
131 if (StandardNames[F] != Name) {
132 setState(F, CustomName);
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200133 CustomNames[F] = std::string(Name);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100134 assert(CustomNames.find(F) != CustomNames.end());
135 } else {
136 setState(F, StandardName);
137 }
138 }
139
140 /// Disables all builtins.
141 ///
142 /// This can be used for options like -fno-builtin.
143 void disableAllFunctions();
144
145 /// Add a set of scalar -> vector mappings, queryable via
146 /// getVectorizedFunction and getScalarizedFunction.
147 void addVectorizableFunctions(ArrayRef<VecDesc> Fns);
148
149 /// Calls addVectorizableFunctions with a known preset of functions for the
150 /// given vector library.
151 void addVectorizableFunctionsFromVecLib(enum VectorLibrary VecLib);
152
153 /// Return true if the function F has a vector equivalent with vectorization
154 /// factor VF.
155 bool isFunctionVectorizable(StringRef F, unsigned VF) const {
156 return !getVectorizedFunction(F, VF).empty();
157 }
158
159 /// Return true if the function F has a vector equivalent with any
160 /// vectorization factor.
161 bool isFunctionVectorizable(StringRef F) const;
162
163 /// Return the name of the equivalent of F, vectorized with factor VF. If no
164 /// such mapping exists, return the empty string.
165 StringRef getVectorizedFunction(StringRef F, unsigned VF) const;
166
167 /// Return true if the function F has a scalar equivalent, and set VF to be
168 /// the vectorization factor.
169 bool isFunctionScalarizable(StringRef F, unsigned &VF) const {
170 return !getScalarizedFunction(F, VF).empty();
171 }
172
173 /// Return the name of the equivalent of F, scalarized. If no such mapping
174 /// exists, return the empty string.
175 ///
176 /// Set VF to the vectorization factor.
177 StringRef getScalarizedFunction(StringRef F, unsigned &VF) const;
178
179 /// Set to true iff i32 parameters to library functions should have signext
180 /// or zeroext attributes if they correspond to C-level int or unsigned int,
181 /// respectively.
182 void setShouldExtI32Param(bool Val) {
183 ShouldExtI32Param = Val;
184 }
185
186 /// Set to true iff i32 results from library functions should have signext
187 /// or zeroext attributes if they correspond to C-level int or unsigned int,
188 /// respectively.
189 void setShouldExtI32Return(bool Val) {
190 ShouldExtI32Return = Val;
191 }
192
193 /// Set to true iff i32 parameters to library functions should have signext
194 /// attribute if they correspond to C-level int or unsigned int.
195 void setShouldSignExtI32Param(bool Val) {
196 ShouldSignExtI32Param = Val;
197 }
198
199 /// Returns the size of the wchar_t type in bytes or 0 if the size is unknown.
200 /// This queries the 'wchar_size' metadata.
201 unsigned getWCharSize(const Module &M) const;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200202
203 /// Returns the largest vectorization factor used in the list of
204 /// vector functions.
205 unsigned getWidestVF(StringRef ScalarF) const;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100206};
207
208/// Provides information about what library functions are available for
209/// the current target.
210///
211/// This both allows optimizations to handle them specially and frontends to
212/// disable such optimizations through -fno-builtin etc.
213class TargetLibraryInfo {
214 friend class TargetLibraryAnalysis;
215 friend class TargetLibraryInfoWrapperPass;
216
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200217 /// The global (module level) TLI info.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100218 const TargetLibraryInfoImpl *Impl;
219
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200220 /// Support for -fno-builtin* options as function attributes, overrides
221 /// information in global TargetLibraryInfoImpl.
222 BitVector OverrideAsUnavailable;
223
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100224public:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200225 explicit TargetLibraryInfo(const TargetLibraryInfoImpl &Impl,
226 Optional<const Function *> F = None)
227 : Impl(&Impl), OverrideAsUnavailable(NumLibFuncs) {
228 if (!F)
229 return;
230 if ((*F)->hasFnAttribute("no-builtins"))
231 disableAllFunctions();
232 else {
233 // Disable individual libc/libm calls in TargetLibraryInfo.
234 LibFunc LF;
235 AttributeSet FnAttrs = (*F)->getAttributes().getFnAttributes();
236 for (const Attribute &Attr : FnAttrs) {
237 if (!Attr.isStringAttribute())
238 continue;
239 auto AttrStr = Attr.getKindAsString();
240 if (!AttrStr.consume_front("no-builtin-"))
241 continue;
242 if (getLibFunc(AttrStr, LF))
243 setUnavailable(LF);
244 }
245 }
246 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100247
248 // Provide value semantics.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200249 TargetLibraryInfo(const TargetLibraryInfo &TLI)
250 : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
251 TargetLibraryInfo(TargetLibraryInfo &&TLI)
252 : Impl(TLI.Impl), OverrideAsUnavailable(TLI.OverrideAsUnavailable) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100253 TargetLibraryInfo &operator=(const TargetLibraryInfo &TLI) {
254 Impl = TLI.Impl;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200255 OverrideAsUnavailable = TLI.OverrideAsUnavailable;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100256 return *this;
257 }
258 TargetLibraryInfo &operator=(TargetLibraryInfo &&TLI) {
259 Impl = TLI.Impl;
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200260 OverrideAsUnavailable = TLI.OverrideAsUnavailable;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100261 return *this;
262 }
263
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200264 /// Determine whether a callee with the given TLI can be inlined into
265 /// caller with this TLI, based on 'nobuiltin' attributes. When requested,
266 /// allow inlining into a caller with a superset of the callee's nobuiltin
267 /// attributes, which is conservatively correct.
268 bool areInlineCompatible(const TargetLibraryInfo &CalleeTLI,
269 bool AllowCallerSuperset) const {
270 if (!AllowCallerSuperset)
271 return OverrideAsUnavailable == CalleeTLI.OverrideAsUnavailable;
272 BitVector B = OverrideAsUnavailable;
273 B |= CalleeTLI.OverrideAsUnavailable;
274 // We can inline if the union of the caller and callee's nobuiltin
275 // attributes is no stricter than the caller's nobuiltin attributes.
276 return B == OverrideAsUnavailable;
277 }
278
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100279 /// Searches for a particular function name.
280 ///
281 /// If it is one of the known library functions, return true and set F to the
282 /// corresponding value.
283 bool getLibFunc(StringRef funcName, LibFunc &F) const {
284 return Impl->getLibFunc(funcName, F);
285 }
286
287 bool getLibFunc(const Function &FDecl, LibFunc &F) const {
288 return Impl->getLibFunc(FDecl, F);
289 }
290
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200291 /// If a callbase does not have the 'nobuiltin' attribute, return if the
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100292 /// called function is a known library function and set F to that function.
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200293 bool getLibFunc(const CallBase &CB, LibFunc &F) const {
294 return !CB.isNoBuiltin() && CB.getCalledFunction() &&
295 getLibFunc(*(CB.getCalledFunction()), F);
296 }
297
298 /// Disables all builtins.
299 ///
300 /// This can be used for options like -fno-builtin.
301 void disableAllFunctions() LLVM_ATTRIBUTE_UNUSED {
302 OverrideAsUnavailable.set();
303 }
304
305 /// Forces a function to be marked as unavailable.
306 void setUnavailable(LibFunc F) LLVM_ATTRIBUTE_UNUSED {
307 OverrideAsUnavailable.set(F);
308 }
309
310 TargetLibraryInfoImpl::AvailabilityState getState(LibFunc F) const {
311 if (OverrideAsUnavailable[F])
312 return TargetLibraryInfoImpl::Unavailable;
313 return Impl->getState(F);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100314 }
315
316 /// Tests whether a library function is available.
317 bool has(LibFunc F) const {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200318 return getState(F) != TargetLibraryInfoImpl::Unavailable;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100319 }
320 bool isFunctionVectorizable(StringRef F, unsigned VF) const {
321 return Impl->isFunctionVectorizable(F, VF);
322 }
323 bool isFunctionVectorizable(StringRef F) const {
324 return Impl->isFunctionVectorizable(F);
325 }
326 StringRef getVectorizedFunction(StringRef F, unsigned VF) const {
327 return Impl->getVectorizedFunction(F, VF);
328 }
329
330 /// Tests if the function is both available and a candidate for optimized code
331 /// generation.
332 bool hasOptimizedCodeGen(LibFunc F) const {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200333 if (getState(F) == TargetLibraryInfoImpl::Unavailable)
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100334 return false;
335 switch (F) {
336 default: break;
337 case LibFunc_copysign: case LibFunc_copysignf: case LibFunc_copysignl:
338 case LibFunc_fabs: case LibFunc_fabsf: case LibFunc_fabsl:
339 case LibFunc_sin: case LibFunc_sinf: case LibFunc_sinl:
340 case LibFunc_cos: case LibFunc_cosf: case LibFunc_cosl:
341 case LibFunc_sqrt: case LibFunc_sqrtf: case LibFunc_sqrtl:
342 case LibFunc_sqrt_finite: case LibFunc_sqrtf_finite:
343 case LibFunc_sqrtl_finite:
344 case LibFunc_fmax: case LibFunc_fmaxf: case LibFunc_fmaxl:
345 case LibFunc_fmin: case LibFunc_fminf: case LibFunc_fminl:
346 case LibFunc_floor: case LibFunc_floorf: case LibFunc_floorl:
347 case LibFunc_nearbyint: case LibFunc_nearbyintf: case LibFunc_nearbyintl:
348 case LibFunc_ceil: case LibFunc_ceilf: case LibFunc_ceill:
349 case LibFunc_rint: case LibFunc_rintf: case LibFunc_rintl:
350 case LibFunc_round: case LibFunc_roundf: case LibFunc_roundl:
351 case LibFunc_trunc: case LibFunc_truncf: case LibFunc_truncl:
352 case LibFunc_log2: case LibFunc_log2f: case LibFunc_log2l:
353 case LibFunc_exp2: case LibFunc_exp2f: case LibFunc_exp2l:
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200354 case LibFunc_memcpy: case LibFunc_memset: case LibFunc_memmove:
Andrew Walbran3d2c1972020-04-07 12:24:26 +0100355 case LibFunc_memcmp: case LibFunc_bcmp: case LibFunc_strcmp:
356 case LibFunc_strcpy: case LibFunc_stpcpy: case LibFunc_strlen:
357 case LibFunc_strnlen: case LibFunc_memchr: case LibFunc_mempcpy:
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100358 return true;
359 }
360 return false;
361 }
362
363 StringRef getName(LibFunc F) const {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200364 auto State = getState(F);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100365 if (State == TargetLibraryInfoImpl::Unavailable)
366 return StringRef();
367 if (State == TargetLibraryInfoImpl::StandardName)
368 return Impl->StandardNames[F];
369 assert(State == TargetLibraryInfoImpl::CustomName);
370 return Impl->CustomNames.find(F)->second;
371 }
372
373 /// Returns extension attribute kind to be used for i32 parameters
374 /// corresponding to C-level int or unsigned int. May be zeroext, signext,
375 /// or none.
376 Attribute::AttrKind getExtAttrForI32Param(bool Signed = true) const {
377 if (Impl->ShouldExtI32Param)
378 return Signed ? Attribute::SExt : Attribute::ZExt;
379 if (Impl->ShouldSignExtI32Param)
380 return Attribute::SExt;
381 return Attribute::None;
382 }
383
384 /// Returns extension attribute kind to be used for i32 return values
385 /// corresponding to C-level int or unsigned int. May be zeroext, signext,
386 /// or none.
387 Attribute::AttrKind getExtAttrForI32Return(bool Signed = true) const {
388 if (Impl->ShouldExtI32Return)
389 return Signed ? Attribute::SExt : Attribute::ZExt;
390 return Attribute::None;
391 }
392
393 /// \copydoc TargetLibraryInfoImpl::getWCharSize()
394 unsigned getWCharSize(const Module &M) const {
395 return Impl->getWCharSize(M);
396 }
397
398 /// Handle invalidation from the pass manager.
399 ///
400 /// If we try to invalidate this info, just return false. It cannot become
401 /// invalid even if the module or function changes.
402 bool invalidate(Module &, const PreservedAnalyses &,
403 ModuleAnalysisManager::Invalidator &) {
404 return false;
405 }
406 bool invalidate(Function &, const PreservedAnalyses &,
407 FunctionAnalysisManager::Invalidator &) {
408 return false;
409 }
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200410 /// Returns the largest vectorization factor used in the list of
411 /// vector functions.
412 unsigned getWidestVF(StringRef ScalarF) const {
413 return Impl->getWidestVF(ScalarF);
414 }
415
416 /// Check if the function "F" is listed in a library known to LLVM.
417 bool isKnownVectorFunctionInLibrary(StringRef F) const {
418 return this->isFunctionVectorizable(F);
419 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100420};
421
422/// Analysis pass providing the \c TargetLibraryInfo.
423///
424/// Note that this pass's result cannot be invalidated, it is immutable for the
425/// life of the module.
426class TargetLibraryAnalysis : public AnalysisInfoMixin<TargetLibraryAnalysis> {
427public:
428 typedef TargetLibraryInfo Result;
429
430 /// Default construct the library analysis.
431 ///
432 /// This will use the module's triple to construct the library info for that
433 /// module.
434 TargetLibraryAnalysis() {}
435
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200436 /// Construct a library analysis with baseline Module-level info.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100437 ///
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200438 /// This will be supplemented with Function-specific info in the Result.
439 TargetLibraryAnalysis(TargetLibraryInfoImpl BaselineInfoImpl)
440 : BaselineInfoImpl(std::move(BaselineInfoImpl)) {}
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100441
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200442 TargetLibraryInfo run(const Function &F, FunctionAnalysisManager &);
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100443
444private:
445 friend AnalysisInfoMixin<TargetLibraryAnalysis>;
446 static AnalysisKey Key;
447
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200448 Optional<TargetLibraryInfoImpl> BaselineInfoImpl;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100449};
450
451class TargetLibraryInfoWrapperPass : public ImmutablePass {
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200452 TargetLibraryAnalysis TLA;
453 Optional<TargetLibraryInfo> TLI;
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100454
455 virtual void anchor();
456
457public:
458 static char ID;
459 TargetLibraryInfoWrapperPass();
460 explicit TargetLibraryInfoWrapperPass(const Triple &T);
461 explicit TargetLibraryInfoWrapperPass(const TargetLibraryInfoImpl &TLI);
462
Olivier Deprezf4ef2d02021-04-20 13:36:24 +0200463 TargetLibraryInfo &getTLI(const Function &F) {
464 FunctionAnalysisManager DummyFAM;
465 TLI = TLA.run(F, DummyFAM);
466 return *TLI;
467 }
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100468};
469
470} // end namespace llvm
471
472#endif