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 |