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 &copyFrom);
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