1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2019-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 /*========================== begin_copyright_notice ============================
10 
11 This file is distributed under the University of Illinois Open Source License.
12 See LICENSE.TXT for details.
13 
14 ============================= end_copyright_notice ===========================*/
15 
16 // Originated from llvm source lib/IR/Function.cpp
17 // Function.cpp - Implement the Global object classes
18 
19 // Implementation of methods declared in llvm/GenXIntrinsics/GenXIntrinsics.h
20 
21 #include "llvm/GenXIntrinsics/GenXIntrinsics.h"
22 
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/Intrinsics.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/IR/Type.h"
29 #include "llvm/Support/CommandLine.h"
30 #include <llvm/ADT/StringExtras.h>
31 #include <llvm/ADT/StringMap.h>
32 #include <llvm/CodeGen/ValueTypes.h>
33 
34 #include "llvmVCWrapper/IR/DerivedTypes.h"
35 #include "llvmVCWrapper/IR/Intrinsics.h"
36 
37 #include <cstring>
38 
39 using namespace llvm;
40 
41 static cl::opt<bool> EnableGenXIntrinsicsCache(
42     "enable-genx-intrinsics-cache", cl::init(true), cl::Hidden,
43     cl::desc("Enable metadata caching of genx intrinsics"));
44 
45 #define MANGLE(STR) (STR)
46 
47 /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be
48 /// overloaded.
49 static bool isOverloaded(GenXIntrinsic::ID id);
50 
51 /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the
52 /// specified intrinsic into an array of IITDescriptors.
53 ///
54 void
55 getIntrinsicInfoTableEntries(GenXIntrinsic::ID id,
56                              SmallVectorImpl<Intrinsic::IITDescriptor> &T);
57 
58 /// IIT_Info - These are enumerators that describe the entries returned by the
59 /// getIntrinsicInfoTableEntries function.
60 ///
61 /// NOTE: This must be kept in synch with the copy in TblGen/IntrinsicEmitter!
62 enum IIT_Info {
63   // Common values should be encoded with 0-15.
64   IIT_Done = 0,
65   IIT_I1   = 1,
66   IIT_I8   = 2,
67   IIT_I16  = 3,
68   IIT_I32  = 4,
69   IIT_I64  = 5,
70   IIT_F16  = 6,
71   IIT_F32  = 7,
72   IIT_F64  = 8,
73   IIT_V2   = 9,
74   IIT_V4   = 10,
75   IIT_V8   = 11,
76   IIT_V16  = 12,
77   IIT_V32  = 13,
78   IIT_PTR  = 14,
79   IIT_ARG  = 15,
80 
81   // Values from 16+ are only encodable with the inefficient encoding.
82   IIT_V64  = 16,
83   IIT_MMX  = 17,
84   IIT_TOKEN = 18,
85   IIT_METADATA = 19,
86   IIT_EMPTYSTRUCT = 20,
87   IIT_STRUCT2 = 21,
88   IIT_STRUCT3 = 22,
89   IIT_STRUCT4 = 23,
90   IIT_STRUCT5 = 24,
91   IIT_EXTEND_ARG = 25,
92   IIT_TRUNC_ARG = 26,
93   IIT_ANYPTR = 27,
94   IIT_V1   = 28,
95   IIT_VARARG = 29,
96   IIT_HALF_VEC_ARG = 30,
97   IIT_SAME_VEC_WIDTH_ARG = 31,
98   IIT_PTR_TO_ARG = 32,
99   IIT_PTR_TO_ELT = 33,
100   IIT_VEC_OF_ANYPTRS_TO_ELT = 34,
101   IIT_I128 = 35,
102   IIT_V512 = 36,
103   IIT_V1024 = 37,
104   IIT_STRUCT6 = 38,
105   IIT_STRUCT7 = 39,
106   IIT_STRUCT8 = 40,
107   IIT_F128 = 41
108 };
109 
110 static void
DecodeIITType(unsigned & NextElt,ArrayRef<unsigned char> Infos,SmallVectorImpl<Intrinsic::IITDescriptor> & OutputTable)111 DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
112               SmallVectorImpl<Intrinsic::IITDescriptor> &OutputTable) {
113   using namespace Intrinsic;
114 
115   IIT_Info Info = IIT_Info(Infos[NextElt++]);
116   unsigned StructElts = 2;
117 
118   switch (Info) {
119   case IIT_Done:
120     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
121     return;
122   case IIT_VARARG:
123     OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));
124     return;
125   case IIT_MMX:
126     OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));
127     return;
128   case IIT_TOKEN:
129     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Token, 0));
130     return;
131   case IIT_METADATA:
132     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Metadata, 0));
133     return;
134   case IIT_F16:
135     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Half, 0));
136     return;
137   case IIT_F32:
138     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Float, 0));
139     return;
140   case IIT_F64:
141     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Double, 0));
142     return;
143   case IIT_F128:
144     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Quad, 0));
145     return;
146   case IIT_I1:
147     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 1));
148     return;
149   case IIT_I8:
150     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 8));
151     return;
152   case IIT_I16:
153     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer,16));
154     return;
155   case IIT_I32:
156     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 32));
157     return;
158   case IIT_I64:
159     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64));
160     return;
161   case IIT_I128:
162     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 128));
163     return;
164   case IIT_V1:
165     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 1));
166     DecodeIITType(NextElt, Infos, OutputTable);
167     return;
168   case IIT_V2:
169     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 2));
170     DecodeIITType(NextElt, Infos, OutputTable);
171     return;
172   case IIT_V4:
173     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 4));
174     DecodeIITType(NextElt, Infos, OutputTable);
175     return;
176   case IIT_V8:
177     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 8));
178     DecodeIITType(NextElt, Infos, OutputTable);
179     return;
180   case IIT_V16:
181     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 16));
182     DecodeIITType(NextElt, Infos, OutputTable);
183     return;
184   case IIT_V32:
185     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32));
186     DecodeIITType(NextElt, Infos, OutputTable);
187     return;
188   case IIT_V64:
189     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 64));
190     DecodeIITType(NextElt, Infos, OutputTable);
191     return;
192   case IIT_V512:
193     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 512));
194     DecodeIITType(NextElt, Infos, OutputTable);
195     return;
196   case IIT_V1024:
197     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 1024));
198     DecodeIITType(NextElt, Infos, OutputTable);
199     return;
200   case IIT_PTR:
201     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0));
202     DecodeIITType(NextElt, Infos, OutputTable);
203     return;
204   case IIT_ANYPTR: {  // [ANYPTR addrspace, subtype]
205     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer,
206                                              Infos[NextElt++]));
207     DecodeIITType(NextElt, Infos, OutputTable);
208     return;
209   }
210   case IIT_ARG: {
211     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
212     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo));
213     return;
214   }
215   case IIT_EXTEND_ARG: {
216     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
217     OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendArgument,
218                                              ArgInfo));
219     return;
220   }
221   case IIT_TRUNC_ARG: {
222     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
223     OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncArgument,
224                                              ArgInfo));
225     return;
226   }
227   case IIT_HALF_VEC_ARG: {
228     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
229     OutputTable.push_back(IITDescriptor::get(IITDescriptor::HalfVecArgument,
230                                              ArgInfo));
231     return;
232   }
233   case IIT_SAME_VEC_WIDTH_ARG: {
234     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
235     OutputTable.push_back(IITDescriptor::get(IITDescriptor::SameVecWidthArgument,
236                                              ArgInfo));
237     return;
238   }
239   case IIT_PTR_TO_ARG: {
240     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
241     OutputTable.push_back(IITDescriptor::get(IITDescriptor::PtrToArgument,
242                                              ArgInfo));
243     return;
244   }
245   case IIT_PTR_TO_ELT: {
246     unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
247     OutputTable.push_back(IITDescriptor::get(IITDescriptor::PtrToElt, ArgInfo));
248     return;
249   }
250   case IIT_VEC_OF_ANYPTRS_TO_ELT: {
251     unsigned short ArgNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
252     unsigned short RefNo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
253     OutputTable.push_back(
254         IITDescriptor::get(IITDescriptor::VecOfAnyPtrsToElt, ArgNo, RefNo));
255     return;
256   }
257   case IIT_EMPTYSTRUCT:
258     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0));
259     return;
260   case IIT_STRUCT8: ++StructElts; LLVM_FALLTHROUGH;
261   case IIT_STRUCT7: ++StructElts; LLVM_FALLTHROUGH;
262   case IIT_STRUCT6: ++StructElts; LLVM_FALLTHROUGH;
263   case IIT_STRUCT5: ++StructElts; LLVM_FALLTHROUGH;
264   case IIT_STRUCT4: ++StructElts; LLVM_FALLTHROUGH;
265   case IIT_STRUCT3: ++StructElts; LLVM_FALLTHROUGH;
266   case IIT_STRUCT2: {
267     OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct,StructElts));
268 
269     for (unsigned i = 0; i != StructElts; ++i)
270       DecodeIITType(NextElt, Infos, OutputTable);
271     return;
272   }
273   }
274   llvm_unreachable("unhandled");
275 }
276 
DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> & Infos,ArrayRef<Type * > Tys,LLVMContext & Context)277 static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
278                              ArrayRef<Type*> Tys, LLVMContext &Context) {
279   using namespace Intrinsic;
280 
281   IITDescriptor D = Infos.front();
282   Infos = Infos.slice(1);
283 
284   switch (D.Kind) {
285   case IITDescriptor::Void: return Type::getVoidTy(Context);
286   case IITDescriptor::VarArg: return Type::getVoidTy(Context);
287   case IITDescriptor::MMX: return Type::getX86_MMXTy(Context);
288   case IITDescriptor::Token: return Type::getTokenTy(Context);
289   case IITDescriptor::Metadata: return Type::getMetadataTy(Context);
290   case IITDescriptor::Half: return Type::getHalfTy(Context);
291   case IITDescriptor::Float: return Type::getFloatTy(Context);
292   case IITDescriptor::Double: return Type::getDoubleTy(Context);
293   case IITDescriptor::Quad: return Type::getFP128Ty(Context);
294 
295   case IITDescriptor::Integer:
296     return IntegerType::get(Context, D.Integer_Width);
297   case IITDescriptor::Vector:
298     return VCINTR::getVectorType(DecodeFixedType(Infos, Tys, Context),D.Vector_Width);
299   case IITDescriptor::Pointer:
300     return PointerType::get(DecodeFixedType(Infos, Tys, Context),
301                             D.Pointer_AddressSpace);
302   case IITDescriptor::Struct: {
303     SmallVector<Type *, 8> Elts;
304     for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)
305       Elts.push_back(DecodeFixedType(Infos, Tys, Context));
306     return StructType::get(Context, Elts);
307   }
308   case IITDescriptor::Argument:
309     return Tys[D.getArgumentNumber()];
310   case IITDescriptor::ExtendArgument: {
311     Type *Ty = Tys[D.getArgumentNumber()];
312     if (VectorType *VTy = dyn_cast<VectorType>(Ty))
313       return VectorType::getExtendedElementVectorType(VTy);
314 
315     return IntegerType::get(Context, 2 * cast<IntegerType>(Ty)->getBitWidth());
316   }
317   case IITDescriptor::TruncArgument: {
318     Type *Ty = Tys[D.getArgumentNumber()];
319     if (VectorType *VTy = dyn_cast<VectorType>(Ty))
320       return VectorType::getTruncatedElementVectorType(VTy);
321 
322     IntegerType *ITy = cast<IntegerType>(Ty);
323     assert(ITy->getBitWidth() % 2 == 0);
324     return IntegerType::get(Context, ITy->getBitWidth() / 2);
325   }
326   case IITDescriptor::HalfVecArgument:
327     return VectorType::getHalfElementsVectorType(cast<VectorType>(
328                                                   Tys[D.getArgumentNumber()]));
329   case IITDescriptor::SameVecWidthArgument: {
330     Type *EltTy = DecodeFixedType(Infos, Tys, Context);
331     Type *Ty = Tys[D.getArgumentNumber()];
332     if (VectorType *VTy = dyn_cast<VectorType>(Ty)) {
333       return VCINTR::getVectorType(EltTy,
334                                    VCINTR::VectorType::getNumElements(VTy));
335     }
336     llvm_unreachable("unhandled");
337   }
338   case IITDescriptor::PtrToArgument: {
339     Type *Ty = Tys[D.getArgumentNumber()];
340     return PointerType::getUnqual(Ty);
341   }
342   case IITDescriptor::PtrToElt: {
343     Type *Ty = Tys[D.getArgumentNumber()];
344     VectorType *VTy = dyn_cast<VectorType>(Ty);
345     if (!VTy)
346       llvm_unreachable("Expected an argument of Vector Type");
347     Type *EltTy = cast<VectorType>(VTy)->getElementType();
348     return PointerType::getUnqual(EltTy);
349   }
350   case IITDescriptor::VecOfAnyPtrsToElt:
351     // Return the overloaded type (which determines the pointers address space)
352     return Tys[D.getOverloadArgNumber()];
353   default:
354     break;
355   }
356   llvm_unreachable("unhandled");
357 }
358 
359 #define GET_INTRINSIC_GENERATOR_GLOBAL
360 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
361 #undef GET_INTRINSIC_GENERATOR_GLOBAL
362 
getIntrinsicInfoTableEntries(GenXIntrinsic::ID id,SmallVectorImpl<Intrinsic::IITDescriptor> & T)363 void GenXIntrinsic::getIntrinsicInfoTableEntries(
364     GenXIntrinsic::ID id, SmallVectorImpl<Intrinsic::IITDescriptor> &T) {
365   assert(id > GenXIntrinsic::not_genx_intrinsic);
366   id = static_cast<GenXIntrinsic::ID>(id - GenXIntrinsic::not_genx_intrinsic);
367   assert(id < sizeof(IIT_Table) / sizeof(*IIT_Table));
368 
369   // Check to see if the intrinsic's type was expressible by the table.
370   unsigned TableVal = IIT_Table[id - 1];
371 
372   // Decode the TableVal into an array of IITValues.
373   SmallVector<unsigned char, 8> IITValues;
374   ArrayRef<unsigned char> IITEntries;
375   unsigned NextElt = 0;
376   if ((TableVal >> 31) != 0) {
377     // This is an offset into the IIT_LongEncodingTable.
378     IITEntries = IIT_LongEncodingTable;
379 
380     // Strip sentinel bit.
381     NextElt = (TableVal << 1) >> 1;
382   } else {
383     // Decode the TableVal into an array of IITValues.  If the entry was encoded
384     // into a single word in the table itself, decode it now.
385     do {
386       IITValues.push_back(TableVal & 0xF);
387       TableVal >>= 4;
388     } while (TableVal);
389 
390     IITEntries = IITValues;
391     NextElt = 0;
392   }
393 
394   // Okay, decode the table into the output vector of IITDescriptors.
395   DecodeIITType(NextElt, IITEntries, T);
396   while (NextElt != IITEntries.size() && IITEntries[NextElt] != 0)
397     DecodeIITType(NextElt, IITEntries, T);
398 }
399 
400 /// Returns a stable mangling for the type specified for use in the name
401 /// mangling scheme used by 'any' types in intrinsic signatures.  The mangling
402 /// of named types is simply their name.  Manglings for unnamed types consist
403 /// of a prefix ('p' for pointers, 'a' for arrays, 'f_' for functions)
404 /// combined with the mangling of their component types.  A vararg function
405 /// type will have a suffix of 'vararg'.  Since function types can contain
406 /// other function types, we close a function type mangling with suffix 'f'
407 /// which can't be confused with it's prefix.  This ensures we don't have
408 /// collisions between two unrelated function types. Otherwise, you might
409 /// parse ffXX as f(fXX) or f(fX)X.  (X is a placeholder for any other type.)
getMangledTypeStr(Type * Ty)410 static std::string getMangledTypeStr(Type* Ty) {
411   std::string Result;
412   if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
413     Result += "p" + llvm::utostr(PTyp->getAddressSpace()) +
414       getMangledTypeStr(PTyp->getElementType());
415   } else if (ArrayType* ATyp = dyn_cast<ArrayType>(Ty)) {
416     Result += "a" + llvm::utostr(ATyp->getNumElements()) +
417       getMangledTypeStr(ATyp->getElementType());
418   } else if (StructType* STyp = dyn_cast<StructType>(Ty)) {
419     if(!STyp->isLiteral())
420         Result += STyp->getName();
421     else {
422         Result += "s" + llvm::utostr(STyp->getNumElements());
423         for(unsigned int i = 0; i < STyp->getNumElements(); i++)
424             Result += getMangledTypeStr(STyp->getElementType(i));
425     }
426   } else if (FunctionType* FT = dyn_cast<FunctionType>(Ty)) {
427     Result += "f_" + getMangledTypeStr(FT->getReturnType());
428     for (size_t i = 0; i < FT->getNumParams(); i++)
429       Result += getMangledTypeStr(FT->getParamType(i));
430     if (FT->isVarArg())
431       Result += "vararg";
432     // Ensure nested function types are distinguishable.
433     Result += "f";
434   } else if (isa<VectorType>(Ty))
435     Result += "v" +
436               utostr(VCINTR::VectorType::getNumElements(cast<VectorType>(Ty))) +
437               getMangledTypeStr(cast<VectorType>(Ty)->getElementType());
438   else if (Ty)
439     Result += EVT::getEVT(Ty).getEVTString();
440   return Result;
441 }
442 
443 static const char * const GenXIntrinsicNameTable[] = {
444     "not_genx_intrinsic",
445 #define GET_INTRINSIC_NAME_TABLE
446 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
447 #undef GET_INTRINSIC_NAME_TABLE
448   };
449 
isOverloaded(GenXIntrinsic::ID id)450 bool isOverloaded(GenXIntrinsic::ID id) {
451   assert(isGenXIntrinsic(id) && "Invalid intrinsic ID!");
452   id = static_cast<GenXIntrinsic::ID>(id - GenXIntrinsic::not_genx_intrinsic);
453 #define GET_INTRINSIC_OVERLOAD_TABLE
454 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
455 #undef GET_INTRINSIC_OVERLOAD_TABLE
456 }
457 
458 /// This defines the "getAttributes(ID id)" method.
459 #define GET_INTRINSIC_ATTRIBUTES
460 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
461 #undef GET_INTRINSIC_ATTRIBUTES
462 
463 static StringRef GenXIntrinsicMDName{ "genx_intrinsic_id" };
464 
isSupportedPlatform(const std::string & CPU,unsigned id)465 bool GenXIntrinsic::isSupportedPlatform(const std::string &CPU, unsigned id) {
466 #define GET_INTRINSIC_PLATFORMS
467 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
468 #undef GET_INTRINSIC_PLATFORMS
469   assert(SupportedIntrinsics.find(CPU) != SupportedIntrinsics.end() &&
470          "Unknown Platform");
471   assert(GenXIntrinsic::isGenXIntrinsic(id) &&
472          "this function should be used only for GenXIntrinsics");
473   auto PlatformInfoIt = SupportedIntrinsics.find(CPU);
474   if (PlatformInfoIt == SupportedIntrinsics.end())
475     return false;
476   const auto &IntrinsicInfo = PlatformInfoIt->second;
477   size_t IntrinsicIdx = id - GenXIntrinsic::ID::not_genx_intrinsic - 1;
478   if (IntrinsicIdx < IntrinsicInfo.size())
479     return IntrinsicInfo[IntrinsicIdx];
480   return false;
481 }
482 
483 /// Table of per-target intrinsic name tables.
484 #define GET_INTRINSIC_TARGET_DATA
485 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
486 #undef GET_INTRINSIC_TARGET_DATA
487 
isOverloadedArg(unsigned IntrinID,unsigned ArgNum)488 bool GenXIntrinsic::isOverloadedArg(unsigned IntrinID, unsigned ArgNum) {
489 #define GET_INTRINSIC_OVERLOAD_ARGS_TABLE
490 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
491 #undef GET_INTRINSIC_OVERLOAD_ARGS_TABLE
492 }
493 
isOverloadedRet(unsigned IntrinID)494 bool GenXIntrinsic::isOverloadedRet(unsigned IntrinID) {
495 #define GET_INTRINSIC_OVERLOAD_RET_TABLE
496 #include "llvm/GenXIntrinsics/GenXIntrinsicDescription.gen"
497 #undef GET_INTRINSIC_OVERLOAD_RET_TABLE
498 }
499 
500 /// Find the segment of \c IntrinsicNameTable for intrinsics with the same
501 /// target as \c Name, or the generic table if \c Name is not target specific.
502 ///
503 /// Returns the relevant slice of \c IntrinsicNameTable
findTargetSubtable(StringRef Name)504 static ArrayRef<const char *> findTargetSubtable(StringRef Name) {
505   assert(Name.startswith("llvm.genx."));
506 
507   ArrayRef<IntrinsicTargetInfo> Targets(TargetInfos);
508   // Drop "llvm." and take the first dotted component. That will be the target
509   // if this is target specific.
510   StringRef Target = Name.drop_front(5).split('.').first;
511   auto It = std::lower_bound(Targets.begin(), Targets.end(), Target,
512                              [](const IntrinsicTargetInfo &TI,
513                                 StringRef Target) { return TI.Name < Target; });
514   // We've either found the target or just fall back to the generic set, which
515   // is always first.
516   const auto &TI = It != Targets.end() && It->Name == Target ? *It : Targets[0];
517   return makeArrayRef(&GenXIntrinsicNameTable[1] + TI.Offset, TI.Count);
518 }
519 
getGenXIntrinsicID(const Function * F)520 GenXIntrinsic::ID GenXIntrinsic::getGenXIntrinsicID(const Function *F) {
521   assert(F);
522   llvm::StringRef Name = F->getName();
523   if (!Name.startswith(getGenXIntrinsicPrefix()))
524     return GenXIntrinsic::not_genx_intrinsic;
525 
526   // Check metadata cache.
527   if (auto *MD = F->getMetadata(GenXIntrinsicMDName)) {
528     assert(MD->getNumOperands() == 1 && "Invalid intrinsic metadata");
529     auto Val = cast<ValueAsMetadata>(MD->getOperand(0))->getValue();
530     GenXIntrinsic::ID Id =
531         static_cast<GenXIntrinsic::ID>(cast<ConstantInt>(Val)->getZExtValue());
532 
533     // we need to check that metadata is correct and can be actually used
534     if (isGenXIntrinsic(Id)) {
535       const char *NamePrefix =
536           GenXIntrinsicNameTable[Id - GenXIntrinsic::not_genx_intrinsic];
537       if (Name.startswith(NamePrefix))
538         return Id;
539     }
540   }
541 
542   // Fallback to string lookup.
543   auto ID = lookupGenXIntrinsicID(Name);
544   assert(ID != GenXIntrinsic::not_genx_intrinsic && "Intrinsic not found!");
545   return ID;
546 }
547 
getGenXName(GenXIntrinsic::ID id,ArrayRef<Type * > Tys)548 std::string GenXIntrinsic::getGenXName(GenXIntrinsic::ID id,
549                                        ArrayRef<Type *> Tys) {
550   assert(isGenXIntrinsic(id) && "Invalid intrinsic ID!");
551   assert(Tys.empty() ||
552          (isOverloaded(id) && "Non-overloadable intrinsic was overloaded!"));
553   id = static_cast<GenXIntrinsic::ID>(id - GenXIntrinsic::not_genx_intrinsic);
554   std::string Result(GenXIntrinsicNameTable[id]);
555   for (Type *Ty : Tys) {
556     Result += "." + getMangledTypeStr(Ty);
557   }
558   return Result;
559 }
560 
lookupGenXIntrinsicID(StringRef Name)561 GenXIntrinsic::ID GenXIntrinsic::lookupGenXIntrinsicID(StringRef Name) {
562   ArrayRef<const char *> NameTable = findTargetSubtable(Name);
563   int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
564   if (Idx == -1)
565     return GenXIntrinsic::not_genx_intrinsic;
566 
567   // Intrinsic IDs correspond to the location in IntrinsicNameTable, but we have
568   // an index into a sub-table.
569   int Adjust = NameTable.data() - GenXIntrinsicNameTable;
570   auto ID = static_cast<GenXIntrinsic::ID>(Idx + Adjust + GenXIntrinsic::not_genx_intrinsic);
571 
572   // If the intrinsic is not overloaded, require an exact match. If it is
573   // overloaded, require either exact or prefix match.
574   assert(Name.size() >= strlen(NameTable[Idx]) &&
575          "Expected either exact or prefix match");
576   assert((Name.size() == strlen(NameTable[Idx])) ||
577          (isOverloaded(ID) && "Non-overloadable intrinsic was overloaded!"));
578   return ID;
579 }
580 
getGenXType(LLVMContext & Context,GenXIntrinsic::ID id,ArrayRef<Type * > Tys)581 FunctionType *GenXIntrinsic::getGenXType(LLVMContext &Context,
582                                          GenXIntrinsic::ID id,
583                                          ArrayRef<Type *> Tys) {
584   SmallVector<Intrinsic::IITDescriptor, 8> Table;
585   getIntrinsicInfoTableEntries(id, Table);
586 
587   ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
588   Type *ResultTy = DecodeFixedType(TableRef, Tys, Context);
589 
590   SmallVector<Type *, 8> ArgTys;
591   while (!TableRef.empty())
592     ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context));
593 
594   // DecodeFixedType returns Void for IITDescriptor::Void and
595   // IITDescriptor::VarArg If we see void type as the type of the last argument,
596   // it is vararg intrinsic
597   if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) {
598     ArgTys.pop_back();
599     return FunctionType::get(ResultTy, ArgTys, true);
600   }
601   return FunctionType::get(ResultTy, ArgTys, false);
602 }
603 
604 #ifndef NDEBUG
605 // Sanity check for intrinsic types.
606 // After translation from SPIRV literal structures become identified.
607 // However, if intrinsic returns multiple values, then it returns
608 // literal structure.
609 // Having this, compatible intrinsics will have same argument types
610 // and either same return types or layout identical structure types.
isCompatibleIntrinsicSignature(FunctionType * DecodedType,FunctionType * FoundType)611 static bool isCompatibleIntrinsicSignature(FunctionType *DecodedType,
612                                            FunctionType *FoundType) {
613   if (DecodedType == FoundType)
614     return true;
615 
616   if (DecodedType->params() != FoundType->params())
617     return false;
618 
619   // Return types are different. Check for structures.
620   auto *DecStrTy = dyn_cast<StructType>(DecodedType->getReturnType());
621   auto *FoundStrTy = dyn_cast<StructType>(FoundType->getReturnType());
622   if (!DecStrTy || !FoundStrTy)
623     return false;
624 
625   return DecStrTy->isLayoutIdentical(FoundStrTy);
626 }
627 #endif
628 
getGenXDeclaration(Module * M,GenXIntrinsic::ID id,ArrayRef<Type * > Tys)629 Function *GenXIntrinsic::getGenXDeclaration(Module *M, GenXIntrinsic::ID id,
630                                             ArrayRef<Type *> Tys) {
631   assert(isGenXNonTrivialIntrinsic(id));
632   assert(Tys.empty() ||
633          (isOverloaded(id) && "Non-overloadable intrinsic was overloaded!"));
634 
635   auto GenXName = getGenXName(id, Tys);
636   FunctionType *FTy = getGenXType(M->getContext(), id, Tys);
637   Function *F = M->getFunction(GenXName);
638   if (!F)
639     F = Function::Create(FTy, GlobalVariable::ExternalLinkage, GenXName, M);
640 
641   assert(isCompatibleIntrinsicSignature(FTy, F->getFunctionType()) &&
642          "Module contains intrinsic declaration with incompatible type!");
643 
644   resetGenXAttributes(F);
645   return F;
646 }
647 
resetGenXAttributes(Function * F)648 void GenXIntrinsic::resetGenXAttributes(Function *F) {
649 
650   assert(F);
651 
652   GenXIntrinsic::ID GXID = getGenXIntrinsicID(F);
653 
654   assert(GXID != GenXIntrinsic::not_genx_intrinsic);
655 
656   // Since Function::isIntrinsic() will return true due to llvm. prefix,
657   // Module::getOrInsertFunction fails to add the attributes. explicitly adding
658   // the attribute to handle this problem. This since is setup on the function
659   // declaration, attribute assignment is global and hence this approach
660   // suffices.
661   F->setAttributes(GenXIntrinsic::getAttributes(F->getContext(), GXID));
662 
663   // Cache intrinsic ID in metadata.
664   if (EnableGenXIntrinsicsCache && !F->hasMetadata(GenXIntrinsicMDName)) {
665     LLVMContext &Ctx = F->getContext();
666     auto *Ty = IntegerType::getInt32Ty(Ctx);
667     auto *Cached = ConstantInt::get(Ty, GXID);
668     auto *MD = MDNode::get(Ctx, {ConstantAsMetadata::get(Cached)});
669     F->addMetadata(GenXIntrinsicMDName, *MD);
670   }
671 }
672 
getAnyName(unsigned id,ArrayRef<Type * > Tys)673 std::string GenXIntrinsic::getAnyName(unsigned id, ArrayRef<Type *> Tys) {
674   assert(isAnyIntrinsic(id));
675   if (id == not_any_intrinsic) {
676     std::string Result("not_any_intrinsic");
677     for (Type *Ty : Tys) {
678       Result += "." + getMangledTypeStr(Ty);
679     }
680     return Result;
681   } else if (isGenXIntrinsic(id))
682     return getGenXName((GenXIntrinsic::ID)id, Tys);
683   else
684     return VCINTR::Intrinsic::getName((Intrinsic::ID)id, Tys);
685 }
686 
getLSCVectorSize(const Instruction * I)687 GenXIntrinsic::LSCVectorSize GenXIntrinsic::getLSCVectorSize(
688     const Instruction *I) {
689   assert(isLSC(I));
690   switch (getLSCCategory(I)) {
691     case LSCCategory::Load:
692     case LSCCategory::Prefetch:
693     case LSCCategory::Store:
694     case LSCCategory::Atomic:
695       return static_cast<LSCVectorSize>(
696           cast<ConstantInt>(I->getOperand(7))->getZExtValue());
697     case LSCCategory::LegacyAtomic:
698       return static_cast<LSCVectorSize>(
699           cast<ConstantInt>(I->getOperand(8))->getZExtValue());
700     case LSCCategory::Fence:
701     case LSCCategory::Load2D:
702     case LSCCategory::Prefetch2D:
703     case LSCCategory::Store2D:
704     case LSCCategory::NotLSC:
705       return LSCVectorSize::N0;
706   }
707   llvm_unreachable("Unknown LSC category");
708 }
709 
getLSCDataSize(const Instruction * I)710 GenXIntrinsic::LSCDataSize GenXIntrinsic::getLSCDataSize(
711     const Instruction *I) {
712   assert(isLSC(I));
713   switch (getLSCCategory(I)) {
714     case LSCCategory::Load:
715     case LSCCategory::Prefetch:
716     case LSCCategory::Store:
717     case LSCCategory::LegacyAtomic:
718     case LSCCategory::Atomic:
719       return static_cast<LSCDataSize>(
720           cast<ConstantInt>(I->getOperand(6))->getZExtValue());
721     case LSCCategory::Load2D:
722     case LSCCategory::Prefetch2D:
723     case LSCCategory::Store2D:
724       return static_cast<LSCDataSize>(
725           cast<ConstantInt>(I->getOperand(3))->getZExtValue());
726     case LSCCategory::Fence:
727     case LSCCategory::NotLSC:
728       return LSCDataSize::Invalid;
729   }
730   llvm_unreachable("Unknown LSC category");
731 }
732 
getLSCDataOrder(const Instruction * I)733 GenXIntrinsic::LSCDataOrder GenXIntrinsic::getLSCDataOrder(
734     const Instruction *I) {
735   assert(isLSC(I));
736   switch (getLSCCategory(I)) {
737     case LSCCategory::Load:
738     case LSCCategory::Prefetch:
739     case LSCCategory::Store:
740     case LSCCategory::Atomic:
741       return static_cast<LSCDataOrder>(
742           cast<ConstantInt>(I->getOperand(8))->getZExtValue());
743     case LSCCategory::LegacyAtomic:
744       return static_cast<LSCDataOrder>(
745           cast<ConstantInt>(I->getOperand(7))->getZExtValue());
746     case LSCCategory::Load2D:
747     case LSCCategory::Prefetch2D:
748     case LSCCategory::Store2D:
749       return static_cast<LSCDataOrder>(
750           cast<ConstantInt>(I->getOperand(4))->getZExtValue());
751     case LSCCategory::Fence:
752     case LSCCategory::NotLSC:
753       return LSCDataOrder::Invalid;
754   }
755   llvm_unreachable("Unknown LSC category");
756 }
757 
getLSCWidth(const Instruction * I)758 unsigned GenXIntrinsic::getLSCWidth(const Instruction *I) {
759   assert(isLSC(I));
760   switch(getLSCCategory(I)) {
761     case LSCCategory::Load:
762     case LSCCategory::Prefetch:
763     case LSCCategory::Store:
764     case LSCCategory::Fence:
765     case LSCCategory::LegacyAtomic:
766     case LSCCategory::Atomic: {
767     case LSCCategory::Prefetch2D:
768       if (auto VT = dyn_cast<VectorType>(I->getOperand(0)->getType()))
769         return VCINTR::VectorType::getNumElements(VT);
770       return 1;
771     }
772     case LSCCategory::Load2D:
773     case LSCCategory::Store2D:
774     case LSCCategory::NotLSC:
775       return 1;
776   }
777   llvm_unreachable("Unknown LSC category");
778 }
779 
780