xref: /freebsd/contrib/llvm-project/clang/utils/TableGen/SveEmitter.cpp (revision 59c8e88e72633afbc47a4ace0d2170d00d51f7dc)
1 //===- SveEmitter.cpp - Generate arm_sve.h for use with clang -*- 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 // This tablegen backend is responsible for emitting arm_sve.h, which includes
10 // a declaration and definition of each function specified by the ARM C/C++
11 // Language Extensions (ACLE).
12 //
13 // For details, visit:
14 //  https://developer.arm.com/architectures/system-architectures/software-standards/acle
15 //
16 // Each SVE instruction is implemented in terms of 1 or more functions which
17 // are suffixed with the element type of the input vectors.  Functions may be
18 // implemented in terms of generic vector operations such as +, *, -, etc. or
19 // by calling a __builtin_-prefixed function which will be handled by clang's
20 // CodeGen library.
21 //
22 // See also the documentation in include/clang/Basic/arm_sve.td.
23 //
24 //===----------------------------------------------------------------------===//
25 
26 #include "llvm/ADT/STLExtras.h"
27 #include "llvm/ADT/StringMap.h"
28 #include "llvm/ADT/ArrayRef.h"
29 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/TableGen/Record.h"
31 #include "llvm/TableGen/Error.h"
32 #include <string>
33 #include <sstream>
34 #include <set>
35 #include <cctype>
36 #include <tuple>
37 
38 using namespace llvm;
39 
40 enum ClassKind {
41   ClassNone,
42   ClassS,     // signed/unsigned, e.g., "_s8", "_u8" suffix
43   ClassG,     // Overloaded name without type suffix
44 };
45 
46 using TypeSpec = std::string;
47 
48 namespace {
49 
50 class ImmCheck {
51   unsigned Arg;
52   unsigned Kind;
53   unsigned ElementSizeInBits;
54 
55 public:
56   ImmCheck(unsigned Arg, unsigned Kind, unsigned ElementSizeInBits = 0)
57       : Arg(Arg), Kind(Kind), ElementSizeInBits(ElementSizeInBits) {}
58   ImmCheck(const ImmCheck &Other) = default;
59   ~ImmCheck() = default;
60 
61   unsigned getArg() const { return Arg; }
62   unsigned getKind() const { return Kind; }
63   unsigned getElementSizeInBits() const { return ElementSizeInBits; }
64 };
65 
66 class SVEType {
67   TypeSpec TS;
68   bool Float, Signed, Immediate, Void, Constant, Pointer, BFloat;
69   bool DefaultType, IsScalable, Predicate, PredicatePattern, PrefetchOp,
70       Svcount;
71   unsigned Bitwidth, ElementBitwidth, NumVectors;
72 
73 public:
74   SVEType() : SVEType(TypeSpec(), 'v') {}
75 
76   SVEType(TypeSpec TS, char CharMod)
77       : TS(TS), Float(false), Signed(true), Immediate(false), Void(false),
78         Constant(false), Pointer(false), BFloat(false), DefaultType(false),
79         IsScalable(true), Predicate(false), PredicatePattern(false),
80         PrefetchOp(false), Svcount(false), Bitwidth(128), ElementBitwidth(~0U),
81         NumVectors(1) {
82     if (!TS.empty())
83       applyTypespec();
84     applyModifier(CharMod);
85   }
86 
87   bool isPointer() const { return Pointer; }
88   bool isVoidPointer() const { return Pointer && Void; }
89   bool isSigned() const { return Signed; }
90   bool isImmediate() const { return Immediate; }
91   bool isScalar() const { return NumVectors == 0; }
92   bool isVector() const { return NumVectors > 0; }
93   bool isScalableVector() const { return isVector() && IsScalable; }
94   bool isChar() const { return ElementBitwidth == 8; }
95   bool isVoid() const { return Void & !Pointer; }
96   bool isDefault() const { return DefaultType; }
97   bool isFloat() const { return Float && !BFloat; }
98   bool isBFloat() const { return BFloat && !Float; }
99   bool isFloatingPoint() const { return Float || BFloat; }
100   bool isInteger() const {
101     return !isFloatingPoint() && !Predicate && !Svcount;
102   }
103   bool isScalarPredicate() const {
104     return !isFloatingPoint() && Predicate && NumVectors == 0;
105   }
106   bool isPredicateVector() const { return Predicate; }
107   bool isPredicatePattern() const { return PredicatePattern; }
108   bool isPrefetchOp() const { return PrefetchOp; }
109   bool isSvcount() const { return Svcount; }
110   bool isConstant() const { return Constant; }
111   unsigned getElementSizeInBits() const { return ElementBitwidth; }
112   unsigned getNumVectors() const { return NumVectors; }
113 
114   unsigned getNumElements() const {
115     assert(ElementBitwidth != ~0U);
116     return Bitwidth / ElementBitwidth;
117   }
118   unsigned getSizeInBits() const {
119     return Bitwidth;
120   }
121 
122   /// Return the string representation of a type, which is an encoded
123   /// string for passing to the BUILTIN() macro in Builtins.def.
124   std::string builtin_str() const;
125 
126   /// Return the C/C++ string representation of a type for use in the
127   /// arm_sve.h header file.
128   std::string str() const;
129 
130 private:
131   /// Creates the type based on the typespec string in TS.
132   void applyTypespec();
133 
134   /// Applies a prototype modifier to the type.
135   void applyModifier(char Mod);
136 };
137 
138 
139 class SVEEmitter;
140 
141 /// The main grunt class. This represents an instantiation of an intrinsic with
142 /// a particular typespec and prototype.
143 class Intrinsic {
144   /// The unmangled name.
145   std::string Name;
146 
147   /// The name of the corresponding LLVM IR intrinsic.
148   std::string LLVMName;
149 
150   /// Intrinsic prototype.
151   std::string Proto;
152 
153   /// The base type spec for this intrinsic.
154   TypeSpec BaseTypeSpec;
155 
156   /// The base class kind. Most intrinsics use ClassS, which has full type
157   /// info for integers (_s32/_u32), or ClassG which is used for overloaded
158   /// intrinsics.
159   ClassKind Class;
160 
161   /// The architectural #ifdef guard.
162   std::string Guard;
163 
164   // The merge suffix such as _m, _x or _z.
165   std::string MergeSuffix;
166 
167   /// The types of return value [0] and parameters [1..].
168   std::vector<SVEType> Types;
169 
170   /// The "base type", which is VarType('d', BaseTypeSpec).
171   SVEType BaseType;
172 
173   uint64_t Flags;
174 
175   SmallVector<ImmCheck, 2> ImmChecks;
176 
177 public:
178   Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
179             StringRef MergeSuffix, uint64_t MemoryElementTy, StringRef LLVMName,
180             uint64_t Flags, ArrayRef<ImmCheck> ImmChecks, TypeSpec BT,
181             ClassKind Class, SVEEmitter &Emitter, StringRef Guard);
182 
183   ~Intrinsic()=default;
184 
185   std::string getName() const { return Name; }
186   std::string getLLVMName() const { return LLVMName; }
187   std::string getProto() const { return Proto; }
188   TypeSpec getBaseTypeSpec() const { return BaseTypeSpec; }
189   SVEType getBaseType() const { return BaseType; }
190 
191   StringRef getGuard() const { return Guard; }
192   ClassKind getClassKind() const { return Class; }
193 
194   SVEType getReturnType() const { return Types[0]; }
195   ArrayRef<SVEType> getTypes() const { return Types; }
196   SVEType getParamType(unsigned I) const { return Types[I + 1]; }
197   unsigned getNumParams() const { return Proto.size() - 1; }
198 
199   uint64_t getFlags() const { return Flags; }
200   bool isFlagSet(uint64_t Flag) const { return Flags & Flag;}
201 
202   ArrayRef<ImmCheck> getImmChecks() const { return ImmChecks; }
203 
204   /// Return the type string for a BUILTIN() macro in Builtins.def.
205   std::string getBuiltinTypeStr();
206 
207   /// Return the name, mangled with type information. The name is mangled for
208   /// ClassS, so will add type suffixes such as _u32/_s32.
209   std::string getMangledName() const { return mangleName(ClassS); }
210 
211   /// As above, but mangles the LLVM name instead.
212   std::string getMangledLLVMName() const { return mangleLLVMName(); }
213 
214   /// Returns true if the intrinsic is overloaded, in that it should also generate
215   /// a short form without the type-specifiers, e.g. 'svld1(..)' instead of
216   /// 'svld1_u32(..)'.
217   static bool isOverloadedIntrinsic(StringRef Name) {
218     auto BrOpen = Name.find('[');
219     auto BrClose = Name.find(']');
220     return BrOpen != std::string::npos && BrClose != std::string::npos;
221   }
222 
223   /// Return true if the intrinsic takes a splat operand.
224   bool hasSplat() const {
225     // These prototype modifiers are described in arm_sve.td.
226     return Proto.find_first_of("ajfrKLR@") != std::string::npos;
227   }
228 
229   /// Return the parameter index of the splat operand.
230   unsigned getSplatIdx() const {
231     // These prototype modifiers are described in arm_sve.td.
232     auto Idx = Proto.find_first_of("ajfrKLR@");
233     assert(Idx != std::string::npos && Idx > 0 &&
234            "Prototype has no splat operand");
235     return Idx - 1;
236   }
237 
238   /// Emits the intrinsic declaration to the ostream.
239   void emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter) const;
240 
241 private:
242   std::string getMergeSuffix() const { return MergeSuffix; }
243   std::string mangleName(ClassKind LocalCK) const;
244   std::string mangleLLVMName() const;
245   std::string replaceTemplatedArgs(std::string Name, TypeSpec TS,
246                                    std::string Proto) const;
247 };
248 
249 class SVEEmitter {
250 private:
251   // The reinterpret builtins are generated separately because they
252   // need the cross product of all types (121 functions in total),
253   // which is inconvenient to specify in the arm_sve.td file or
254   // generate in CGBuiltin.cpp.
255   struct ReinterpretTypeInfo {
256     const char *Suffix;
257     const char *Type;
258     const char *BuiltinType;
259   };
260   SmallVector<ReinterpretTypeInfo, 12> Reinterprets = {
261       {"s8", "svint8_t", "q16Sc"},   {"s16", "svint16_t", "q8Ss"},
262       {"s32", "svint32_t", "q4Si"},  {"s64", "svint64_t", "q2SWi"},
263       {"u8", "svuint8_t", "q16Uc"},  {"u16", "svuint16_t", "q8Us"},
264       {"u32", "svuint32_t", "q4Ui"}, {"u64", "svuint64_t", "q2UWi"},
265       {"f16", "svfloat16_t", "q8h"}, {"bf16", "svbfloat16_t", "q8y"},
266       {"f32", "svfloat32_t", "q4f"}, {"f64", "svfloat64_t", "q2d"}};
267 
268   RecordKeeper &Records;
269   llvm::StringMap<uint64_t> EltTypes;
270   llvm::StringMap<uint64_t> MemEltTypes;
271   llvm::StringMap<uint64_t> FlagTypes;
272   llvm::StringMap<uint64_t> MergeTypes;
273   llvm::StringMap<uint64_t> ImmCheckTypes;
274 
275 public:
276   SVEEmitter(RecordKeeper &R) : Records(R) {
277     for (auto *RV : Records.getAllDerivedDefinitions("EltType"))
278       EltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
279     for (auto *RV : Records.getAllDerivedDefinitions("MemEltType"))
280       MemEltTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
281     for (auto *RV : Records.getAllDerivedDefinitions("FlagType"))
282       FlagTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
283     for (auto *RV : Records.getAllDerivedDefinitions("MergeType"))
284       MergeTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
285     for (auto *RV : Records.getAllDerivedDefinitions("ImmCheckType"))
286       ImmCheckTypes[RV->getNameInitAsString()] = RV->getValueAsInt("Value");
287   }
288 
289   /// Returns the enum value for the immcheck type
290   unsigned getEnumValueForImmCheck(StringRef C) const {
291     auto It = ImmCheckTypes.find(C);
292     if (It != ImmCheckTypes.end())
293       return It->getValue();
294     llvm_unreachable("Unsupported imm check");
295   }
296 
297   /// Returns the enum value for the flag type
298   uint64_t getEnumValueForFlag(StringRef C) const {
299     auto Res = FlagTypes.find(C);
300     if (Res != FlagTypes.end())
301       return Res->getValue();
302     llvm_unreachable("Unsupported flag");
303   }
304 
305   // Returns the SVETypeFlags for a given value and mask.
306   uint64_t encodeFlag(uint64_t V, StringRef MaskName) const {
307     auto It = FlagTypes.find(MaskName);
308     if (It != FlagTypes.end()) {
309       uint64_t Mask = It->getValue();
310       unsigned Shift = llvm::countr_zero(Mask);
311       assert(Shift < 64 && "Mask value produced an invalid shift value");
312       return (V << Shift) & Mask;
313     }
314     llvm_unreachable("Unsupported flag");
315   }
316 
317   // Returns the SVETypeFlags for the given element type.
318   uint64_t encodeEltType(StringRef EltName) {
319     auto It = EltTypes.find(EltName);
320     if (It != EltTypes.end())
321       return encodeFlag(It->getValue(), "EltTypeMask");
322     llvm_unreachable("Unsupported EltType");
323   }
324 
325   // Returns the SVETypeFlags for the given memory element type.
326   uint64_t encodeMemoryElementType(uint64_t MT) {
327     return encodeFlag(MT, "MemEltTypeMask");
328   }
329 
330   // Returns the SVETypeFlags for the given merge type.
331   uint64_t encodeMergeType(uint64_t MT) {
332     return encodeFlag(MT, "MergeTypeMask");
333   }
334 
335   // Returns the SVETypeFlags for the given splat operand.
336   unsigned encodeSplatOperand(unsigned SplatIdx) {
337     assert(SplatIdx < 7 && "SplatIdx out of encodable range");
338     return encodeFlag(SplatIdx + 1, "SplatOperandMask");
339   }
340 
341   // Returns the SVETypeFlags value for the given SVEType.
342   uint64_t encodeTypeFlags(const SVEType &T);
343 
344   /// Emit arm_sve.h.
345   void createHeader(raw_ostream &o);
346 
347   /// Emit all the __builtin prototypes and code needed by Sema.
348   void createBuiltins(raw_ostream &o);
349 
350   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
351   void createCodeGenMap(raw_ostream &o);
352 
353   /// Emit all the range checks for the immediates.
354   void createRangeChecks(raw_ostream &o);
355 
356   /// Create the SVETypeFlags used in CGBuiltins
357   void createTypeFlags(raw_ostream &o);
358 
359   /// Emit arm_sme.h.
360   void createSMEHeader(raw_ostream &o);
361 
362   /// Emit all the SME __builtin prototypes and code needed by Sema.
363   void createSMEBuiltins(raw_ostream &o);
364 
365   /// Emit all the information needed to map builtin -> LLVM IR intrinsic.
366   void createSMECodeGenMap(raw_ostream &o);
367 
368   /// Emit all the range checks for the immediates.
369   void createSMERangeChecks(raw_ostream &o);
370 
371   /// Create intrinsic and add it to \p Out
372   void createIntrinsic(Record *R,
373                        SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out);
374 };
375 
376 } // end anonymous namespace
377 
378 
379 //===----------------------------------------------------------------------===//
380 // Type implementation
381 //===----------------------------------------------------------------------===//
382 
383 std::string SVEType::builtin_str() const {
384   std::string S;
385   if (isVoid())
386     return "v";
387 
388   if (isScalarPredicate())
389     return "b";
390 
391   if (isSvcount())
392     return "Qa";
393 
394   if (isVoidPointer())
395     S += "v";
396   else if (!isFloatingPoint())
397     switch (ElementBitwidth) {
398     case 1: S += "b"; break;
399     case 8: S += "c"; break;
400     case 16: S += "s"; break;
401     case 32: S += "i"; break;
402     case 64: S += "Wi"; break;
403     case 128: S += "LLLi"; break;
404     default: llvm_unreachable("Unhandled case!");
405     }
406   else if (isFloat())
407     switch (ElementBitwidth) {
408     case 16: S += "h"; break;
409     case 32: S += "f"; break;
410     case 64: S += "d"; break;
411     default: llvm_unreachable("Unhandled case!");
412     }
413   else if (isBFloat()) {
414     assert(ElementBitwidth == 16 && "Not a valid BFloat.");
415     S += "y";
416   }
417 
418   if (!isFloatingPoint()) {
419     if ((isChar() || isPointer()) && !isVoidPointer()) {
420       // Make chars and typed pointers explicitly signed.
421       if (Signed)
422         S = "S" + S;
423       else if (!Signed)
424         S = "U" + S;
425     } else if (!isVoidPointer() && !Signed) {
426       S = "U" + S;
427     }
428   }
429 
430   // Constant indices are "int", but have the "constant expression" modifier.
431   if (isImmediate()) {
432     assert(!isFloat() && "fp immediates are not supported");
433     S = "I" + S;
434   }
435 
436   if (isScalar()) {
437     if (Constant) S += "C";
438     if (Pointer) S += "*";
439     return S;
440   }
441 
442   assert(isScalableVector() && "Unsupported type");
443   return "q" + utostr(getNumElements() * NumVectors) + S;
444 }
445 
446 std::string SVEType::str() const {
447   if (isPredicatePattern())
448     return "enum svpattern";
449 
450   if (isPrefetchOp())
451     return "enum svprfop";
452 
453   std::string S;
454   if (Void)
455     S += "void";
456   else {
457     if (isScalableVector() || isSvcount())
458       S += "sv";
459     if (!Signed && !isFloatingPoint())
460       S += "u";
461 
462     if (Float)
463       S += "float";
464     else if (isSvcount())
465       S += "count";
466     else if (isScalarPredicate() || isPredicateVector())
467       S += "bool";
468     else if (isBFloat())
469       S += "bfloat";
470     else
471       S += "int";
472 
473     if (!isScalarPredicate() && !isPredicateVector() && !isSvcount())
474       S += utostr(ElementBitwidth);
475     if (!isScalableVector() && isVector())
476       S += "x" + utostr(getNumElements());
477     if (NumVectors > 1)
478       S += "x" + utostr(NumVectors);
479     if (!isScalarPredicate())
480       S += "_t";
481   }
482 
483   if (Constant)
484     S += " const";
485   if (Pointer)
486     S += " *";
487 
488   return S;
489 }
490 void SVEType::applyTypespec() {
491   for (char I : TS) {
492     switch (I) {
493     case 'Q':
494       Svcount = true;
495       break;
496     case 'P':
497       Predicate = true;
498       break;
499     case 'U':
500       Signed = false;
501       break;
502     case 'c':
503       ElementBitwidth = 8;
504       break;
505     case 's':
506       ElementBitwidth = 16;
507       break;
508     case 'i':
509       ElementBitwidth = 32;
510       break;
511     case 'l':
512       ElementBitwidth = 64;
513       break;
514     case 'q':
515       ElementBitwidth = 128;
516       break;
517     case 'h':
518       Float = true;
519       ElementBitwidth = 16;
520       break;
521     case 'f':
522       Float = true;
523       ElementBitwidth = 32;
524       break;
525     case 'd':
526       Float = true;
527       ElementBitwidth = 64;
528       break;
529     case 'b':
530       BFloat = true;
531       Float = false;
532       ElementBitwidth = 16;
533       break;
534     default:
535       llvm_unreachable("Unhandled type code!");
536     }
537   }
538   assert(ElementBitwidth != ~0U && "Bad element bitwidth!");
539 }
540 
541 void SVEType::applyModifier(char Mod) {
542   switch (Mod) {
543   case '2':
544     NumVectors = 2;
545     break;
546   case '3':
547     NumVectors = 3;
548     break;
549   case '4':
550     NumVectors = 4;
551     break;
552   case 'v':
553     Void = true;
554     break;
555   case 'd':
556     DefaultType = true;
557     break;
558   case 'c':
559     Constant = true;
560     [[fallthrough]];
561   case 'p':
562     Pointer = true;
563     Bitwidth = ElementBitwidth;
564     NumVectors = 0;
565     break;
566   case 'e':
567     Signed = false;
568     ElementBitwidth /= 2;
569     break;
570   case 'h':
571     ElementBitwidth /= 2;
572     break;
573   case 'q':
574     ElementBitwidth /= 4;
575     break;
576   case 'b':
577     Signed = false;
578     Float = false;
579     BFloat = false;
580     ElementBitwidth /= 4;
581     break;
582   case 'o':
583     ElementBitwidth *= 4;
584     break;
585   case 'P':
586     Signed = true;
587     Float = false;
588     BFloat = false;
589     Predicate = true;
590     Svcount = false;
591     Bitwidth = 16;
592     ElementBitwidth = 1;
593     break;
594   case 's':
595   case 'a':
596     Bitwidth = ElementBitwidth;
597     NumVectors = 0;
598     break;
599   case 'R':
600     ElementBitwidth /= 2;
601     NumVectors = 0;
602     break;
603   case 'r':
604     ElementBitwidth /= 4;
605     NumVectors = 0;
606     break;
607   case '@':
608     Signed = false;
609     Float = false;
610     BFloat = false;
611     ElementBitwidth /= 4;
612     NumVectors = 0;
613     break;
614   case 'K':
615     Signed = true;
616     Float = false;
617     BFloat = false;
618     Bitwidth = ElementBitwidth;
619     NumVectors = 0;
620     break;
621   case 'L':
622     Signed = false;
623     Float = false;
624     BFloat = false;
625     Bitwidth = ElementBitwidth;
626     NumVectors = 0;
627     break;
628   case 'u':
629     Predicate = false;
630     Svcount = false;
631     Signed = false;
632     Float = false;
633     BFloat = false;
634     break;
635   case 'x':
636     Predicate = false;
637     Svcount = false;
638     Signed = true;
639     Float = false;
640     BFloat = false;
641     break;
642   case 'i':
643     Predicate = false;
644     Svcount = false;
645     Float = false;
646     BFloat = false;
647     ElementBitwidth = Bitwidth = 64;
648     NumVectors = 0;
649     Signed = false;
650     Immediate = true;
651     break;
652   case 'I':
653     Predicate = false;
654     Svcount = false;
655     Float = false;
656     BFloat = false;
657     ElementBitwidth = Bitwidth = 32;
658     NumVectors = 0;
659     Signed = true;
660     Immediate = true;
661     PredicatePattern = true;
662     break;
663   case 'J':
664     Predicate = false;
665     Svcount = false;
666     Float = false;
667     BFloat = false;
668     ElementBitwidth = Bitwidth = 32;
669     NumVectors = 0;
670     Signed = true;
671     Immediate = true;
672     PrefetchOp = true;
673     break;
674   case 'k':
675     Predicate = false;
676     Svcount = false;
677     Signed = true;
678     Float = false;
679     BFloat = false;
680     ElementBitwidth = Bitwidth = 32;
681     NumVectors = 0;
682     break;
683   case 'l':
684     Predicate = false;
685     Svcount = false;
686     Signed = true;
687     Float = false;
688     BFloat = false;
689     ElementBitwidth = Bitwidth = 64;
690     NumVectors = 0;
691     break;
692   case 'm':
693     Predicate = false;
694     Svcount = false;
695     Signed = false;
696     Float = false;
697     BFloat = false;
698     ElementBitwidth = Bitwidth = 32;
699     NumVectors = 0;
700     break;
701   case 'n':
702     Predicate = false;
703     Svcount = false;
704     Signed = false;
705     Float = false;
706     BFloat = false;
707     ElementBitwidth = Bitwidth = 64;
708     NumVectors = 0;
709     break;
710   case 'w':
711     ElementBitwidth = 64;
712     break;
713   case 'j':
714     ElementBitwidth = Bitwidth = 64;
715     NumVectors = 0;
716     break;
717   case 'f':
718     Signed = false;
719     ElementBitwidth = Bitwidth = 64;
720     NumVectors = 0;
721     break;
722   case 'g':
723     Signed = false;
724     Float = false;
725     BFloat = false;
726     ElementBitwidth = 64;
727     break;
728   case 't':
729     Signed = true;
730     Float = false;
731     BFloat = false;
732     ElementBitwidth = 32;
733     break;
734   case 'z':
735     Signed = false;
736     Float = false;
737     BFloat = false;
738     ElementBitwidth = 32;
739     break;
740   case 'O':
741     Predicate = false;
742     Svcount = false;
743     Float = true;
744     ElementBitwidth = 16;
745     break;
746   case 'M':
747     Predicate = false;
748     Svcount = false;
749     Float = true;
750     BFloat = false;
751     ElementBitwidth = 32;
752     break;
753   case 'N':
754     Predicate = false;
755     Svcount = false;
756     Float = true;
757     ElementBitwidth = 64;
758     break;
759   case 'Q':
760     Constant = true;
761     Pointer = true;
762     Void = true;
763     NumVectors = 0;
764     break;
765   case 'S':
766     Constant = true;
767     Pointer = true;
768     ElementBitwidth = Bitwidth = 8;
769     NumVectors = 0;
770     Signed = true;
771     break;
772   case 'W':
773     Constant = true;
774     Pointer = true;
775     ElementBitwidth = Bitwidth = 8;
776     NumVectors = 0;
777     Signed = false;
778     break;
779   case 'T':
780     Constant = true;
781     Pointer = true;
782     ElementBitwidth = Bitwidth = 16;
783     NumVectors = 0;
784     Signed = true;
785     break;
786   case 'X':
787     Constant = true;
788     Pointer = true;
789     ElementBitwidth = Bitwidth = 16;
790     NumVectors = 0;
791     Signed = false;
792     break;
793   case 'Y':
794     Constant = true;
795     Pointer = true;
796     ElementBitwidth = Bitwidth = 32;
797     NumVectors = 0;
798     Signed = false;
799     break;
800   case 'U':
801     Constant = true;
802     Pointer = true;
803     ElementBitwidth = Bitwidth = 32;
804     NumVectors = 0;
805     Signed = true;
806     break;
807   case '%':
808     Pointer = true;
809     Void = true;
810     NumVectors = 0;
811     break;
812   case 'A':
813     Pointer = true;
814     ElementBitwidth = Bitwidth = 8;
815     NumVectors = 0;
816     Signed = true;
817     break;
818   case 'B':
819     Pointer = true;
820     ElementBitwidth = Bitwidth = 16;
821     NumVectors = 0;
822     Signed = true;
823     break;
824   case 'C':
825     Pointer = true;
826     ElementBitwidth = Bitwidth = 32;
827     NumVectors = 0;
828     Signed = true;
829     break;
830   case 'D':
831     Pointer = true;
832     ElementBitwidth = Bitwidth = 64;
833     NumVectors = 0;
834     Signed = true;
835     break;
836   case 'E':
837     Pointer = true;
838     ElementBitwidth = Bitwidth = 8;
839     NumVectors = 0;
840     Signed = false;
841     break;
842   case 'F':
843     Pointer = true;
844     ElementBitwidth = Bitwidth = 16;
845     NumVectors = 0;
846     Signed = false;
847     break;
848   case 'G':
849     Pointer = true;
850     ElementBitwidth = Bitwidth = 32;
851     NumVectors = 0;
852     Signed = false;
853     break;
854   case '}':
855     Predicate = false;
856     Signed = true;
857     Svcount = true;
858     NumVectors = 0;
859     Float = false;
860     BFloat = false;
861     break;
862   default:
863     llvm_unreachable("Unhandled character!");
864   }
865 }
866 
867 
868 //===----------------------------------------------------------------------===//
869 // Intrinsic implementation
870 //===----------------------------------------------------------------------===//
871 
872 Intrinsic::Intrinsic(StringRef Name, StringRef Proto, uint64_t MergeTy,
873                      StringRef MergeSuffix, uint64_t MemoryElementTy,
874                      StringRef LLVMName, uint64_t Flags,
875                      ArrayRef<ImmCheck> Checks, TypeSpec BT, ClassKind Class,
876                      SVEEmitter &Emitter, StringRef Guard)
877     : Name(Name.str()), LLVMName(LLVMName), Proto(Proto.str()),
878       BaseTypeSpec(BT), Class(Class), Guard(Guard.str()),
879       MergeSuffix(MergeSuffix.str()), BaseType(BT, 'd'), Flags(Flags),
880       ImmChecks(Checks.begin(), Checks.end()) {
881   // Types[0] is the return value.
882   for (unsigned I = 0; I < Proto.size(); ++I) {
883     SVEType T(BaseTypeSpec, Proto[I]);
884     Types.push_back(T);
885 
886     // Add range checks for immediates
887     if (I > 0) {
888       if (T.isPredicatePattern())
889         ImmChecks.emplace_back(
890             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_31"));
891       else if (T.isPrefetchOp())
892         ImmChecks.emplace_back(
893             I - 1, Emitter.getEnumValueForImmCheck("ImmCheck0_13"));
894     }
895   }
896 
897   // Set flags based on properties
898   this->Flags |= Emitter.encodeTypeFlags(BaseType);
899   this->Flags |= Emitter.encodeMemoryElementType(MemoryElementTy);
900   this->Flags |= Emitter.encodeMergeType(MergeTy);
901   if (hasSplat())
902     this->Flags |= Emitter.encodeSplatOperand(getSplatIdx());
903 }
904 
905 std::string Intrinsic::getBuiltinTypeStr() {
906   std::string S = getReturnType().builtin_str();
907   for (unsigned I = 0; I < getNumParams(); ++I)
908     S += getParamType(I).builtin_str();
909 
910   return S;
911 }
912 
913 std::string Intrinsic::replaceTemplatedArgs(std::string Name, TypeSpec TS,
914                                             std::string Proto) const {
915   std::string Ret = Name;
916   while (Ret.find('{') != std::string::npos) {
917     size_t Pos = Ret.find('{');
918     size_t End = Ret.find('}');
919     unsigned NumChars = End - Pos + 1;
920     assert(NumChars == 3 && "Unexpected template argument");
921 
922     SVEType T;
923     char C = Ret[Pos+1];
924     switch(C) {
925     default:
926       llvm_unreachable("Unknown predication specifier");
927     case 'd':
928       T = SVEType(TS, 'd');
929       break;
930     case '0':
931     case '1':
932     case '2':
933     case '3':
934       T = SVEType(TS, Proto[C - '0']);
935       break;
936     }
937 
938     // Replace templated arg with the right suffix (e.g. u32)
939     std::string TypeCode;
940     if (T.isInteger())
941       TypeCode = T.isSigned() ? 's' : 'u';
942     else if (T.isSvcount())
943       TypeCode = 'c';
944     else if (T.isPredicateVector())
945       TypeCode = 'b';
946     else if (T.isBFloat())
947       TypeCode = "bf";
948     else
949       TypeCode = 'f';
950     Ret.replace(Pos, NumChars, TypeCode + utostr(T.getElementSizeInBits()));
951   }
952 
953   return Ret;
954 }
955 
956 std::string Intrinsic::mangleLLVMName() const {
957   std::string S = getLLVMName();
958 
959   // Replace all {d} like expressions with e.g. 'u32'
960   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto());
961 }
962 
963 std::string Intrinsic::mangleName(ClassKind LocalCK) const {
964   std::string S = getName();
965 
966   if (LocalCK == ClassG) {
967     // Remove the square brackets and everything in between.
968     while (S.find('[') != std::string::npos) {
969       auto Start = S.find('[');
970       auto End = S.find(']');
971       S.erase(Start, (End-Start)+1);
972     }
973   } else {
974     // Remove the square brackets.
975     while (S.find('[') != std::string::npos) {
976       auto BrPos = S.find('[');
977       if (BrPos != std::string::npos)
978         S.erase(BrPos, 1);
979       BrPos = S.find(']');
980       if (BrPos != std::string::npos)
981         S.erase(BrPos, 1);
982     }
983   }
984 
985   // Replace all {d} like expressions with e.g. 'u32'
986   return replaceTemplatedArgs(S, getBaseTypeSpec(), getProto()) +
987          getMergeSuffix();
988 }
989 
990 void Intrinsic::emitIntrinsic(raw_ostream &OS, SVEEmitter &Emitter) const {
991   bool IsOverloaded = getClassKind() == ClassG && getProto().size() > 1;
992 
993   std::string FullName = mangleName(ClassS);
994   std::string ProtoName = mangleName(getClassKind());
995   std::string SMEAttrs = "";
996 
997   if (Flags & Emitter.getEnumValueForFlag("IsStreaming"))
998     SMEAttrs += ", arm_streaming";
999   if (Flags & Emitter.getEnumValueForFlag("IsStreamingCompatible"))
1000     SMEAttrs += ", arm_streaming_compatible";
1001   if (Flags & Emitter.getEnumValueForFlag("IsSharedZA"))
1002     SMEAttrs += ", arm_shared_za";
1003   if (Flags & Emitter.getEnumValueForFlag("IsPreservesZA"))
1004     SMEAttrs += ", arm_preserves_za";
1005 
1006   OS << (IsOverloaded ? "__aio " : "__ai ")
1007      << "__attribute__((__clang_arm_builtin_alias("
1008      << (SMEAttrs.empty() ? "__builtin_sve_" : "__builtin_sme_")
1009      << FullName << ")";
1010   if (!SMEAttrs.empty())
1011     OS << SMEAttrs;
1012   OS << "))\n";
1013 
1014   OS << getTypes()[0].str() << " " << ProtoName << "(";
1015   for (unsigned I = 0; I < getTypes().size() - 1; ++I) {
1016     if (I != 0)
1017       OS << ", ";
1018     OS << getTypes()[I + 1].str();
1019   }
1020   OS << ");\n";
1021 }
1022 
1023 //===----------------------------------------------------------------------===//
1024 // SVEEmitter implementation
1025 //===----------------------------------------------------------------------===//
1026 uint64_t SVEEmitter::encodeTypeFlags(const SVEType &T) {
1027   if (T.isFloat()) {
1028     switch (T.getElementSizeInBits()) {
1029     case 16:
1030       return encodeEltType("EltTyFloat16");
1031     case 32:
1032       return encodeEltType("EltTyFloat32");
1033     case 64:
1034       return encodeEltType("EltTyFloat64");
1035     default:
1036       llvm_unreachable("Unhandled float element bitwidth!");
1037     }
1038   }
1039 
1040   if (T.isBFloat()) {
1041     assert(T.getElementSizeInBits() == 16 && "Not a valid BFloat.");
1042     return encodeEltType("EltTyBFloat16");
1043   }
1044 
1045   if (T.isPredicateVector() || T.isSvcount()) {
1046     switch (T.getElementSizeInBits()) {
1047     case 8:
1048       return encodeEltType("EltTyBool8");
1049     case 16:
1050       return encodeEltType("EltTyBool16");
1051     case 32:
1052       return encodeEltType("EltTyBool32");
1053     case 64:
1054       return encodeEltType("EltTyBool64");
1055     default:
1056       llvm_unreachable("Unhandled predicate element bitwidth!");
1057     }
1058   }
1059 
1060   switch (T.getElementSizeInBits()) {
1061   case 8:
1062     return encodeEltType("EltTyInt8");
1063   case 16:
1064     return encodeEltType("EltTyInt16");
1065   case 32:
1066     return encodeEltType("EltTyInt32");
1067   case 64:
1068     return encodeEltType("EltTyInt64");
1069   case 128:
1070     return encodeEltType("EltTyInt128");
1071   default:
1072     llvm_unreachable("Unhandled integer element bitwidth!");
1073   }
1074 }
1075 
1076 void SVEEmitter::createIntrinsic(
1077     Record *R, SmallVectorImpl<std::unique_ptr<Intrinsic>> &Out) {
1078   StringRef Name = R->getValueAsString("Name");
1079   StringRef Proto = R->getValueAsString("Prototype");
1080   StringRef Types = R->getValueAsString("Types");
1081   StringRef Guard = R->getValueAsString("TargetGuard");
1082   StringRef LLVMName = R->getValueAsString("LLVMIntrinsic");
1083   uint64_t Merge = R->getValueAsInt("Merge");
1084   StringRef MergeSuffix = R->getValueAsString("MergeSuffix");
1085   uint64_t MemEltType = R->getValueAsInt("MemEltType");
1086   std::vector<Record*> FlagsList = R->getValueAsListOfDefs("Flags");
1087   std::vector<Record*> ImmCheckList = R->getValueAsListOfDefs("ImmChecks");
1088 
1089   int64_t Flags = 0;
1090   for (auto FlagRec : FlagsList)
1091     Flags |= FlagRec->getValueAsInt("Value");
1092 
1093   // Create a dummy TypeSpec for non-overloaded builtins.
1094   if (Types.empty()) {
1095     assert((Flags & getEnumValueForFlag("IsOverloadNone")) &&
1096            "Expect TypeSpec for overloaded builtin!");
1097     Types = "i";
1098   }
1099 
1100   // Extract type specs from string
1101   SmallVector<TypeSpec, 8> TypeSpecs;
1102   TypeSpec Acc;
1103   for (char I : Types) {
1104     Acc.push_back(I);
1105     if (islower(I)) {
1106       TypeSpecs.push_back(TypeSpec(Acc));
1107       Acc.clear();
1108     }
1109   }
1110 
1111   // Remove duplicate type specs.
1112   llvm::sort(TypeSpecs);
1113   TypeSpecs.erase(std::unique(TypeSpecs.begin(), TypeSpecs.end()),
1114                   TypeSpecs.end());
1115 
1116   // Create an Intrinsic for each type spec.
1117   for (auto TS : TypeSpecs) {
1118     // Collate a list of range/option checks for the immediates.
1119     SmallVector<ImmCheck, 2> ImmChecks;
1120     for (auto *R : ImmCheckList) {
1121       int64_t Arg = R->getValueAsInt("Arg");
1122       int64_t EltSizeArg = R->getValueAsInt("EltSizeArg");
1123       int64_t Kind = R->getValueAsDef("Kind")->getValueAsInt("Value");
1124       assert(Arg >= 0 && Kind >= 0 && "Arg and Kind must be nonnegative");
1125 
1126       unsigned ElementSizeInBits = 0;
1127       if (EltSizeArg >= 0)
1128         ElementSizeInBits =
1129             SVEType(TS, Proto[EltSizeArg + /* offset by return arg */ 1])
1130                 .getElementSizeInBits();
1131       ImmChecks.push_back(ImmCheck(Arg, Kind, ElementSizeInBits));
1132     }
1133 
1134     Out.push_back(std::make_unique<Intrinsic>(
1135         Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags, ImmChecks,
1136         TS, ClassS, *this, Guard));
1137 
1138     // Also generate the short-form (e.g. svadd_m) for the given type-spec.
1139     if (Intrinsic::isOverloadedIntrinsic(Name))
1140       Out.push_back(std::make_unique<Intrinsic>(
1141           Name, Proto, Merge, MergeSuffix, MemEltType, LLVMName, Flags,
1142           ImmChecks, TS, ClassG, *this, Guard));
1143   }
1144 }
1145 
1146 void SVEEmitter::createHeader(raw_ostream &OS) {
1147   OS << "/*===---- arm_sve.h - ARM SVE intrinsics "
1148         "-----------------------------------===\n"
1149         " *\n"
1150         " *\n"
1151         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1152         "Exceptions.\n"
1153         " * See https://llvm.org/LICENSE.txt for license information.\n"
1154         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1155         " *\n"
1156         " *===-----------------------------------------------------------------"
1157         "------===\n"
1158         " */\n\n";
1159 
1160   OS << "#ifndef __ARM_SVE_H\n";
1161   OS << "#define __ARM_SVE_H\n\n";
1162 
1163   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1164   OS << "#error \"Big endian is currently not supported for arm_sve.h\"\n";
1165   OS << "#endif\n";
1166 
1167   OS << "#include <stdint.h>\n\n";
1168   OS << "#ifdef  __cplusplus\n";
1169   OS << "extern \"C\" {\n";
1170   OS << "#else\n";
1171   OS << "#include <stdbool.h>\n";
1172   OS << "#endif\n\n";
1173 
1174   OS << "typedef __fp16 float16_t;\n";
1175   OS << "typedef float float32_t;\n";
1176   OS << "typedef double float64_t;\n";
1177 
1178   OS << "typedef __SVInt8_t svint8_t;\n";
1179   OS << "typedef __SVInt16_t svint16_t;\n";
1180   OS << "typedef __SVInt32_t svint32_t;\n";
1181   OS << "typedef __SVInt64_t svint64_t;\n";
1182   OS << "typedef __SVUint8_t svuint8_t;\n";
1183   OS << "typedef __SVUint16_t svuint16_t;\n";
1184   OS << "typedef __SVUint32_t svuint32_t;\n";
1185   OS << "typedef __SVUint64_t svuint64_t;\n";
1186   OS << "typedef __SVFloat16_t svfloat16_t;\n\n";
1187 
1188   OS << "typedef __SVBFloat16_t svbfloat16_t;\n";
1189 
1190   OS << "#include <arm_bf16.h>\n";
1191 
1192   OS << "typedef __SVFloat32_t svfloat32_t;\n";
1193   OS << "typedef __SVFloat64_t svfloat64_t;\n";
1194   OS << "typedef __clang_svint8x2_t svint8x2_t;\n";
1195   OS << "typedef __clang_svint16x2_t svint16x2_t;\n";
1196   OS << "typedef __clang_svint32x2_t svint32x2_t;\n";
1197   OS << "typedef __clang_svint64x2_t svint64x2_t;\n";
1198   OS << "typedef __clang_svuint8x2_t svuint8x2_t;\n";
1199   OS << "typedef __clang_svuint16x2_t svuint16x2_t;\n";
1200   OS << "typedef __clang_svuint32x2_t svuint32x2_t;\n";
1201   OS << "typedef __clang_svuint64x2_t svuint64x2_t;\n";
1202   OS << "typedef __clang_svfloat16x2_t svfloat16x2_t;\n";
1203   OS << "typedef __clang_svfloat32x2_t svfloat32x2_t;\n";
1204   OS << "typedef __clang_svfloat64x2_t svfloat64x2_t;\n";
1205   OS << "typedef __clang_svint8x3_t svint8x3_t;\n";
1206   OS << "typedef __clang_svint16x3_t svint16x3_t;\n";
1207   OS << "typedef __clang_svint32x3_t svint32x3_t;\n";
1208   OS << "typedef __clang_svint64x3_t svint64x3_t;\n";
1209   OS << "typedef __clang_svuint8x3_t svuint8x3_t;\n";
1210   OS << "typedef __clang_svuint16x3_t svuint16x3_t;\n";
1211   OS << "typedef __clang_svuint32x3_t svuint32x3_t;\n";
1212   OS << "typedef __clang_svuint64x3_t svuint64x3_t;\n";
1213   OS << "typedef __clang_svfloat16x3_t svfloat16x3_t;\n";
1214   OS << "typedef __clang_svfloat32x3_t svfloat32x3_t;\n";
1215   OS << "typedef __clang_svfloat64x3_t svfloat64x3_t;\n";
1216   OS << "typedef __clang_svint8x4_t svint8x4_t;\n";
1217   OS << "typedef __clang_svint16x4_t svint16x4_t;\n";
1218   OS << "typedef __clang_svint32x4_t svint32x4_t;\n";
1219   OS << "typedef __clang_svint64x4_t svint64x4_t;\n";
1220   OS << "typedef __clang_svuint8x4_t svuint8x4_t;\n";
1221   OS << "typedef __clang_svuint16x4_t svuint16x4_t;\n";
1222   OS << "typedef __clang_svuint32x4_t svuint32x4_t;\n";
1223   OS << "typedef __clang_svuint64x4_t svuint64x4_t;\n";
1224   OS << "typedef __clang_svfloat16x4_t svfloat16x4_t;\n";
1225   OS << "typedef __clang_svfloat32x4_t svfloat32x4_t;\n";
1226   OS << "typedef __clang_svfloat64x4_t svfloat64x4_t;\n";
1227   OS << "typedef __SVBool_t  svbool_t;\n";
1228   OS << "typedef __clang_svboolx2_t  svboolx2_t;\n";
1229   OS << "typedef __clang_svboolx4_t  svboolx4_t;\n\n";
1230 
1231   OS << "typedef __clang_svbfloat16x2_t svbfloat16x2_t;\n";
1232   OS << "typedef __clang_svbfloat16x3_t svbfloat16x3_t;\n";
1233   OS << "typedef __clang_svbfloat16x4_t svbfloat16x4_t;\n";
1234 
1235   OS << "typedef __SVCount_t svcount_t;\n\n";
1236 
1237   OS << "enum svpattern\n";
1238   OS << "{\n";
1239   OS << "  SV_POW2 = 0,\n";
1240   OS << "  SV_VL1 = 1,\n";
1241   OS << "  SV_VL2 = 2,\n";
1242   OS << "  SV_VL3 = 3,\n";
1243   OS << "  SV_VL4 = 4,\n";
1244   OS << "  SV_VL5 = 5,\n";
1245   OS << "  SV_VL6 = 6,\n";
1246   OS << "  SV_VL7 = 7,\n";
1247   OS << "  SV_VL8 = 8,\n";
1248   OS << "  SV_VL16 = 9,\n";
1249   OS << "  SV_VL32 = 10,\n";
1250   OS << "  SV_VL64 = 11,\n";
1251   OS << "  SV_VL128 = 12,\n";
1252   OS << "  SV_VL256 = 13,\n";
1253   OS << "  SV_MUL4 = 29,\n";
1254   OS << "  SV_MUL3 = 30,\n";
1255   OS << "  SV_ALL = 31\n";
1256   OS << "};\n\n";
1257 
1258   OS << "enum svprfop\n";
1259   OS << "{\n";
1260   OS << "  SV_PLDL1KEEP = 0,\n";
1261   OS << "  SV_PLDL1STRM = 1,\n";
1262   OS << "  SV_PLDL2KEEP = 2,\n";
1263   OS << "  SV_PLDL2STRM = 3,\n";
1264   OS << "  SV_PLDL3KEEP = 4,\n";
1265   OS << "  SV_PLDL3STRM = 5,\n";
1266   OS << "  SV_PSTL1KEEP = 8,\n";
1267   OS << "  SV_PSTL1STRM = 9,\n";
1268   OS << "  SV_PSTL2KEEP = 10,\n";
1269   OS << "  SV_PSTL2STRM = 11,\n";
1270   OS << "  SV_PSTL3KEEP = 12,\n";
1271   OS << "  SV_PSTL3STRM = 13\n";
1272   OS << "};\n\n";
1273 
1274   OS << "/* Function attributes */\n";
1275   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1276         "__nodebug__))\n\n";
1277   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
1278         "__nodebug__, __overloadable__))\n\n";
1279 
1280   // Add reinterpret functions.
1281   for (auto ShortForm : { false, true } )
1282     for (const ReinterpretTypeInfo &From : Reinterprets)
1283       for (const ReinterpretTypeInfo &To : Reinterprets) {
1284         if (ShortForm) {
1285           OS << "__aio __attribute__((target(\"sve\"))) " << From.Type
1286              << " svreinterpret_" << From.Suffix;
1287           OS << "(" << To.Type << " op) {\n";
1288           OS << "  return __builtin_sve_reinterpret_" << From.Suffix << "_"
1289              << To.Suffix << "(op);\n";
1290           OS << "}\n\n";
1291         } else
1292           OS << "#define svreinterpret_" << From.Suffix << "_" << To.Suffix
1293              << "(...) __builtin_sve_reinterpret_" << From.Suffix << "_"
1294              << To.Suffix << "(__VA_ARGS__)\n";
1295       }
1296 
1297   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1298   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1299   for (auto *R : RV)
1300     createIntrinsic(R, Defs);
1301 
1302   // Sort intrinsics in header file by following order/priority:
1303   // - Architectural guard (i.e. does it require SVE2 or SVE2_AES)
1304   // - Class (is intrinsic overloaded or not)
1305   // - Intrinsic name
1306   std::stable_sort(
1307       Defs.begin(), Defs.end(), [](const std::unique_ptr<Intrinsic> &A,
1308                                    const std::unique_ptr<Intrinsic> &B) {
1309         auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1310           return std::make_tuple(I->getGuard(), (unsigned)I->getClassKind(), I->getName());
1311         };
1312         return ToTuple(A) < ToTuple(B);
1313       });
1314 
1315   // Actually emit the intrinsic declarations.
1316   for (auto &I : Defs)
1317     I->emitIntrinsic(OS, *this);
1318 
1319   OS << "#define svcvtnt_bf16_x      svcvtnt_bf16_m\n";
1320   OS << "#define svcvtnt_bf16_f32_x  svcvtnt_bf16_f32_m\n";
1321 
1322   OS << "#define svcvtnt_f16_x      svcvtnt_f16_m\n";
1323   OS << "#define svcvtnt_f16_f32_x  svcvtnt_f16_f32_m\n";
1324   OS << "#define svcvtnt_f32_x      svcvtnt_f32_m\n";
1325   OS << "#define svcvtnt_f32_f64_x  svcvtnt_f32_f64_m\n\n";
1326 
1327   OS << "#define svcvtxnt_f32_x     svcvtxnt_f32_m\n";
1328   OS << "#define svcvtxnt_f32_f64_x svcvtxnt_f32_f64_m\n\n";
1329 
1330   OS << "#ifdef __cplusplus\n";
1331   OS << "} // extern \"C\"\n";
1332   OS << "#endif\n\n";
1333   OS << "#undef __ai\n\n";
1334   OS << "#undef __aio\n\n";
1335   OS << "#endif /* __ARM_SVE_H */\n";
1336 }
1337 
1338 void SVEEmitter::createBuiltins(raw_ostream &OS) {
1339   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1340   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1341   for (auto *R : RV)
1342     createIntrinsic(R, Defs);
1343 
1344   // The mappings must be sorted based on BuiltinID.
1345   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1346                       const std::unique_ptr<Intrinsic> &B) {
1347     return A->getMangledName() < B->getMangledName();
1348   });
1349 
1350   OS << "#ifdef GET_SVE_BUILTINS\n";
1351   for (auto &Def : Defs) {
1352     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1353     // declarations only live in the header file.
1354     if (Def->getClassKind() != ClassG)
1355       OS << "TARGET_BUILTIN(__builtin_sve_" << Def->getMangledName() << ", \""
1356          << Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1357          << "\")\n";
1358   }
1359 
1360   // Add reinterpret builtins
1361   for (const ReinterpretTypeInfo &From : Reinterprets)
1362     for (const ReinterpretTypeInfo &To : Reinterprets)
1363       OS << "TARGET_BUILTIN(__builtin_sve_reinterpret_" << From.Suffix << "_"
1364          << To.Suffix << +", \"" << From.BuiltinType << To.BuiltinType
1365          << "\", \"n\", \"sve\")\n";
1366 
1367   OS << "#endif\n\n";
1368 }
1369 
1370 void SVEEmitter::createCodeGenMap(raw_ostream &OS) {
1371   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1372   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1373   for (auto *R : RV)
1374     createIntrinsic(R, Defs);
1375 
1376   // The mappings must be sorted based on BuiltinID.
1377   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1378                       const std::unique_ptr<Intrinsic> &B) {
1379     return A->getMangledName() < B->getMangledName();
1380   });
1381 
1382   OS << "#ifdef GET_SVE_LLVM_INTRINSIC_MAP\n";
1383   for (auto &Def : Defs) {
1384     // Builtins only exist for non-overloaded intrinsics, overloaded
1385     // declarations only live in the header file.
1386     if (Def->getClassKind() == ClassG)
1387       continue;
1388 
1389     uint64_t Flags = Def->getFlags();
1390     auto FlagString = std::to_string(Flags);
1391 
1392     std::string LLVMName = Def->getMangledLLVMName();
1393     std::string Builtin = Def->getMangledName();
1394     if (!LLVMName.empty())
1395       OS << "SVEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1396          << "),\n";
1397     else
1398       OS << "SVEMAP2(" << Builtin << ", " << FlagString << "),\n";
1399   }
1400   OS << "#endif\n\n";
1401 }
1402 
1403 void SVEEmitter::createRangeChecks(raw_ostream &OS) {
1404   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1405   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1406   for (auto *R : RV)
1407     createIntrinsic(R, Defs);
1408 
1409   // The mappings must be sorted based on BuiltinID.
1410   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1411                       const std::unique_ptr<Intrinsic> &B) {
1412     return A->getMangledName() < B->getMangledName();
1413   });
1414 
1415 
1416   OS << "#ifdef GET_SVE_IMMEDIATE_CHECK\n";
1417 
1418   // Ensure these are only emitted once.
1419   std::set<std::string> Emitted;
1420 
1421   for (auto &Def : Defs) {
1422     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1423         Def->getImmChecks().empty())
1424       continue;
1425 
1426     OS << "case SVE::BI__builtin_sve_" << Def->getMangledName() << ":\n";
1427     for (auto &Check : Def->getImmChecks())
1428       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", "
1429          << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n";
1430     OS << "  break;\n";
1431 
1432     Emitted.insert(Def->getMangledName());
1433   }
1434 
1435   OS << "#endif\n\n";
1436 }
1437 
1438 /// Create the SVETypeFlags used in CGBuiltins
1439 void SVEEmitter::createTypeFlags(raw_ostream &OS) {
1440   OS << "#ifdef LLVM_GET_SVE_TYPEFLAGS\n";
1441   for (auto &KV : FlagTypes)
1442     OS << "const uint64_t " << KV.getKey() << " = " << KV.getValue() << ";\n";
1443   OS << "#endif\n\n";
1444 
1445   OS << "#ifdef LLVM_GET_SVE_ELTTYPES\n";
1446   for (auto &KV : EltTypes)
1447     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1448   OS << "#endif\n\n";
1449 
1450   OS << "#ifdef LLVM_GET_SVE_MEMELTTYPES\n";
1451   for (auto &KV : MemEltTypes)
1452     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1453   OS << "#endif\n\n";
1454 
1455   OS << "#ifdef LLVM_GET_SVE_MERGETYPES\n";
1456   for (auto &KV : MergeTypes)
1457     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1458   OS << "#endif\n\n";
1459 
1460   OS << "#ifdef LLVM_GET_SVE_IMMCHECKTYPES\n";
1461   for (auto &KV : ImmCheckTypes)
1462     OS << "  " << KV.getKey() << " = " << KV.getValue() << ",\n";
1463   OS << "#endif\n\n";
1464 }
1465 
1466 void SVEEmitter::createSMEHeader(raw_ostream &OS) {
1467   OS << "/*===---- arm_sme_draft_spec_subject_to_change.h - ARM SME intrinsics "
1468         "------===\n"
1469         " *\n"
1470         " *\n"
1471         " * Part of the LLVM Project, under the Apache License v2.0 with LLVM "
1472         "Exceptions.\n"
1473         " * See https://llvm.org/LICENSE.txt for license information.\n"
1474         " * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception\n"
1475         " *\n"
1476         " *===-----------------------------------------------------------------"
1477         "------===\n"
1478         " */\n\n";
1479 
1480   OS << "#ifndef __ARM_SME_H\n";
1481   OS << "#define __ARM_SME_H\n\n";
1482 
1483   OS << "#if !defined(__LITTLE_ENDIAN__)\n";
1484   OS << "#error \"Big endian is currently not supported for arm_sme_draft_spec_subject_to_change.h\"\n";
1485   OS << "#endif\n";
1486 
1487   OS << "#include <arm_sve.h> \n\n";
1488 
1489   OS << "/* Function attributes */\n";
1490   OS << "#define __ai static __inline__ __attribute__((__always_inline__, "
1491         "__nodebug__))\n\n";
1492   OS << "#define __aio static __inline__ __attribute__((__always_inline__, "
1493         "__nodebug__, __overloadable__))\n\n";
1494 
1495   OS << "#ifdef  __cplusplus\n";
1496   OS << "extern \"C\" {\n";
1497   OS << "#endif\n\n";
1498 
1499   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1500   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1501   for (auto *R : RV)
1502     createIntrinsic(R, Defs);
1503 
1504   // Sort intrinsics in header file by following order/priority similar to SVE:
1505   // - Architectural guard
1506   // - Class (is intrinsic overloaded or not)
1507   // - Intrinsic name
1508   std::stable_sort(Defs.begin(), Defs.end(),
1509                    [](const std::unique_ptr<Intrinsic> &A,
1510                       const std::unique_ptr<Intrinsic> &B) {
1511                      auto ToTuple = [](const std::unique_ptr<Intrinsic> &I) {
1512                        return std::make_tuple(I->getGuard(),
1513                                               (unsigned)I->getClassKind(),
1514                                               I->getName());
1515                      };
1516                      return ToTuple(A) < ToTuple(B);
1517                    });
1518 
1519   // Actually emit the intrinsic declaration.
1520   for (auto &I : Defs) {
1521     I->emitIntrinsic(OS, *this);
1522   }
1523 
1524   OS << "#ifdef __cplusplus\n";
1525   OS << "} // extern \"C\"\n";
1526   OS << "#endif\n\n";
1527   OS << "#undef __ai\n\n";
1528   OS << "#endif /* __ARM_SME_H */\n";
1529 }
1530 
1531 void SVEEmitter::createSMEBuiltins(raw_ostream &OS) {
1532   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1533   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1534   for (auto *R : RV) {
1535     createIntrinsic(R, Defs);
1536   }
1537 
1538   // The mappings must be sorted based on BuiltinID.
1539   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1540                       const std::unique_ptr<Intrinsic> &B) {
1541     return A->getMangledName() < B->getMangledName();
1542   });
1543 
1544   OS << "#ifdef GET_SME_BUILTINS\n";
1545   for (auto &Def : Defs) {
1546     // Only create BUILTINs for non-overloaded intrinsics, as overloaded
1547     // declarations only live in the header file.
1548     if (Def->getClassKind() != ClassG)
1549       OS << "TARGET_BUILTIN(__builtin_sme_" << Def->getMangledName() << ", \""
1550          << Def->getBuiltinTypeStr() << "\", \"n\", \"" << Def->getGuard()
1551          << "\")\n";
1552   }
1553 
1554   OS << "#endif\n\n";
1555 }
1556 
1557 void SVEEmitter::createSMECodeGenMap(raw_ostream &OS) {
1558   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1559   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1560   for (auto *R : RV) {
1561     createIntrinsic(R, Defs);
1562   }
1563 
1564   // The mappings must be sorted based on BuiltinID.
1565   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1566                       const std::unique_ptr<Intrinsic> &B) {
1567     return A->getMangledName() < B->getMangledName();
1568   });
1569 
1570   OS << "#ifdef GET_SME_LLVM_INTRINSIC_MAP\n";
1571   for (auto &Def : Defs) {
1572     // Builtins only exist for non-overloaded intrinsics, overloaded
1573     // declarations only live in the header file.
1574     if (Def->getClassKind() == ClassG)
1575       continue;
1576 
1577     uint64_t Flags = Def->getFlags();
1578     auto FlagString = std::to_string(Flags);
1579 
1580     std::string LLVMName = Def->getLLVMName();
1581     std::string Builtin = Def->getMangledName();
1582     if (!LLVMName.empty())
1583       OS << "SMEMAP1(" << Builtin << ", " << LLVMName << ", " << FlagString
1584          << "),\n";
1585     else
1586       OS << "SMEMAP2(" << Builtin << ", " << FlagString << "),\n";
1587   }
1588   OS << "#endif\n\n";
1589 }
1590 
1591 void SVEEmitter::createSMERangeChecks(raw_ostream &OS) {
1592   std::vector<Record *> RV = Records.getAllDerivedDefinitions("Inst");
1593   SmallVector<std::unique_ptr<Intrinsic>, 128> Defs;
1594   for (auto *R : RV) {
1595     createIntrinsic(R, Defs);
1596   }
1597 
1598   // The mappings must be sorted based on BuiltinID.
1599   llvm::sort(Defs, [](const std::unique_ptr<Intrinsic> &A,
1600                       const std::unique_ptr<Intrinsic> &B) {
1601     return A->getMangledName() < B->getMangledName();
1602   });
1603 
1604 
1605   OS << "#ifdef GET_SME_IMMEDIATE_CHECK\n";
1606 
1607   // Ensure these are only emitted once.
1608   std::set<std::string> Emitted;
1609 
1610   for (auto &Def : Defs) {
1611     if (Emitted.find(Def->getMangledName()) != Emitted.end() ||
1612         Def->getImmChecks().empty())
1613       continue;
1614 
1615     OS << "case SME::BI__builtin_sme_" << Def->getMangledName() << ":\n";
1616     for (auto &Check : Def->getImmChecks())
1617       OS << "ImmChecks.push_back(std::make_tuple(" << Check.getArg() << ", "
1618          << Check.getKind() << ", " << Check.getElementSizeInBits() << "));\n";
1619     OS << "  break;\n";
1620 
1621     Emitted.insert(Def->getMangledName());
1622   }
1623 
1624   OS << "#endif\n\n";
1625 }
1626 
1627 namespace clang {
1628 void EmitSveHeader(RecordKeeper &Records, raw_ostream &OS) {
1629   SVEEmitter(Records).createHeader(OS);
1630 }
1631 
1632 void EmitSveBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1633   SVEEmitter(Records).createBuiltins(OS);
1634 }
1635 
1636 void EmitSveBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1637   SVEEmitter(Records).createCodeGenMap(OS);
1638 }
1639 
1640 void EmitSveRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
1641   SVEEmitter(Records).createRangeChecks(OS);
1642 }
1643 
1644 void EmitSveTypeFlags(RecordKeeper &Records, raw_ostream &OS) {
1645   SVEEmitter(Records).createTypeFlags(OS);
1646 }
1647 
1648 void EmitSmeHeader(RecordKeeper &Records, raw_ostream &OS) {
1649   SVEEmitter(Records).createSMEHeader(OS);
1650 }
1651 
1652 void EmitSmeBuiltins(RecordKeeper &Records, raw_ostream &OS) {
1653   SVEEmitter(Records).createSMEBuiltins(OS);
1654 }
1655 
1656 void EmitSmeBuiltinCG(RecordKeeper &Records, raw_ostream &OS) {
1657   SVEEmitter(Records).createSMECodeGenMap(OS);
1658 }
1659 
1660 void EmitSmeRangeChecks(RecordKeeper &Records, raw_ostream &OS) {
1661   SVEEmitter(Records).createSMERangeChecks(OS);
1662 }
1663 } // End namespace clang
1664