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