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 |