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