blob: 2354ed7df2059b55bc256c31046b173db4790a14 [file] [log] [blame]
//===-- AMDGPULibFunc.h ----------------------------------------*- C++ -*--===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef _AMDGPU_LIBFUNC_H_
#define _AMDGPU_LIBFUNC_H_
#include "llvm/ADT/StringRef.h"
namespace llvm {
class FunctionType;
class Function;
class Module;
class AMDGPULibFuncBase {
public:
enum EFuncId {
EI_NONE,
// IMPORTANT: enums below should go in ascending by 1 value order
// because they are used as indexes in the mangling rules table.
// don't use explicit value assignment.
//
// There are two types of library functions: those with mangled
// name and those with unmangled name. The enums for the library
// functions with mangled name are defined before enums for the
// library functions with unmangled name. The enum for the last
// library function with mangled name is EI_LAST_MANGLED.
//
// Library functions with mangled name.
EI_ABS,
EI_ABS_DIFF,
EI_ACOS,
EI_ACOSH,
EI_ACOSPI,
EI_ADD_SAT,
EI_ALL,
EI_ANY,
EI_ASIN,
EI_ASINH,
EI_ASINPI,
EI_ASYNC_WORK_GROUP_COPY,
EI_ASYNC_WORK_GROUP_STRIDED_COPY,
EI_ATAN,
EI_ATAN2,
EI_ATAN2PI,
EI_ATANH,
EI_ATANPI,
EI_ATOMIC_ADD,
EI_ATOMIC_AND,
EI_ATOMIC_CMPXCHG,
EI_ATOMIC_DEC,
EI_ATOMIC_INC,
EI_ATOMIC_MAX,
EI_ATOMIC_MIN,
EI_ATOMIC_OR,
EI_ATOMIC_SUB,
EI_ATOMIC_XCHG,
EI_ATOMIC_XOR,
EI_BITSELECT,
EI_CBRT,
EI_CEIL,
EI_CLAMP,
EI_CLZ,
EI_COMMIT_READ_PIPE,
EI_COMMIT_WRITE_PIPE,
EI_COPYSIGN,
EI_COS,
EI_COSH,
EI_COSPI,
EI_CROSS,
EI_CTZ,
EI_DEGREES,
EI_DISTANCE,
EI_DIVIDE,
EI_DOT,
EI_ERF,
EI_ERFC,
EI_EXP,
EI_EXP10,
EI_EXP2,
EI_EXPM1,
EI_FABS,
EI_FAST_DISTANCE,
EI_FAST_LENGTH,
EI_FAST_NORMALIZE,
EI_FDIM,
EI_FLOOR,
EI_FMA,
EI_FMAX,
EI_FMIN,
EI_FMOD,
EI_FRACT,
EI_FREXP,
EI_GET_IMAGE_ARRAY_SIZE,
EI_GET_IMAGE_CHANNEL_DATA_TYPE,
EI_GET_IMAGE_CHANNEL_ORDER,
EI_GET_IMAGE_DIM,
EI_GET_IMAGE_HEIGHT,
EI_GET_IMAGE_WIDTH,
EI_GET_PIPE_MAX_PACKETS,
EI_GET_PIPE_NUM_PACKETS,
EI_HADD,
EI_HYPOT,
EI_ILOGB,
EI_ISEQUAL,
EI_ISFINITE,
EI_ISGREATER,
EI_ISGREATEREQUAL,
EI_ISINF,
EI_ISLESS,
EI_ISLESSEQUAL,
EI_ISLESSGREATER,
EI_ISNAN,
EI_ISNORMAL,
EI_ISNOTEQUAL,
EI_ISORDERED,
EI_ISUNORDERED,
EI_LDEXP,
EI_LENGTH,
EI_LGAMMA,
EI_LGAMMA_R,
EI_LOG,
EI_LOG10,
EI_LOG1P,
EI_LOG2,
EI_LOGB,
EI_MAD,
EI_MAD24,
EI_MAD_HI,
EI_MAD_SAT,
EI_MAX,
EI_MAXMAG,
EI_MIN,
EI_MINMAG,
EI_MIX,
EI_MODF,
EI_MUL24,
EI_MUL_HI,
EI_NAN,
EI_NEXTAFTER,
EI_NORMALIZE,
EI_POPCOUNT,
EI_POW,
EI_POWN,
EI_POWR,
EI_PREFETCH,
EI_RADIANS,
EI_RECIP,
EI_REMAINDER,
EI_REMQUO,
EI_RESERVE_READ_PIPE,
EI_RESERVE_WRITE_PIPE,
EI_RHADD,
EI_RINT,
EI_ROOTN,
EI_ROTATE,
EI_ROUND,
EI_RSQRT,
EI_SELECT,
EI_SHUFFLE,
EI_SHUFFLE2,
EI_SIGN,
EI_SIGNBIT,
EI_SIN,
EI_SINCOS,
EI_SINH,
EI_SINPI,
EI_SMOOTHSTEP,
EI_SQRT,
EI_STEP,
EI_SUB_GROUP_BROADCAST,
EI_SUB_GROUP_COMMIT_READ_PIPE,
EI_SUB_GROUP_COMMIT_WRITE_PIPE,
EI_SUB_GROUP_REDUCE_ADD,
EI_SUB_GROUP_REDUCE_MAX,
EI_SUB_GROUP_REDUCE_MIN,
EI_SUB_GROUP_RESERVE_READ_PIPE,
EI_SUB_GROUP_RESERVE_WRITE_PIPE,
EI_SUB_GROUP_SCAN_EXCLUSIVE_ADD,
EI_SUB_GROUP_SCAN_EXCLUSIVE_MAX,
EI_SUB_GROUP_SCAN_EXCLUSIVE_MIN,
EI_SUB_GROUP_SCAN_INCLUSIVE_ADD,
EI_SUB_GROUP_SCAN_INCLUSIVE_MAX,
EI_SUB_GROUP_SCAN_INCLUSIVE_MIN,
EI_SUB_SAT,
EI_TAN,
EI_TANH,
EI_TANPI,
EI_TGAMMA,
EI_TRUNC,
EI_UPSAMPLE,
EI_VEC_STEP,
EI_VSTORE,
EI_VSTORE16,
EI_VSTORE2,
EI_VSTORE3,
EI_VSTORE4,
EI_VSTORE8,
EI_WORK_GROUP_COMMIT_READ_PIPE,
EI_WORK_GROUP_COMMIT_WRITE_PIPE,
EI_WORK_GROUP_REDUCE_ADD,
EI_WORK_GROUP_REDUCE_MAX,
EI_WORK_GROUP_REDUCE_MIN,
EI_WORK_GROUP_RESERVE_READ_PIPE,
EI_WORK_GROUP_RESERVE_WRITE_PIPE,
EI_WORK_GROUP_SCAN_EXCLUSIVE_ADD,
EI_WORK_GROUP_SCAN_EXCLUSIVE_MAX,
EI_WORK_GROUP_SCAN_EXCLUSIVE_MIN,
EI_WORK_GROUP_SCAN_INCLUSIVE_ADD,
EI_WORK_GROUP_SCAN_INCLUSIVE_MAX,
EI_WORK_GROUP_SCAN_INCLUSIVE_MIN,
EI_WRITE_IMAGEF,
EI_WRITE_IMAGEI,
EI_WRITE_IMAGEUI,
EI_NCOS,
EI_NEXP2,
EI_NFMA,
EI_NLOG2,
EI_NRCP,
EI_NRSQRT,
EI_NSIN,
EI_NSQRT,
EI_FTZ,
EI_FLDEXP,
EI_CLASS,
EI_RCBRT,
EI_LAST_MANGLED =
EI_RCBRT, /* The last library function with mangled name */
// Library functions with unmangled name.
EI_READ_PIPE_2,
EI_READ_PIPE_4,
EI_WRITE_PIPE_2,
EI_WRITE_PIPE_4,
EX_INTRINSICS_COUNT
};
enum ENamePrefix {
NOPFX,
NATIVE,
HALF
};
enum EType {
B8 = 1,
B16 = 2,
B32 = 3,
B64 = 4,
SIZE_MASK = 7,
FLOAT = 0x10,
INT = 0x20,
UINT = 0x30,
BASE_TYPE_MASK = 0x30,
U8 = UINT | B8,
U16 = UINT | B16,
U32 = UINT | B32,
U64 = UINT | B64,
I8 = INT | B8,
I16 = INT | B16,
I32 = INT | B32,
I64 = INT | B64,
F16 = FLOAT | B16,
F32 = FLOAT | B32,
F64 = FLOAT | B64,
IMG1DA = 0x80,
IMG1DB,
IMG2DA,
IMG1D,
IMG2D,
IMG3D,
SAMPLER,
EVENT,
DUMMY
};
enum EPtrKind {
BYVALUE = 0,
ADDR_SPACE = 0xF, // Address space takes value 0x1 ~ 0xF.
CONST = 0x10,
VOLATILE = 0x20
};
struct Param {
unsigned char ArgType;
unsigned char VectorSize;
unsigned char PtrKind;
unsigned char Reserved;
void reset() {
ArgType = 0;
VectorSize = 1;
PtrKind = 0;
}
Param() { reset(); }
template <typename Stream>
void mangleItanium(Stream& os);
};
static bool isMangled(EFuncId Id) {
return static_cast<unsigned>(Id) <= static_cast<unsigned>(EI_LAST_MANGLED);
}
static unsigned getEPtrKindFromAddrSpace(unsigned AS) {
assert(((AS + 1) & ~ADDR_SPACE) == 0);
return AS + 1;
}
static unsigned getAddrSpaceFromEPtrKind(unsigned Kind) {
Kind = Kind & ADDR_SPACE;
assert(Kind >= 1);
return Kind - 1;
}
};
class AMDGPULibFuncImpl : public AMDGPULibFuncBase {
public:
AMDGPULibFuncImpl() {}
virtual ~AMDGPULibFuncImpl() {}
/// Get unmangled name for mangled library function and name for unmangled
/// library function.
virtual std::string getName() const = 0;
virtual unsigned getNumArgs() const = 0;
EFuncId getId() const { return FuncId; }
ENamePrefix getPrefix() const { return FKind; }
bool isMangled() const { return AMDGPULibFuncBase::isMangled(FuncId); }
void setId(EFuncId id) { FuncId = id; }
virtual bool parseFuncName(StringRef &mangledName) = 0;
/// \return The mangled function name for mangled library functions
/// and unmangled function name for unmangled library functions.
virtual std::string mangle() const = 0;
void setName(StringRef N) { Name = N; }
void setPrefix(ENamePrefix pfx) { FKind = pfx; }
virtual FunctionType *getFunctionType(Module &M) const = 0;
protected:
EFuncId FuncId;
std::string Name;
ENamePrefix FKind;
};
/// Wrapper class for AMDGPULIbFuncImpl
class AMDGPULibFunc : public AMDGPULibFuncBase {
public:
explicit AMDGPULibFunc() : Impl(std::unique_ptr<AMDGPULibFuncImpl>()) {}
AMDGPULibFunc(const AMDGPULibFunc &F);
/// Clone a mangled library func with the Id \p Id and argument info from \p
/// CopyFrom.
explicit AMDGPULibFunc(EFuncId Id, const AMDGPULibFunc &CopyFrom);
/// Construct an unmangled library function on the fly.
explicit AMDGPULibFunc(StringRef FName, FunctionType *FT);
AMDGPULibFunc &operator=(const AMDGPULibFunc &F);
/// Get unmangled name for mangled library function and name for unmangled
/// library function.
std::string getName() const { return Impl->getName(); }
unsigned getNumArgs() const { return Impl->getNumArgs(); }
EFuncId getId() const { return Impl->getId(); }
ENamePrefix getPrefix() const { return Impl->getPrefix(); }
/// Get leading parameters for mangled lib functions.
Param *getLeads();
const Param *getLeads() const;
bool isMangled() const { return Impl->isMangled(); }
void setId(EFuncId Id) { Impl->setId(Id); }
bool parseFuncName(StringRef &MangledName) {
return Impl->parseFuncName(MangledName);
}
/// \return The mangled function name for mangled library functions
/// and unmangled function name for unmangled library functions.
std::string mangle() const { return Impl->mangle(); }
void setName(StringRef N) { Impl->setName(N); }
void setPrefix(ENamePrefix PFX) { Impl->setPrefix(PFX); }
FunctionType *getFunctionType(Module &M) const {
return Impl->getFunctionType(M);
}
static Function *getFunction(llvm::Module *M, const AMDGPULibFunc &fInfo);
static FunctionCallee getOrInsertFunction(llvm::Module *M,
const AMDGPULibFunc &fInfo);
static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr);
private:
/// Initialize as a mangled library function.
void initMangled();
std::unique_ptr<AMDGPULibFuncImpl> Impl;
};
class AMDGPUMangledLibFunc : public AMDGPULibFuncImpl {
public:
Param Leads[2];
explicit AMDGPUMangledLibFunc();
explicit AMDGPUMangledLibFunc(EFuncId id,
const AMDGPUMangledLibFunc &copyFrom);
std::string getName() const override;
unsigned getNumArgs() const override;
FunctionType *getFunctionType(Module &M) const override;
static StringRef getUnmangledName(StringRef MangledName);
bool parseFuncName(StringRef &mangledName) override;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const AMDGPULibFuncImpl *F) { return F->isMangled(); }
std::string mangle() const override;
private:
std::string mangleNameItanium() const;
std::string mangleName(StringRef Name) const;
bool parseUnmangledName(StringRef MangledName);
template <typename Stream> void writeName(Stream &OS) const;
};
class AMDGPUUnmangledLibFunc : public AMDGPULibFuncImpl {
FunctionType *FuncTy;
public:
explicit AMDGPUUnmangledLibFunc();
explicit AMDGPUUnmangledLibFunc(StringRef FName, FunctionType *FT) {
Name = FName;
FuncTy = FT;
}
std::string getName() const override { return Name; }
unsigned getNumArgs() const override;
FunctionType *getFunctionType(Module &M) const override { return FuncTy; }
bool parseFuncName(StringRef &Name) override;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const AMDGPULibFuncImpl *F) { return !F->isMangled(); }
std::string mangle() const override { return Name; }
void setFunctionType(FunctionType *FT) { FuncTy = FT; }
};
}
#endif // _AMDGPU_LIBFUNC_H_