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() = default;
328   virtual ~AMDGPULibFuncImpl() = default;
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 &copyFrom);
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