xref: /llvm-project/llvm/utils/TableGen/Basic/IntrinsicEmitter.cpp (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1 //===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
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 emits information about intrinsic functions.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CodeGenIntrinsics.h"
14 #include "SequenceToOffsetTable.h"
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/ADT/Twine.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Support/ErrorHandling.h"
21 #include "llvm/Support/FormatVariadic.h"
22 #include "llvm/Support/ModRef.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/TableGen/Error.h"
25 #include "llvm/TableGen/Record.h"
26 #include "llvm/TableGen/StringToOffsetTable.h"
27 #include "llvm/TableGen/TableGenBackend.h"
28 #include <algorithm>
29 #include <array>
30 #include <cassert>
31 #include <cctype>
32 #include <map>
33 #include <optional>
34 #include <string>
35 #include <utility>
36 #include <vector>
37 using namespace llvm;
38 
39 static cl::OptionCategory GenIntrinsicCat("Options for -gen-intrinsic-enums");
40 static cl::opt<std::string>
41     IntrinsicPrefix("intrinsic-prefix",
42                     cl::desc("Generate intrinsics with this target prefix"),
43                     cl::value_desc("target prefix"), cl::cat(GenIntrinsicCat));
44 
45 namespace {
46 class IntrinsicEmitter {
47   const RecordKeeper &Records;
48 
49 public:
50   IntrinsicEmitter(const RecordKeeper &R) : Records(R) {}
51 
52   void run(raw_ostream &OS, bool Enums);
53 
54   void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
55   void EmitArgKind(raw_ostream &OS);
56   void EmitIITInfo(raw_ostream &OS);
57   void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
58   void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
59                                 raw_ostream &OS);
60   void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
61                                     raw_ostream &OS);
62   void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
63   void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
64   void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints,
65                                  bool IsClang, raw_ostream &OS);
66 };
67 
68 // Helper class to use with `TableGen::Emitter::OptClass`.
69 template <bool Enums> class IntrinsicEmitterOpt : public IntrinsicEmitter {
70 public:
71   IntrinsicEmitterOpt(const RecordKeeper &R) : IntrinsicEmitter(R) {}
72   void run(raw_ostream &OS) { IntrinsicEmitter::run(OS, Enums); }
73 };
74 
75 } // End anonymous namespace
76 
77 //===----------------------------------------------------------------------===//
78 // IntrinsicEmitter Implementation
79 //===----------------------------------------------------------------------===//
80 
81 void IntrinsicEmitter::run(raw_ostream &OS, bool Enums) {
82   emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
83 
84   CodeGenIntrinsicTable Ints(Records);
85 
86   if (Enums) {
87     // Emit the enum information.
88     EmitEnumInfo(Ints, OS);
89 
90     // Emit ArgKind for Intrinsics.h.
91     EmitArgKind(OS);
92   } else {
93     // Emit IIT_Info constants.
94     EmitIITInfo(OS);
95 
96     // Emit the target metadata.
97     EmitTargetInfo(Ints, OS);
98 
99     // Emit the intrinsic ID -> name table.
100     EmitIntrinsicToNameTable(Ints, OS);
101 
102     // Emit the intrinsic ID -> overload table.
103     EmitIntrinsicToOverloadTable(Ints, OS);
104 
105     // Emit the intrinsic declaration generator.
106     EmitGenerator(Ints, OS);
107 
108     // Emit the intrinsic parameter attributes.
109     EmitAttributes(Ints, OS);
110 
111     // Emit code to translate Clang builtins into LLVM intrinsics.
112     EmitIntrinsicToBuiltinMap(Ints, true, OS);
113 
114     // Emit code to translate MS builtins into LLVM intrinsics.
115     EmitIntrinsicToBuiltinMap(Ints, false, OS);
116   }
117 }
118 
119 void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
120                                     raw_ostream &OS) {
121   // Find the TargetSet for which to generate enums. There will be an initial
122   // set with an empty target prefix which will include target independent
123   // intrinsics like dbg.value.
124   using TargetSet = CodeGenIntrinsicTable::TargetSet;
125   const TargetSet *Set = nullptr;
126   for (const auto &Target : Ints.getTargets()) {
127     if (Target.Name == IntrinsicPrefix) {
128       Set = &Target;
129       break;
130     }
131   }
132   if (!Set) {
133     // The first entry is for target independent intrinsics, so drop it.
134     auto KnowTargets = Ints.getTargets().drop_front();
135     PrintFatalError([KnowTargets](raw_ostream &OS) {
136       OS << "tried to generate intrinsics for unknown target "
137          << IntrinsicPrefix << "\nKnown targets are: ";
138       interleaveComma(KnowTargets, OS,
139                       [&OS](const TargetSet &Target) { OS << Target.Name; });
140       OS << '\n';
141     });
142   }
143 
144   // Generate a complete header for target specific intrinsics.
145   if (IntrinsicPrefix.empty()) {
146     OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
147   } else {
148     std::string UpperPrefix = StringRef(IntrinsicPrefix).upper();
149     OS << formatv("#ifndef LLVM_IR_INTRINSIC_{}_ENUMS_H\n", UpperPrefix);
150     OS << formatv("#define LLVM_IR_INTRINSIC_{}_ENUMS_H\n", UpperPrefix);
151     OS << "namespace llvm::Intrinsic {\n";
152     OS << formatv("enum {}Intrinsics : unsigned {{\n", UpperPrefix);
153   }
154 
155   OS << "// Enum values for intrinsics.\n";
156   bool First = true;
157   for (const auto &Int : Ints[*Set]) {
158     OS << "    " << Int.EnumName;
159 
160     // Assign a value to the first intrinsic in this target set so that all
161     // intrinsic ids are distinct.
162     if (First) {
163       OS << " = " << Set->Offset + 1;
164       First = false;
165     }
166 
167     OS << ", ";
168     if (Int.EnumName.size() < 40)
169       OS.indent(40 - Int.EnumName.size());
170     OS << formatv(" // {}\n", Int.Name);
171   }
172 
173   // Emit num_intrinsics into the target neutral enum.
174   if (IntrinsicPrefix.empty()) {
175     OS << formatv("    num_intrinsics = {}\n", Ints.size() + 1);
176     OS << "#endif\n\n";
177   } else {
178     OS << R"(}; // enum
179 } // namespace llvm::Intrinsic
180 #endif
181 
182 )";
183   }
184 }
185 
186 void IntrinsicEmitter::EmitArgKind(raw_ostream &OS) {
187   if (!IntrinsicPrefix.empty())
188     return;
189   OS << "// llvm::Intrinsic::IITDescriptor::ArgKind.\n";
190   OS << "#ifdef GET_INTRINSIC_ARGKIND\n";
191   if (const auto RecArgKind = Records.getDef("ArgKind")) {
192     for (const auto &RV : RecArgKind->getValues())
193       OS << "    AK_" << RV.getName() << " = " << *RV.getValue() << ",\n";
194   } else {
195     OS << "#error \"ArgKind is not defined\"\n";
196   }
197   OS << "#endif\n\n";
198 }
199 
200 void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
201   OS << "#ifdef GET_INTRINSIC_IITINFO\n";
202   std::array<StringRef, 256> RecsByNumber;
203   auto IIT_Base = Records.getAllDerivedDefinitionsIfDefined("IIT_Base");
204   for (const Record *Rec : IIT_Base) {
205     auto Number = Rec->getValueAsInt("Number");
206     assert(0 <= Number && Number < (int)RecsByNumber.size() &&
207            "IIT_Info.Number should be uint8_t");
208     assert(RecsByNumber[Number].empty() && "Duplicate IIT_Info.Number");
209     RecsByNumber[Number] = Rec->getName();
210   }
211   if (IIT_Base.size() > 0) {
212     for (unsigned I = 0, E = RecsByNumber.size(); I < E; ++I)
213       if (!RecsByNumber[I].empty())
214         OS << "  " << RecsByNumber[I] << " = " << I << ",\n";
215   } else {
216     OS << "#error \"class IIT_Base is not defined\"\n";
217   }
218   OS << "#endif\n\n";
219 }
220 
221 void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
222                                       raw_ostream &OS) {
223   OS << R"(// Target mapping.
224 #ifdef GET_INTRINSIC_TARGET_DATA
225 struct IntrinsicTargetInfo {
226   StringLiteral Name;
227   size_t Offset;
228   size_t Count;
229 };
230 static constexpr IntrinsicTargetInfo TargetInfos[] = {
231 )";
232   for (const auto [Name, Offset, Count] : Ints.getTargets())
233     OS << formatv("  {{\"{}\", {}, {}},\n", Name, Offset, Count);
234   OS << R"(};
235 #endif
236 
237 )";
238 }
239 
240 void IntrinsicEmitter::EmitIntrinsicToNameTable(
241     const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
242   // Built up a table of the intrinsic names.
243   constexpr StringLiteral NotIntrinsic = "not_intrinsic";
244   StringToOffsetTable Table;
245   Table.GetOrAddStringOffset(NotIntrinsic);
246   for (const auto &Int : Ints)
247     Table.GetOrAddStringOffset(Int.Name);
248 
249   OS << R"(// Intrinsic ID to name table.
250 #ifdef GET_INTRINSIC_NAME_TABLE
251 // Note that entry #0 is the invalid intrinsic!
252 
253 )";
254 
255   Table.EmitStringTableDef(OS, "IntrinsicNameTable", /*Indent=*/"");
256 
257   OS << R"(
258 static constexpr unsigned IntrinsicNameOffsetTable[] = {
259 )";
260 
261   OS << formatv("  {}, // {}\n", Table.GetStringOffset(NotIntrinsic),
262                 NotIntrinsic);
263   for (const auto &Int : Ints)
264     OS << formatv("  {}, // {}\n", Table.GetStringOffset(Int.Name), Int.Name);
265 
266   OS << R"(
267 }; // IntrinsicNameOffsetTable
268 
269 #endif
270 
271 )";
272 }
273 
274 void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
275     const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
276   OS << R"(// Intrinsic ID to overload bitset.
277 #ifdef GET_INTRINSIC_OVERLOAD_TABLE
278 static constexpr uint8_t OTable[] = {
279   0
280   )";
281   for (auto [I, Int] : enumerate(Ints)) {
282     // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
283     size_t Idx = I + 1;
284 
285     if (Idx % 8 == 0)
286       OS << ",\n  0";
287     if (Int.isOverloaded)
288       OS << " | (1<<" << Idx % 8 << ')';
289   }
290   OS << "\n};\n\n";
291   // OTable contains a true bit at the position if the intrinsic is overloaded.
292   OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
293   OS << "#endif\n\n";
294 }
295 
296 using TypeSigTy = SmallVector<unsigned char>;
297 
298 /// Computes type signature of the intrinsic \p Int.
299 static TypeSigTy ComputeTypeSignature(const CodeGenIntrinsic &Int) {
300   TypeSigTy TypeSig;
301   const Record *TypeInfo = Int.TheDef->getValueAsDef("TypeInfo");
302   const ListInit *TypeList = TypeInfo->getValueAsListInit("TypeSig");
303 
304   for (const auto *TypeListEntry : TypeList->getValues())
305     TypeSig.emplace_back(cast<IntInit>(TypeListEntry)->getValue());
306   return TypeSig;
307 }
308 
309 // Pack the type signature into 32-bit fixed encoding word.
310 static std::optional<uint32_t> encodePacked(const TypeSigTy &TypeSig) {
311   if (TypeSig.size() > 8)
312     return std::nullopt;
313 
314   uint32_t Result = 0;
315   for (unsigned char C : reverse(TypeSig)) {
316     if (C > 15)
317       return std::nullopt;
318     Result = (Result << 4) | C;
319   }
320   return Result;
321 }
322 
323 void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
324                                      raw_ostream &OS) {
325   // Note: the code below can be switched to use 32-bit fixed encoding by
326   // flipping the flag below.
327   constexpr bool Use16BitFixedEncoding = true;
328   using FixedEncodingTy =
329       std::conditional_t<Use16BitFixedEncoding, uint16_t, uint32_t>;
330   constexpr unsigned FixedEncodingBits = sizeof(FixedEncodingTy) * CHAR_BIT;
331   // Mask with all bits 1 except the most significant bit.
332   const unsigned Mask = (1U << (FixedEncodingBits - 1)) - 1;
333   const unsigned MSBPostion = FixedEncodingBits - 1;
334   StringRef FixedEncodingTypeName =
335       Use16BitFixedEncoding ? "uint16_t" : "uint32_t";
336 
337   // If we can compute a 16/32-bit fixed encoding for this intrinsic, do so and
338   // capture it in this vector, otherwise store a ~0U.
339   std::vector<FixedEncodingTy> FixedEncodings;
340   SequenceToOffsetTable<TypeSigTy> LongEncodingTable;
341 
342   FixedEncodings.reserve(Ints.size());
343 
344   // Compute the unique argument type info.
345   for (const CodeGenIntrinsic &Int : Ints) {
346     // Get the signature for the intrinsic.
347     TypeSigTy TypeSig = ComputeTypeSignature(Int);
348 
349     // Check to see if we can encode it into a 16/32 bit word.
350     std::optional<uint32_t> Result = encodePacked(TypeSig);
351     if (Result && (*Result & Mask) == Result) {
352       FixedEncodings.push_back(static_cast<FixedEncodingTy>(*Result));
353       continue;
354     }
355 
356     LongEncodingTable.add(TypeSig);
357 
358     // This is a placehold that we'll replace after the table is laid out.
359     FixedEncodings.push_back(static_cast<FixedEncodingTy>(~0U));
360   }
361 
362   LongEncodingTable.layout();
363 
364   OS << formatv(R"(// Global intrinsic function declaration type table.
365 #ifdef GET_INTRINSIC_GENERATOR_GLOBAL
366 static constexpr {} IIT_Table[] = {{
367   )",
368                 FixedEncodingTypeName);
369 
370   unsigned MaxOffset = 0;
371   for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) {
372     if ((Idx & 7) == 7)
373       OS << "\n  ";
374 
375     // If the entry fit in the table, just emit it.
376     if ((FixedEncoding & Mask) == FixedEncoding) {
377       OS << "0x" << Twine::utohexstr(FixedEncoding) << ", ";
378       continue;
379     }
380 
381     TypeSigTy TypeSig = ComputeTypeSignature(Int);
382     unsigned Offset = LongEncodingTable.get(TypeSig);
383     MaxOffset = std::max(MaxOffset, Offset);
384 
385     // Otherwise, emit the offset into the long encoding table.  We emit it this
386     // way so that it is easier to read the offset in the .def file.
387     OS << formatv("(1U<<{}) | {}, ", MSBPostion, Offset);
388   }
389 
390   OS << "0\n};\n\n";
391 
392   // verify that all offsets will fit in 16/32 bits.
393   if ((MaxOffset & Mask) != MaxOffset)
394     PrintFatalError("Offset of long encoding table exceeds encoding bits");
395 
396   // Emit the shared table of register lists.
397   OS << "static constexpr unsigned char IIT_LongEncodingTable[] = {\n";
398   if (!LongEncodingTable.empty())
399     LongEncodingTable.emit(
400         OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned)C; });
401   OS << "  255\n};\n";
402   OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
403 }
404 
405 /// Returns the effective MemoryEffects for intrinsic \p Int.
406 static MemoryEffects getEffectiveME(const CodeGenIntrinsic &Int) {
407   MemoryEffects ME = Int.ME;
408   // TODO: IntrHasSideEffects should affect not only readnone intrinsics.
409   if (ME.doesNotAccessMemory() && Int.hasSideEffects)
410     ME = MemoryEffects::unknown();
411   return ME;
412 }
413 
414 static bool compareFnAttributes(const CodeGenIntrinsic *L,
415                                 const CodeGenIntrinsic *R) {
416   auto TieBoolAttributes = [](const CodeGenIntrinsic *I) -> auto {
417     // Sort throwing intrinsics after non-throwing intrinsics.
418     return std::tie(I->canThrow, I->isNoDuplicate, I->isNoMerge, I->isNoReturn,
419                     I->isNoCallback, I->isNoSync, I->isNoFree, I->isWillReturn,
420                     I->isCold, I->isConvergent, I->isSpeculatable,
421                     I->hasSideEffects, I->isStrictFP);
422   };
423 
424   auto TieL = TieBoolAttributes(L);
425   auto TieR = TieBoolAttributes(R);
426 
427   if (TieL != TieR)
428     return TieL < TieR;
429 
430   // Try to order by readonly/readnone attribute.
431   uint32_t LME = getEffectiveME(*L).toIntValue();
432   uint32_t RME = getEffectiveME(*R).toIntValue();
433   if (LME != RME)
434     return LME > RME;
435 
436   return false;
437 }
438 
439 /// Returns true if \p Int has a non-empty set of function attributes. Note that
440 /// NoUnwind = !canThrow, so we need to negate it's sense to test if the
441 // intrinsic has NoUnwind attribute.
442 static bool hasFnAttributes(const CodeGenIntrinsic &Int) {
443   return !Int.canThrow || Int.isNoReturn || Int.isNoCallback || Int.isNoSync ||
444          Int.isNoFree || Int.isWillReturn || Int.isCold || Int.isNoDuplicate ||
445          Int.isNoMerge || Int.isConvergent || Int.isSpeculatable ||
446          Int.isStrictFP || getEffectiveME(Int) != MemoryEffects::unknown();
447 }
448 
449 namespace {
450 struct FnAttributeComparator {
451   bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
452     return compareFnAttributes(L, R);
453   }
454 };
455 
456 struct AttributeComparator {
457   bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
458     // Order all intrinsics with no functiona attributes before all intrinsics
459     // with function attributes.
460     bool HasFnAttrLHS = hasFnAttributes(*L);
461     bool HasFnAttrRHS = hasFnAttributes(*R);
462 
463     // Order by argument attributes if function `hasFnAttributes` is equal.
464     // This is reliable because each side is already sorted internally.
465     return std::tie(HasFnAttrLHS, L->ArgumentAttributes) <
466            std::tie(HasFnAttrRHS, R->ArgumentAttributes);
467   }
468 };
469 } // End anonymous namespace
470 
471 /// Returns the name of the IR enum for argument attribute kind \p Kind.
472 static StringRef getArgAttrEnumName(CodeGenIntrinsic::ArgAttrKind Kind) {
473   switch (Kind) {
474   case CodeGenIntrinsic::NoCapture:
475     llvm_unreachable("Handled separately");
476   case CodeGenIntrinsic::NoAlias:
477     return "NoAlias";
478   case CodeGenIntrinsic::NoUndef:
479     return "NoUndef";
480   case CodeGenIntrinsic::NonNull:
481     return "NonNull";
482   case CodeGenIntrinsic::Returned:
483     return "Returned";
484   case CodeGenIntrinsic::ReadOnly:
485     return "ReadOnly";
486   case CodeGenIntrinsic::WriteOnly:
487     return "WriteOnly";
488   case CodeGenIntrinsic::ReadNone:
489     return "ReadNone";
490   case CodeGenIntrinsic::ImmArg:
491     return "ImmArg";
492   case CodeGenIntrinsic::Alignment:
493     return "Alignment";
494   case CodeGenIntrinsic::Dereferenceable:
495     return "Dereferenceable";
496   }
497   llvm_unreachable("Unknown CodeGenIntrinsic::ArgAttrKind enum");
498 }
499 
500 /// EmitAttributes - This emits the Intrinsic::getAttributes method.
501 void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
502                                       raw_ostream &OS) {
503   OS << R"(// Add parameter attributes that are not common to all intrinsics.
504 #ifdef GET_INTRINSIC_ATTRIBUTES
505 static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
506   switch (ID) {
507   default: llvm_unreachable("Invalid attribute set number");)";
508   // Compute unique argument attribute sets.
509   std::map<SmallVector<CodeGenIntrinsic::ArgAttribute, 0>, unsigned>
510       UniqArgAttributes;
511   for (const CodeGenIntrinsic &Int : Ints) {
512     for (auto &Attrs : Int.ArgumentAttributes) {
513       if (Attrs.empty())
514         continue;
515 
516       unsigned ID = UniqArgAttributes.size();
517       if (!UniqArgAttributes.try_emplace(Attrs, ID).second)
518         continue;
519 
520       assert(is_sorted(Attrs) && "Argument attributes are not sorted");
521 
522       OS << formatv(R"(
523   case {}:
524     return AttributeSet::get(C, {{
525 )",
526                     ID);
527       for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) {
528         if (Attr.Kind == CodeGenIntrinsic::NoCapture) {
529           OS << "      Attribute::getWithCaptureInfo(C, "
530                 "CaptureInfo::none()),\n";
531           continue;
532         }
533         StringRef AttrName = getArgAttrEnumName(Attr.Kind);
534         if (Attr.Kind == CodeGenIntrinsic::Alignment ||
535             Attr.Kind == CodeGenIntrinsic::Dereferenceable)
536           OS << formatv("      Attribute::get(C, Attribute::{}, {}),\n",
537                         AttrName, Attr.Value);
538         else
539           OS << formatv("      Attribute::get(C, Attribute::{}),\n", AttrName);
540       }
541       OS << "    });";
542     }
543   }
544   OS << R"(
545   }
546 } // getIntrinsicArgAttributeSet
547 )";
548 
549   // Compute unique function attribute sets.
550   std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator>
551       UniqFnAttributes;
552   OS << R"(
553 static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
554   switch (ID) {
555     default: llvm_unreachable("Invalid attribute set number");)";
556 
557   for (const CodeGenIntrinsic &Int : Ints) {
558     if (!hasFnAttributes(Int))
559       continue;
560     unsigned ID = UniqFnAttributes.size();
561     if (!UniqFnAttributes.try_emplace(&Int, ID).second)
562       continue;
563     OS << formatv(R"(
564   case {}:
565     return AttributeSet::get(C, {{
566 )",
567                   ID);
568     auto addAttribute = [&OS](StringRef Attr) {
569       OS << formatv("      Attribute::get(C, Attribute::{}),\n", Attr);
570     };
571     if (!Int.canThrow)
572       addAttribute("NoUnwind");
573     if (Int.isNoReturn)
574       addAttribute("NoReturn");
575     if (Int.isNoCallback)
576       addAttribute("NoCallback");
577     if (Int.isNoSync)
578       addAttribute("NoSync");
579     if (Int.isNoFree)
580       addAttribute("NoFree");
581     if (Int.isWillReturn)
582       addAttribute("WillReturn");
583     if (Int.isCold)
584       addAttribute("Cold");
585     if (Int.isNoDuplicate)
586       addAttribute("NoDuplicate");
587     if (Int.isNoMerge)
588       addAttribute("NoMerge");
589     if (Int.isConvergent)
590       addAttribute("Convergent");
591     if (Int.isSpeculatable)
592       addAttribute("Speculatable");
593     if (Int.isStrictFP)
594       addAttribute("StrictFP");
595 
596     const MemoryEffects ME = getEffectiveME(Int);
597     if (ME != MemoryEffects::unknown()) {
598       OS << formatv("      // {}\n", ME);
599       OS << formatv("      Attribute::getWithMemoryEffects(C, "
600                     "MemoryEffects::createFromIntValue({})),\n",
601                     ME.toIntValue());
602     }
603     OS << "    });";
604   }
605   OS << R"(
606   }
607 } // getIntrinsicFnAttributeSet
608 
609 AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {
610 )";
611 
612   // Compute the maximum number of attribute arguments and the map. For function
613   // attributes, we only consider whether the intrinsics has any function
614   // arguments or not.
615   std::map<const CodeGenIntrinsic *, unsigned, AttributeComparator>
616       UniqAttributes;
617   for (const CodeGenIntrinsic &Int : Ints) {
618     unsigned ID = UniqAttributes.size();
619     UniqAttributes.try_emplace(&Int, ID);
620   }
621 
622   // Assign a 16-bit packed ID for each intrinsic. The lower 8-bits will be its
623   // "argument attribute ID" (index in UniqAttributes) and upper 8 bits will be
624   // its "function attribute ID" (index in UniqFnAttributes).
625   if (UniqAttributes.size() > 256)
626     PrintFatalError("Too many unique argument attributes for table!");
627   if (UniqFnAttributes.size() > 256)
628     PrintFatalError("Too many unique function attributes for table!");
629 
630   // Emit an array of AttributeList.  Most intrinsics will have at least one
631   // entry, for the function itself (index ~1), which is usually nounwind.
632   OS << "  static constexpr uint16_t IntrinsicsToAttributesMap[] = {";
633   for (const CodeGenIntrinsic &Int : Ints) {
634     uint16_t FnAttrIndex = hasFnAttributes(Int) ? UniqFnAttributes[&Int] : 0;
635     OS << formatv("\n    {} << 8 | {}, // {}", FnAttrIndex,
636                   UniqAttributes[&Int], Int.Name);
637   }
638 
639   OS << formatv(R"(
640   };
641   if (id == 0)
642     return AttributeList();
643 
644   uint16_t PackedID = IntrinsicsToAttributesMap[id - 1];
645   uint8_t FnAttrID = PackedID >> 8;
646   switch(PackedID & 0xFF) {{
647     default: llvm_unreachable("Invalid attribute number");
648 )");
649 
650   for (const auto [IntPtr, UniqueID] : UniqAttributes) {
651     OS << formatv("  case {}:\n", UniqueID);
652     const CodeGenIntrinsic &Int = *IntPtr;
653 
654     // Keep track of the number of attributes we're writing out.
655     unsigned NumAttrs =
656         llvm::count_if(Int.ArgumentAttributes,
657                        [](const auto &Attrs) { return !Attrs.empty(); });
658     NumAttrs += hasFnAttributes(Int);
659     if (NumAttrs == 0) {
660       OS << "    return AttributeList();\n";
661       continue;
662     }
663 
664     OS << "    return AttributeList::get(C, {\n";
665     ListSeparator LS(",\n");
666     for (const auto &[AttrIdx, Attrs] : enumerate(Int.ArgumentAttributes)) {
667       if (Attrs.empty())
668         continue;
669 
670       unsigned ArgAttrID = UniqArgAttributes.find(Attrs)->second;
671       OS << LS
672          << formatv("      {{{}, getIntrinsicArgAttributeSet(C, {})}", AttrIdx,
673                     ArgAttrID);
674     }
675 
676     if (hasFnAttributes(Int)) {
677       OS << LS
678          << "      {AttributeList::FunctionIndex, "
679             "getIntrinsicFnAttributeSet(C, FnAttrID)}";
680     }
681     OS << "\n    });\n";
682   }
683 
684   OS << R"(  }
685 }
686 #endif // GET_INTRINSIC_ATTRIBUTES
687 
688 )";
689 }
690 
691 void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
692     const CodeGenIntrinsicTable &Ints, bool IsClang, raw_ostream &OS) {
693   StringRef CompilerName = IsClang ? "Clang" : "MS";
694   StringRef UpperCompilerName = IsClang ? "CLANG" : "MS";
695 
696   // map<TargetPrefix, pair<map<BuiltinName, EnumName>, CommonPrefix>.
697   // Note that we iterate over both the maps in the code below and both
698   // iterations need to iterate in sorted key order. For the inner map, entries
699   // need to be emitted in the sorted order of `BuiltinName` with `CommonPrefix`
700   // rempved, because we use std::lower_bound to search these entries. For the
701   // outer map as well, entries need to be emitted in sorter order of
702   // `TargetPrefix` as we use std::lower_bound to search these entries.
703   using BIMEntryTy =
704       std::pair<std::map<StringRef, StringRef>, std::optional<StringRef>>;
705   std::map<StringRef, BIMEntryTy> BuiltinMap;
706 
707   for (const CodeGenIntrinsic &Int : Ints) {
708     StringRef BuiltinName = IsClang ? Int.ClangBuiltinName : Int.MSBuiltinName;
709     if (BuiltinName.empty())
710       continue;
711     // Get the map for this target prefix.
712     auto &[Map, CommonPrefix] = BuiltinMap[Int.TargetPrefix];
713 
714     if (!Map.insert({BuiltinName, Int.EnumName}).second)
715       PrintFatalError(Int.TheDef->getLoc(),
716                       "Intrinsic '" + Int.TheDef->getName() + "': duplicate " +
717                           CompilerName + " builtin name!");
718 
719     // Update common prefix.
720     if (!CommonPrefix) {
721       // For the first builtin for this target, initialize the common prefix.
722       CommonPrefix = BuiltinName;
723       continue;
724     }
725 
726     // Update the common prefix. Note that this assumes that `take_front` will
727     // never set the `Data` pointer in CommonPrefix to nullptr.
728     const char *Mismatch = mismatch(*CommonPrefix, BuiltinName).first;
729     *CommonPrefix = CommonPrefix->take_front(Mismatch - CommonPrefix->begin());
730   }
731 
732   // Populate the string table with the names of all the builtins after
733   // removing this common prefix.
734   StringToOffsetTable Table;
735   for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
736     auto &[Map, CommonPrefix] = Entry;
737     for (auto &[BuiltinName, EnumName] : Map) {
738       StringRef Suffix = BuiltinName.substr(CommonPrefix->size());
739       Table.GetOrAddStringOffset(Suffix);
740     }
741   }
742 
743   OS << formatv(R"(
744 // Get the LLVM intrinsic that corresponds to a builtin. This is used by the
745 // C front-end. The builtin name is passed in as BuiltinName, and a target
746 // prefix (e.g. 'ppc') is passed in as TargetPrefix.
747 #ifdef GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
748 Intrinsic::ID
749 Intrinsic::getIntrinsicFor{}Builtin(StringRef TargetPrefix,
750                                       StringRef BuiltinName) {{
751   using namespace Intrinsic;
752 )",
753                 UpperCompilerName, CompilerName);
754 
755   if (BuiltinMap.empty()) {
756     OS << formatv(R"(
757   return not_intrinsic;
758   }
759 #endif  // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
760 )",
761                   UpperCompilerName);
762     return;
763   }
764 
765   if (!Table.empty()) {
766     Table.EmitStringTableDef(OS, "BuiltinNames");
767 
768     OS << R"(
769   struct BuiltinEntry {
770     ID IntrinsicID;
771     unsigned StrTabOffset;
772     const char *getName() const { return BuiltinNames[StrTabOffset].data(); }
773     bool operator<(StringRef RHS) const {
774       return strncmp(getName(), RHS.data(), RHS.size()) < 0;
775     }
776   };
777 
778 )";
779   }
780 
781   // Emit a per target table of bultin names.
782   bool HasTargetIndependentBuiltins = false;
783   StringRef TargetIndepndentCommonPrefix;
784   for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
785     const auto &[Map, CommonPrefix] = Entry;
786     if (!TargetPrefix.empty()) {
787       OS << formatv("  // Builtins for {0}.\n", TargetPrefix);
788     } else {
789       OS << "  // Target independent builtins.\n";
790       HasTargetIndependentBuiltins = true;
791       TargetIndepndentCommonPrefix = *CommonPrefix;
792     }
793 
794     // Emit the builtin table for this target prefix.
795     OS << formatv("  static constexpr BuiltinEntry {}Names[] = {{\n",
796                   TargetPrefix);
797     for (const auto &[BuiltinName, EnumName] : Map) {
798       StringRef Suffix = BuiltinName.substr(CommonPrefix->size());
799       OS << formatv("    {{{}, {}}, // {}\n", EnumName,
800                     *Table.GetStringOffset(Suffix), BuiltinName);
801     }
802     OS << formatv("  }; // {}Names\n\n", TargetPrefix);
803   }
804 
805   // After emitting the builtin tables for all targets, emit a lookup table for
806   // all targets. We will use binary search, similar to the table for builtin
807   // names to lookup into this table.
808   OS << R"(
809   struct TargetEntry {
810     StringLiteral TargetPrefix;
811     ArrayRef<BuiltinEntry> Names;
812     StringLiteral CommonPrefix;
813     bool operator<(StringRef RHS) const {
814       return TargetPrefix < RHS;
815     };
816   };
817   static constexpr TargetEntry TargetTable[] = {
818 )";
819 
820   for (const auto &[TargetPrefix, Entry] : BuiltinMap) {
821     const auto &[Map, CommonPrefix] = Entry;
822     if (TargetPrefix.empty())
823       continue;
824     OS << formatv(R"(    {{"{0}", {0}Names, "{1}"},)", TargetPrefix,
825                   CommonPrefix)
826        << "\n";
827   }
828   OS << "  };\n";
829 
830   // Now for the actual lookup, first check the target independent table if
831   // we emitted one.
832   if (HasTargetIndependentBuiltins) {
833     OS << formatv(R"(
834   // Check if it's a target independent builtin.
835   // Copy the builtin name so we can use it in consume_front without clobbering
836   // if for the lookup in the target specific table.
837   StringRef Suffix = BuiltinName;
838   if (Suffix.consume_front("{}")) {{
839     auto II = lower_bound(Names, Suffix);
840     if (II != std::end(Names) && II->getName() == Suffix)
841       return II->IntrinsicID;
842   }
843 )",
844                   TargetIndepndentCommonPrefix);
845   }
846 
847   // If a target independent builtin was not found, lookup the target specific.
848   OS << formatv(R"(
849   auto TI = lower_bound(TargetTable, TargetPrefix);
850   if (TI == std::end(TargetTable) || TI->TargetPrefix != TargetPrefix)
851     return not_intrinsic;
852   // This is the last use of BuiltinName, so no need to copy before using it in
853   // consume_front.
854   if (!BuiltinName.consume_front(TI->CommonPrefix))
855     return not_intrinsic;
856   auto II = lower_bound(TI->Names, BuiltinName);
857   if (II == std::end(TI->Names) || II->getName() != BuiltinName)
858     return not_intrinsic;
859   return II->IntrinsicID;
860 }
861 #endif // GET_LLVM_INTRINSIC_FOR_{}_BUILTIN
862 
863 )",
864                 UpperCompilerName);
865 }
866 
867 static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/true>>
868     X("gen-intrinsic-enums", "Generate intrinsic enums");
869 
870 static TableGen::Emitter::OptClass<IntrinsicEmitterOpt</*Enums=*/false>>
871     Y("gen-intrinsic-impl", "Generate intrinsic implementation code");
872