1 //===-- AMDGPULibFunc.h ----------------------------------------*- 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 _AMDGPU_LIBFUNC_H_ 10 #define _AMDGPU_LIBFUNC_H_ 11 12 #include "llvm/ADT/StringRef.h" 13 14 namespace llvm { 15 16 class FunctionCallee; 17 class FunctionType; 18 class Function; 19 class Module; 20 21 class AMDGPULibFuncBase { 22 public: 23 enum EFuncId { 24 EI_NONE, 25 26 // IMPORTANT: enums below should go in ascending by 1 value order 27 // because they are used as indexes in the mangling rules table. 28 // don't use explicit value assignment. 29 // 30 // There are two types of library functions: those with mangled 31 // name and those with unmangled name. The enums for the library 32 // functions with mangled name are defined before enums for the 33 // library functions with unmangled name. The enum for the last 34 // library function with mangled name is EI_LAST_MANGLED. 35 // 36 // Library functions with mangled name. 37 EI_ABS, 38 EI_ABS_DIFF, 39 EI_ACOS, 40 EI_ACOSH, 41 EI_ACOSPI, 42 EI_ADD_SAT, 43 EI_ALL, 44 EI_ANY, 45 EI_ASIN, 46 EI_ASINH, 47 EI_ASINPI, 48 EI_ASYNC_WORK_GROUP_COPY, 49 EI_ASYNC_WORK_GROUP_STRIDED_COPY, 50 EI_ATAN, 51 EI_ATAN2, 52 EI_ATAN2PI, 53 EI_ATANH, 54 EI_ATANPI, 55 EI_ATOMIC_ADD, 56 EI_ATOMIC_AND, 57 EI_ATOMIC_CMPXCHG, 58 EI_ATOMIC_DEC, 59 EI_ATOMIC_INC, 60 EI_ATOMIC_MAX, 61 EI_ATOMIC_MIN, 62 EI_ATOMIC_OR, 63 EI_ATOMIC_SUB, 64 EI_ATOMIC_XCHG, 65 EI_ATOMIC_XOR, 66 EI_BITSELECT, 67 EI_CBRT, 68 EI_CEIL, 69 EI_CLAMP, 70 EI_CLZ, 71 EI_COMMIT_READ_PIPE, 72 EI_COMMIT_WRITE_PIPE, 73 EI_COPYSIGN, 74 EI_COS, 75 EI_COSH, 76 EI_COSPI, 77 EI_CROSS, 78 EI_CTZ, 79 EI_DEGREES, 80 EI_DISTANCE, 81 EI_DIVIDE, 82 EI_DOT, 83 EI_ERF, 84 EI_ERFC, 85 EI_EXP, 86 EI_EXP10, 87 EI_EXP2, 88 EI_EXPM1, 89 EI_FABS, 90 EI_FAST_DISTANCE, 91 EI_FAST_LENGTH, 92 EI_FAST_NORMALIZE, 93 EI_FDIM, 94 EI_FLOOR, 95 EI_FMA, 96 EI_FMAX, 97 EI_FMIN, 98 EI_FMOD, 99 EI_FRACT, 100 EI_FREXP, 101 EI_GET_IMAGE_ARRAY_SIZE, 102 EI_GET_IMAGE_CHANNEL_DATA_TYPE, 103 EI_GET_IMAGE_CHANNEL_ORDER, 104 EI_GET_IMAGE_DIM, 105 EI_GET_IMAGE_HEIGHT, 106 EI_GET_IMAGE_WIDTH, 107 EI_GET_PIPE_MAX_PACKETS, 108 EI_GET_PIPE_NUM_PACKETS, 109 EI_HADD, 110 EI_HYPOT, 111 EI_ILOGB, 112 EI_ISEQUAL, 113 EI_ISFINITE, 114 EI_ISGREATER, 115 EI_ISGREATEREQUAL, 116 EI_ISINF, 117 EI_ISLESS, 118 EI_ISLESSEQUAL, 119 EI_ISLESSGREATER, 120 EI_ISNAN, 121 EI_ISNORMAL, 122 EI_ISNOTEQUAL, 123 EI_ISORDERED, 124 EI_ISUNORDERED, 125 EI_LDEXP, 126 EI_LENGTH, 127 EI_LGAMMA, 128 EI_LGAMMA_R, 129 EI_LOG, 130 EI_LOG10, 131 EI_LOG1P, 132 EI_LOG2, 133 EI_LOGB, 134 EI_MAD, 135 EI_MAD24, 136 EI_MAD_HI, 137 EI_MAD_SAT, 138 EI_MAX, 139 EI_MAXMAG, 140 EI_MIN, 141 EI_MINMAG, 142 EI_MIX, 143 EI_MODF, 144 EI_MUL24, 145 EI_MUL_HI, 146 EI_NAN, 147 EI_NEXTAFTER, 148 EI_NORMALIZE, 149 EI_POPCOUNT, 150 EI_POW, 151 EI_POWN, 152 EI_POWR, 153 EI_PREFETCH, 154 EI_RADIANS, 155 EI_RECIP, 156 EI_REMAINDER, 157 EI_REMQUO, 158 EI_RESERVE_READ_PIPE, 159 EI_RESERVE_WRITE_PIPE, 160 EI_RHADD, 161 EI_RINT, 162 EI_ROOTN, 163 EI_ROTATE, 164 EI_ROUND, 165 EI_RSQRT, 166 EI_SELECT, 167 EI_SHUFFLE, 168 EI_SHUFFLE2, 169 EI_SIGN, 170 EI_SIGNBIT, 171 EI_SIN, 172 EI_SINCOS, 173 EI_SINH, 174 EI_SINPI, 175 EI_SMOOTHSTEP, 176 EI_SQRT, 177 EI_STEP, 178 EI_SUB_GROUP_BROADCAST, 179 EI_SUB_GROUP_COMMIT_READ_PIPE, 180 EI_SUB_GROUP_COMMIT_WRITE_PIPE, 181 EI_SUB_GROUP_REDUCE_ADD, 182 EI_SUB_GROUP_REDUCE_MAX, 183 EI_SUB_GROUP_REDUCE_MIN, 184 EI_SUB_GROUP_RESERVE_READ_PIPE, 185 EI_SUB_GROUP_RESERVE_WRITE_PIPE, 186 EI_SUB_GROUP_SCAN_EXCLUSIVE_ADD, 187 EI_SUB_GROUP_SCAN_EXCLUSIVE_MAX, 188 EI_SUB_GROUP_SCAN_EXCLUSIVE_MIN, 189 EI_SUB_GROUP_SCAN_INCLUSIVE_ADD, 190 EI_SUB_GROUP_SCAN_INCLUSIVE_MAX, 191 EI_SUB_GROUP_SCAN_INCLUSIVE_MIN, 192 EI_SUB_SAT, 193 EI_TAN, 194 EI_TANH, 195 EI_TANPI, 196 EI_TGAMMA, 197 EI_TRUNC, 198 EI_UPSAMPLE, 199 EI_VEC_STEP, 200 EI_VSTORE, 201 EI_VSTORE16, 202 EI_VSTORE2, 203 EI_VSTORE3, 204 EI_VSTORE4, 205 EI_VSTORE8, 206 EI_WORK_GROUP_COMMIT_READ_PIPE, 207 EI_WORK_GROUP_COMMIT_WRITE_PIPE, 208 EI_WORK_GROUP_REDUCE_ADD, 209 EI_WORK_GROUP_REDUCE_MAX, 210 EI_WORK_GROUP_REDUCE_MIN, 211 EI_WORK_GROUP_RESERVE_READ_PIPE, 212 EI_WORK_GROUP_RESERVE_WRITE_PIPE, 213 EI_WORK_GROUP_SCAN_EXCLUSIVE_ADD, 214 EI_WORK_GROUP_SCAN_EXCLUSIVE_MAX, 215 EI_WORK_GROUP_SCAN_EXCLUSIVE_MIN, 216 EI_WORK_GROUP_SCAN_INCLUSIVE_ADD, 217 EI_WORK_GROUP_SCAN_INCLUSIVE_MAX, 218 EI_WORK_GROUP_SCAN_INCLUSIVE_MIN, 219 EI_WRITE_IMAGEF, 220 EI_WRITE_IMAGEI, 221 EI_WRITE_IMAGEUI, 222 EI_NCOS, 223 EI_NEXP2, 224 EI_NFMA, 225 EI_NLOG2, 226 EI_NRCP, 227 EI_NRSQRT, 228 EI_NSIN, 229 EI_NSQRT, 230 EI_FTZ, 231 EI_FLDEXP, 232 EI_CLASS, 233 EI_RCBRT, 234 EI_LAST_MANGLED = 235 EI_RCBRT, /* The last library function with mangled name */ 236 237 // Library functions with unmangled name. 238 EI_READ_PIPE_2, 239 EI_READ_PIPE_4, 240 EI_WRITE_PIPE_2, 241 EI_WRITE_PIPE_4, 242 243 EX_INTRINSICS_COUNT 244 }; 245 246 enum ENamePrefix { 247 NOPFX, 248 NATIVE, 249 HALF 250 }; 251 252 enum EType { 253 B8 = 1, 254 B16 = 2, 255 B32 = 3, 256 B64 = 4, 257 SIZE_MASK = 7, 258 FLOAT = 0x10, 259 INT = 0x20, 260 UINT = 0x30, 261 BASE_TYPE_MASK = 0x30, 262 U8 = UINT | B8, 263 U16 = UINT | B16, 264 U32 = UINT | B32, 265 U64 = UINT | B64, 266 I8 = INT | B8, 267 I16 = INT | B16, 268 I32 = INT | B32, 269 I64 = INT | B64, 270 F16 = FLOAT | B16, 271 F32 = FLOAT | B32, 272 F64 = FLOAT | B64, 273 IMG1DA = 0x80, 274 IMG1DB, 275 IMG2DA, 276 IMG1D, 277 IMG2D, 278 IMG3D, 279 SAMPLER, 280 EVENT, 281 DUMMY 282 }; 283 284 enum EPtrKind { 285 BYVALUE = 0, 286 ADDR_SPACE = 0xF, // Address space takes value 0x1 ~ 0xF. 287 CONST = 0x10, 288 VOLATILE = 0x20 289 }; 290 291 struct Param { 292 unsigned char ArgType; 293 unsigned char VectorSize; 294 unsigned char PtrKind; 295 296 unsigned char Reserved; 297 resetParam298 void reset() { 299 ArgType = 0; 300 VectorSize = 1; 301 PtrKind = 0; 302 } ParamParam303 Param() { reset(); } 304 305 template <typename Stream> 306 void mangleItanium(Stream& os); 307 }; isMangled(EFuncId Id)308 static bool isMangled(EFuncId Id) { 309 return static_cast<unsigned>(Id) <= static_cast<unsigned>(EI_LAST_MANGLED); 310 } 311 getEPtrKindFromAddrSpace(unsigned AS)312 static unsigned getEPtrKindFromAddrSpace(unsigned AS) { 313 assert(((AS + 1) & ~ADDR_SPACE) == 0); 314 return AS + 1; 315 } 316 getAddrSpaceFromEPtrKind(unsigned Kind)317 static unsigned getAddrSpaceFromEPtrKind(unsigned Kind) { 318 Kind = Kind & ADDR_SPACE; 319 assert(Kind >= 1); 320 return Kind - 1; 321 } 322 }; 323 324 class AMDGPULibFuncImpl : public AMDGPULibFuncBase { 325 public: AMDGPULibFuncImpl()326 AMDGPULibFuncImpl() {} ~AMDGPULibFuncImpl()327 virtual ~AMDGPULibFuncImpl() {} 328 329 /// Get unmangled name for mangled library function and name for unmangled 330 /// library function. 331 virtual std::string getName() const = 0; 332 virtual unsigned getNumArgs() const = 0; getId()333 EFuncId getId() const { return FuncId; } getPrefix()334 ENamePrefix getPrefix() const { return FKind; } 335 isMangled()336 bool isMangled() const { return AMDGPULibFuncBase::isMangled(FuncId); } 337 setId(EFuncId id)338 void setId(EFuncId id) { FuncId = id; } 339 virtual bool parseFuncName(StringRef &mangledName) = 0; 340 341 /// \return The mangled function name for mangled library functions 342 /// and unmangled function name for unmangled library functions. 343 virtual std::string mangle() const = 0; 344 setName(StringRef N)345 void setName(StringRef N) { Name = std::string(N); } setPrefix(ENamePrefix pfx)346 void setPrefix(ENamePrefix pfx) { FKind = pfx; } 347 348 virtual FunctionType *getFunctionType(Module &M) const = 0; 349 350 protected: 351 EFuncId FuncId; 352 std::string Name; 353 ENamePrefix FKind; 354 }; 355 356 /// Wrapper class for AMDGPULIbFuncImpl 357 class AMDGPULibFunc : public AMDGPULibFuncBase { 358 public: AMDGPULibFunc()359 explicit AMDGPULibFunc() : Impl(std::unique_ptr<AMDGPULibFuncImpl>()) {} 360 AMDGPULibFunc(const AMDGPULibFunc &F); 361 /// Clone a mangled library func with the Id \p Id and argument info from \p 362 /// CopyFrom. 363 explicit AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom); 364 /// Construct an unmangled library function on the fly. 365 explicit AMDGPULibFunc(StringRef FName, FunctionType *FT); 366 367 AMDGPULibFunc &operator=(const AMDGPULibFunc &F); 368 369 /// Get unmangled name for mangled library function and name for unmangled 370 /// library function. getName()371 std::string getName() const { return Impl->getName(); } getNumArgs()372 unsigned getNumArgs() const { return Impl->getNumArgs(); } getId()373 EFuncId getId() const { return Impl->getId(); } getPrefix()374 ENamePrefix getPrefix() const { return Impl->getPrefix(); } 375 /// Get leading parameters for mangled lib functions. 376 Param *getLeads(); 377 const Param *getLeads() const; 378 isMangled()379 bool isMangled() const { return Impl->isMangled(); } setId(EFuncId Id)380 void setId(EFuncId Id) { Impl->setId(Id); } parseFuncName(StringRef & MangledName)381 bool parseFuncName(StringRef &MangledName) { 382 return Impl->parseFuncName(MangledName); 383 } 384 385 /// \return The mangled function name for mangled library functions 386 /// and unmangled function name for unmangled library functions. mangle()387 std::string mangle() const { return Impl->mangle(); } 388 setName(StringRef N)389 void setName(StringRef N) { Impl->setName(N); } setPrefix(ENamePrefix PFX)390 void setPrefix(ENamePrefix PFX) { Impl->setPrefix(PFX); } 391 getFunctionType(Module & M)392 FunctionType *getFunctionType(Module &M) const { 393 return Impl->getFunctionType(M); 394 } 395 static Function *getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo); 396 397 static FunctionCallee getOrInsertFunction(llvm::Module *M, 398 const AMDGPULibFunc &fInfo); 399 static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr); 400 401 private: 402 /// Initialize as a mangled library function. 403 void initMangled(); 404 std::unique_ptr<AMDGPULibFuncImpl> Impl; 405 }; 406 407 class AMDGPUMangledLibFunc : public AMDGPULibFuncImpl { 408 public: 409 Param Leads[2]; 410 411 explicit AMDGPUMangledLibFunc(); 412 explicit AMDGPUMangledLibFunc(EFuncId id, 413 const AMDGPUMangledLibFunc ©From); 414 415 std::string getName() const override; 416 unsigned getNumArgs() const override; 417 FunctionType *getFunctionType(Module &M) const override; 418 static StringRef getUnmangledName(StringRef MangledName); 419 420 bool parseFuncName(StringRef &mangledName) override; 421 422 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const AMDGPULibFuncImpl * F)423 static bool classof(const AMDGPULibFuncImpl *F) { return F->isMangled(); } 424 425 std::string mangle() const override; 426 427 private: 428 std::string mangleNameItanium() const; 429 430 std::string mangleName(StringRef Name) const; 431 bool parseUnmangledName(StringRef MangledName); 432 433 template <typename Stream> void writeName(Stream &OS) const; 434 }; 435 436 class AMDGPUUnmangledLibFunc : public AMDGPULibFuncImpl { 437 FunctionType *FuncTy; 438 439 public: 440 explicit AMDGPUUnmangledLibFunc(); AMDGPUUnmangledLibFunc(StringRef FName,FunctionType * FT)441 explicit AMDGPUUnmangledLibFunc(StringRef FName, FunctionType *FT) { 442 Name = std::string(FName); 443 FuncTy = FT; 444 } getName()445 std::string getName() const override { return Name; } 446 unsigned getNumArgs() const override; getFunctionType(Module & M)447 FunctionType *getFunctionType(Module &M) const override { return FuncTy; } 448 449 bool parseFuncName(StringRef &Name) override; 450 451 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const AMDGPULibFuncImpl * F)452 static bool classof(const AMDGPULibFuncImpl *F) { return !F->isMangled(); } 453 mangle()454 std::string mangle() const override { return Name; } 455 setFunctionType(FunctionType * FT)456 void setFunctionType(FunctionType *FT) { FuncTy = FT; } 457 }; 458 } 459 #endif // _AMDGPU_LIBFUNC_H_ 460