[llvm] [NFC][TableGen] Refactor IntrinsicEmitter code (PR #106479)
Rahul Joshi via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 28 18:15:25 PDT 2024
https://github.com/jurahul created https://github.com/llvm/llvm-project/pull/106479
- Use formatv() and raw string literals to simplify emission code.
- Use range based for loops and structured bindings to simplify loops.
- Use const Pointers to Records.
- Rename `ComputeFixedEncoding` to `ComputeTypeSignature` to reflect what the function actually does, cnd change it to return a vector.
- Use reverse() and for_each() for loop to pack 8 nibbles into 32-bits.
- Rename some variables to follow LLVM coding standards.
>From 60eb6ae25eef13579274a1c7f73a760f83603369 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Tue, 27 Aug 2024 07:32:42 -0700
Subject: [PATCH] [NFC][TableGen] Refactor IntrinsicEmitter code
- Use formatv() and raw string literals to simplify emission code.
- Use range based for loops and structured bindings to simplify loops.
- Use const Pointers to Records.
- Rename `ComputeFixedEncoding` to `ComputeTypeSignature` to reflect
what the function actually does, cnd change it to return a vector.
- Use reverse() and for_each() for loop to pack 8 nibbles into 32-bits.
- Rename some variables to follow LLVM coding standards.
---
llvm/test/TableGen/intrinsic-attrs.td | 2 +-
llvm/utils/TableGen/IntrinsicEmitter.cpp | 392 ++++++++++++-----------
2 files changed, 202 insertions(+), 192 deletions(-)
diff --git a/llvm/test/TableGen/intrinsic-attrs.td b/llvm/test/TableGen/intrinsic-attrs.td
index 22019b8fb87140..29e8cb1e89bb01 100644
--- a/llvm/test/TableGen/intrinsic-attrs.td
+++ b/llvm/test/TableGen/intrinsic-attrs.td
@@ -60,7 +60,7 @@ def int_deref_ptr_ret : Intrinsic<[llvm_ptr_ty], [], [Dereferenceable<RetIndex,
// CHECK-NEXT: default: llvm_unreachable("Invalid attribute set number");
// CHECK-NEXT: case 0:
// CHECK-NEXT: return AttributeSet::get(C, {
-// CHECK-NEXT: Attribute::get(C, Attribute::Dereferenceable, 16),
+// CHECK-NEXT: Attribute::get(C, Attribute::Dereferenceable, 16),
// CHECK-NEXT: });
// CHECK-NEXT: }
// CHECK-NEXT: }
diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp
index af8ff889918428..d888257c3e941a 100644
--- a/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -144,35 +144,40 @@ void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
} else {
std::string UpperPrefix = StringRef(IntrinsicPrefix).upper();
- OS << "#ifndef LLVM_IR_INTRINSIC_" << UpperPrefix << "_ENUMS_H\n";
- OS << "#define LLVM_IR_INTRINSIC_" << UpperPrefix << "_ENUMS_H\n\n";
+ OS << formatv("#ifndef LLVM_IR_INTRINSIC_{0}_ENUMS_H\n", UpperPrefix);
+ OS << formatv("#define LLVM_IR_INTRINSIC_{0}_ENUMS_H\n", UpperPrefix);
OS << "namespace llvm::Intrinsic {\n";
- OS << "enum " << UpperPrefix << "Intrinsics : unsigned {\n";
+ OS << formatv("enum {0}Intrinsics : unsigned {{\n", UpperPrefix);
}
OS << "// Enum values for intrinsics.\n";
- for (unsigned i = Set->Offset, e = Set->Offset + Set->Count; i != e; ++i) {
- OS << " " << Ints[i].EnumName;
+ bool First = true;
+ for (const auto &Int : ArrayRef(&Ints[Set->Offset], Set->Count)) {
+ OS << " " << Int.EnumName;
// Assign a value to the first intrinsic in this target set so that all
// intrinsic ids are distinct.
- if (i == Set->Offset)
- OS << " = " << (Set->Offset + 1);
+ if (First) {
+ OS << " = " << Set->Offset + 1;
+ First = false;
+ }
OS << ", ";
- if (Ints[i].EnumName.size() < 40)
- OS.indent(40 - Ints[i].EnumName.size());
- OS << " // " << Ints[i].Name << "\n";
+ if (Int.EnumName.size() < 40)
+ OS.indent(40 - Int.EnumName.size());
+ OS << formatv(" // {0}\n", Int.Name);
}
// Emit num_intrinsics into the target neutral enum.
if (IntrinsicPrefix.empty()) {
- OS << " num_intrinsics = " << (Ints.size() + 1) << "\n";
+ OS << formatv(" num_intrinsics = {0}\n", Ints.size() + 1);
OS << "#endif\n\n";
} else {
- OS << "}; // enum\n";
- OS << "} // namespace llvm::Intrinsic\n\n";
- OS << "#endif\n";
+ OS << R"(}; // enum
+} // namespace llvm::Intrinsic
+#endif
+
+)";
}
}
@@ -181,8 +186,8 @@ void IntrinsicEmitter::EmitArgKind(raw_ostream &OS) {
return;
OS << "// llvm::Intrinsic::IITDescriptor::ArgKind.\n";
OS << "#ifdef GET_INTRINSIC_ARGKIND\n";
- if (auto RecArgKind = Records.getDef("ArgKind")) {
- for (auto &RV : RecArgKind->getValues())
+ if (const auto RecArgKind = Records.getDef("ArgKind")) {
+ for (const auto &RV : RecArgKind->getValues())
OS << " AK_" << RV.getName() << " = " << *RV.getValue() << ",\n";
} else {
OS << "#error \"ArgKind is not defined\"\n";
@@ -194,7 +199,7 @@ void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
OS << "#ifdef GET_INTRINSIC_IITINFO\n";
std::array<StringRef, 256> RecsByNumber;
auto IIT_Base = Records.getAllDerivedDefinitionsIfDefined("IIT_Base");
- for (auto Rec : IIT_Base) {
+ for (const Record *Rec : IIT_Base) {
auto Number = Rec->getValueAsInt("Number");
assert(0 <= Number && Number < (int)RecsByNumber.size() &&
"IIT_Info.Number should be uint8_t");
@@ -213,26 +218,29 @@ void IntrinsicEmitter::EmitIITInfo(raw_ostream &OS) {
void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS) {
- OS << "// Target mapping.\n";
- OS << "#ifdef GET_INTRINSIC_TARGET_DATA\n";
- OS << "struct IntrinsicTargetInfo {\n"
- << " llvm::StringLiteral Name;\n"
- << " size_t Offset;\n"
- << " size_t Count;\n"
- << "};\n";
- OS << "static constexpr IntrinsicTargetInfo TargetInfos[] = {\n";
- for (const auto &Target : Ints.Targets)
- OS << " {llvm::StringLiteral(\"" << Target.Name << "\"), " << Target.Offset
- << ", " << Target.Count << "},\n";
- OS << "};\n";
- OS << "#endif\n\n";
+ OS << R"(// Target mapping.
+#ifdef GET_INTRINSIC_TARGET_DATA
+struct IntrinsicTargetInfo {
+ StringLiteral Name;
+ size_t Offset;
+ size_t Count;
+};
+static constexpr IntrinsicTargetInfo TargetInfos[] = {
+)";
+ for (const auto [Name, Offset, Count] : Ints.Targets)
+ OS << formatv(" {{\"{0}\", {1}, {2}},\n", Name, Offset, Count);
+ OS << R"(};
+#endif
+
+)";
}
void IntrinsicEmitter::EmitIntrinsicToNameTable(
const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
- OS << "// Intrinsic ID to name table.\n";
- OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
- OS << " // Note that entry #0 is the invalid intrinsic!\n";
+ OS << R"(// Intrinsic ID to name table.
+#ifdef GET_INTRINSIC_NAME_TABLE
+// Note that entry #0 is the invalid intrinsic!
+)";
for (const auto &Int : Ints)
OS << " \"" << Int.Name << "\",\n";
OS << "#endif\n\n";
@@ -240,16 +248,19 @@ void IntrinsicEmitter::EmitIntrinsicToNameTable(
void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
- OS << "// Intrinsic ID to overload bitset.\n";
- OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
- OS << "static constexpr uint8_t OTable[] = {\n";
- OS << " 0";
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ OS << R"(// Intrinsic ID to overload bitset.
+#ifdef GET_INTRINSIC_OVERLOAD_TABLE
+static constexpr uint8_t OTable[] = {
+ 0
+ )";
+ for (auto [I, Int] : enumerate(Ints)) {
// Add one to the index so we emit a null bit for the invalid #0 intrinsic.
- if ((i + 1) % 8 == 0)
+ size_t Idx = I + 1;
+
+ if (Idx % 8 == 0)
OS << ",\n 0";
- if (Ints[i].isOverloaded)
- OS << " | (1<<" << (i + 1) % 8 << ')';
+ if (Int.isOverloaded)
+ OS << " | (1<<" << Idx % 8 << ')';
}
OS << "\n};\n\n";
// OTable contains a true bit at the position if the intrinsic is overloaded.
@@ -257,20 +268,17 @@ void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
OS << "#endif\n\n";
}
-/// ComputeFixedEncoding - If we can encode the type signature for this
-/// intrinsic into 32 bits, return it. If not, return ~0U.
-static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
- std::vector<unsigned char> &TypeSig) {
- if (auto *R = Int.TheDef->getValue("TypeSig")) {
- for (auto &a : cast<ListInit>(R->getValue())->getValues()) {
- for (auto &b : cast<ListInit>(a)->getValues())
+/// ComputeTypeSignature - Compute type signature of the intrinsic `Int`.
+static std::vector<unsigned char>
+ComputeTypeSignature(const CodeGenIntrinsic &Int) {
+ std::vector<unsigned char> TypeSig;
+ if (const auto *R = Int.TheDef->getValue("TypeSig")) {
+ for (const auto *a : cast<ListInit>(R->getValue())->getValues()) {
+ for (const auto *b : cast<ListInit>(a)->getValues())
TypeSig.push_back(cast<IntInit>(b)->getValue());
}
}
-}
-
-static void printIITEntry(raw_ostream &OS, unsigned char X) {
- OS << (unsigned)X;
+ return TypeSig;
}
void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
@@ -278,30 +286,26 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
// If we can compute a 32-bit fixed encoding for this intrinsic, do so and
// capture it in this vector, otherwise store a ~0U.
std::vector<unsigned> FixedEncodings;
-
SequenceToOffsetTable<std::vector<unsigned char>> LongEncodingTable;
- std::vector<unsigned char> TypeSig;
-
// Compute the unique argument type info.
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ for (const CodeGenIntrinsic &Int : Ints) {
// Get the signature for the intrinsic.
- TypeSig.clear();
- ComputeFixedEncoding(Ints[i], TypeSig);
+ std::vector<unsigned char> TypeSig = ComputeTypeSignature(Int);
- // Check to see if we can encode it into a 32-bit word. We can only encode
+ // Check to see if we can encode it into a 32-bit word. We can only encode
// 8 nibbles into a 32-bit word.
if (TypeSig.size() <= 8) {
- bool Failed = false;
+ // Attempt to pack elements of TypeSig into a 32-bit word, starting from
+ // the most significant nibble.
unsigned Result = 0;
- for (unsigned i = 0, e = TypeSig.size(); i != e; ++i) {
- // If we had an unencodable argument, bail out.
- if (TypeSig[i] > 15) {
+ bool Failed = false;
+ for_each(reverse(TypeSig), [&Result, &Failed](unsigned char C) {
+ if (C > 15)
Failed = true;
- break;
- }
- Result = (Result << 4) | TypeSig[e - i - 1];
- }
+ else
+ Result = (Result << 4) | C;
+ });
// If this could be encoded into a 31-bit word, return it.
if (!Failed && (Result >> 31) == 0) {
@@ -320,23 +324,23 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
LongEncodingTable.layout();
- OS << "// Global intrinsic function declaration type table.\n";
- OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n";
+ OS << R"(// Global intrinsic function declaration type table.
+#ifdef GET_INTRINSIC_GENERATOR_GLOBAL
+static constexpr unsigned IIT_Table[] = {
- OS << "static constexpr unsigned IIT_Table[] = {\n ";
+)";
- for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {
- if ((i & 7) == 7)
+ for (auto [Idx, FixedEncoding, Int] : enumerate(FixedEncodings, Ints)) {
+ if ((Idx & 7) == 7)
OS << "\n ";
// If the entry fit in the table, just emit it.
- if (FixedEncodings[i] != ~0U) {
- OS << "0x" << Twine::utohexstr(FixedEncodings[i]) << ", ";
+ if (FixedEncoding != ~0U) {
+ OS << "0x" << Twine::utohexstr(FixedEncoding) << ", ";
continue;
}
- TypeSig.clear();
- ComputeFixedEncoding(Ints[i], TypeSig);
+ std::vector<unsigned char> TypeSig = ComputeTypeSignature(Int);
// Otherwise, emit the offset into the long encoding table. We emit it this
// way so that it is easier to read the offset in the .def file.
@@ -348,7 +352,8 @@ void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
// Emit the shared table of register lists.
OS << "static constexpr unsigned char IIT_LongEncodingTable[] = {\n";
if (!LongEncodingTable.empty())
- LongEncodingTable.emit(OS, printIITEntry);
+ LongEncodingTable.emit(
+ OS, [](raw_ostream &OS, unsigned char C) { OS << (unsigned)C; });
OS << " 255\n};\n\n";
OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
@@ -399,16 +404,14 @@ struct AttributeComparator {
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS) {
- OS << "// Add parameter attributes that are not common to all intrinsics.\n";
- OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
-
+ OS << R"(// Add parameter attributes that are not common to all intrinsics.
+#ifdef GET_INTRINSIC_ATTRIBUTES
+static AttributeSet getIntrinsicArgAttributeSet(LLVMContext &C, unsigned ID) {
+ switch (ID) {
+ default: llvm_unreachable("Invalid attribute set number");)";
// Compute unique argument attribute sets.
std::map<SmallVector<CodeGenIntrinsic::ArgAttribute, 0>, unsigned>
UniqArgAttributes;
- OS << "static AttributeSet getIntrinsicArgAttributeSet("
- << "LLVMContext &C, unsigned ID) {\n"
- << " switch (ID) {\n"
- << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
for (const CodeGenIntrinsic &Int : Ints) {
for (auto &Attrs : Int.ArgumentAttributes) {
if (Attrs.empty())
@@ -419,118 +422,127 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
continue;
assert(is_sorted(Attrs) && "Argument attributes are not sorted");
-
- OS << " case " << ID << ":\n";
- OS << " return AttributeSet::get(C, {\n";
- for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) {
- switch (Attr.Kind) {
+ auto getAttrEnumName =
+ [](CodeGenIntrinsic::ArgAttrKind Kind) -> StringRef {
+ switch (Kind) {
case CodeGenIntrinsic::NoCapture:
- OS << " Attribute::get(C, Attribute::NoCapture),\n";
- break;
+ return "NoCapture";
case CodeGenIntrinsic::NoAlias:
- OS << " Attribute::get(C, Attribute::NoAlias),\n";
- break;
+ return "NoAlias";
case CodeGenIntrinsic::NoUndef:
- OS << " Attribute::get(C, Attribute::NoUndef),\n";
- break;
+ return "NoUndef";
case CodeGenIntrinsic::NonNull:
- OS << " Attribute::get(C, Attribute::NonNull),\n";
- break;
+ return "NonNull";
case CodeGenIntrinsic::Returned:
- OS << " Attribute::get(C, Attribute::Returned),\n";
- break;
+ return "Returned";
case CodeGenIntrinsic::ReadOnly:
- OS << " Attribute::get(C, Attribute::ReadOnly),\n";
- break;
+ return "ReadOnly";
case CodeGenIntrinsic::WriteOnly:
- OS << " Attribute::get(C, Attribute::WriteOnly),\n";
- break;
+ return "WriteOnly";
case CodeGenIntrinsic::ReadNone:
- OS << " Attribute::get(C, Attribute::ReadNone),\n";
- break;
+ return "ReadNone";
case CodeGenIntrinsic::ImmArg:
- OS << " Attribute::get(C, Attribute::ImmArg),\n";
- break;
+ return "ImmArg";
case CodeGenIntrinsic::Alignment:
- OS << " Attribute::get(C, Attribute::Alignment, " << Attr.Value
- << "),\n";
- break;
+ return "Alignment";
case CodeGenIntrinsic::Dereferenceable:
- OS << " Attribute::get(C, Attribute::Dereferenceable, "
- << Attr.Value << "),\n";
- break;
+ return "Dereferenceable";
}
+ };
+
+ OS << formatv(R"(
+ case {0}:
+ return AttributeSet::get(C, {{
+)",
+ ID);
+ for (const CodeGenIntrinsic::ArgAttribute &Attr : Attrs) {
+ StringRef AttrName = getAttrEnumName(Attr.Kind);
+ if (Attr.Kind == CodeGenIntrinsic::Alignment ||
+ Attr.Kind == CodeGenIntrinsic::Dereferenceable)
+ OS << formatv(" Attribute::get(C, Attribute::{0}, {1}),\n",
+ AttrName, Attr.Value);
+ else
+ OS << formatv(" Attribute::get(C, Attribute::{0}),\n", AttrName);
}
- OS << " });\n";
+ OS << " });";
}
}
- OS << " }\n";
- OS << "}\n\n";
+ OS << R"(
+ }
+} // getIntrinsicArgAttributeSet
+
+static AttributeSet getIntrinsicFnAttributeSet(LLVMContext &C, unsigned ID) {
+ switch (ID) {
+ default: llvm_unreachable("Invalid attribute set number");)";
// Compute unique function attribute sets.
std::map<const CodeGenIntrinsic *, unsigned, FnAttributeComparator>
UniqFnAttributes;
- OS << "static AttributeSet getIntrinsicFnAttributeSet("
- << "LLVMContext &C, unsigned ID) {\n"
- << " switch (ID) {\n"
- << " default: llvm_unreachable(\"Invalid attribute set number\");\n";
for (const CodeGenIntrinsic &Intrinsic : Ints) {
unsigned ID = UniqFnAttributes.size();
if (!UniqFnAttributes.try_emplace(&Intrinsic, ID).second)
continue;
-
- OS << " case " << ID << ":\n"
- << " return AttributeSet::get(C, {\n";
+ OS << formatv(R"(
+ case {0}:
+ return AttributeSet::get(C, {{
+)",
+ ID);
+ auto addAttribute = [&OS](StringRef Attr) {
+ OS << formatv(" Attribute::get(C, Attribute::{0}),\n", Attr);
+ };
if (!Intrinsic.canThrow)
- OS << " Attribute::get(C, Attribute::NoUnwind),\n";
+ addAttribute("NoUnwind");
if (Intrinsic.isNoReturn)
- OS << " Attribute::get(C, Attribute::NoReturn),\n";
+ addAttribute("NoReturn");
if (Intrinsic.isNoCallback)
- OS << " Attribute::get(C, Attribute::NoCallback),\n";
+ addAttribute("NoCallback");
if (Intrinsic.isNoSync)
- OS << " Attribute::get(C, Attribute::NoSync),\n";
+ addAttribute("NoSync");
if (Intrinsic.isNoFree)
- OS << " Attribute::get(C, Attribute::NoFree),\n";
+ addAttribute("NoFree");
if (Intrinsic.isWillReturn)
- OS << " Attribute::get(C, Attribute::WillReturn),\n";
+ addAttribute("WillReturn");
if (Intrinsic.isCold)
- OS << " Attribute::get(C, Attribute::Cold),\n";
+ addAttribute("Cold");
if (Intrinsic.isNoDuplicate)
- OS << " Attribute::get(C, Attribute::NoDuplicate),\n";
+ addAttribute("NoDuplicate");
if (Intrinsic.isNoMerge)
- OS << " Attribute::get(C, Attribute::NoMerge),\n";
+ addAttribute("NoMerge");
if (Intrinsic.isConvergent)
- OS << " Attribute::get(C, Attribute::Convergent),\n";
+ addAttribute("Convergent");
if (Intrinsic.isSpeculatable)
- OS << " Attribute::get(C, Attribute::Speculatable),\n";
+ addAttribute("Speculatable");
if (Intrinsic.isStrictFP)
- OS << " Attribute::get(C, Attribute::StrictFP),\n";
+ addAttribute("StrictFP");
MemoryEffects ME = Intrinsic.ME;
// TODO: IntrHasSideEffects should affect not only readnone intrinsics.
if (ME.doesNotAccessMemory() && Intrinsic.hasSideEffects)
ME = MemoryEffects::unknown();
if (ME != MemoryEffects::unknown()) {
- OS << " Attribute::getWithMemoryEffects(C, "
- << "MemoryEffects::createFromIntValue(" << ME.toIntValue() << ")),\n";
+ OS << formatv(" // {0}\n", ME);
+ OS << formatv(" Attribute::getWithMemoryEffects(C, "
+ "MemoryEffects::createFromIntValue({0})),\n",
+ ME.toIntValue());
}
OS << " });\n";
}
- OS << " }\n";
- OS << "}\n\n";
- OS << "AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
+ OS << R"( }
+} // getIntrinsicFnAttributeSet
+
+AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {
+)";
- // Compute the maximum number of attribute arguments and the map
+ // Compute the maximum number of attribute arguments and the map.
typedef std::map<const CodeGenIntrinsic *, unsigned, AttributeComparator>
UniqAttrMapTy;
UniqAttrMapTy UniqAttributes;
- unsigned maxArgAttrs = 0;
+ unsigned MaxArgAttrs = 0;
unsigned AttrNum = 0;
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- const CodeGenIntrinsic &intrinsic = Ints[i];
- maxArgAttrs =
- std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
- unsigned &N = UniqAttributes[&intrinsic];
+ for (const CodeGenIntrinsic &Int : Ints) {
+ MaxArgAttrs =
+ std::max(MaxArgAttrs, unsigned(Int.ArgumentAttributes.size()));
+ unsigned &N = UniqAttributes[&Int];
if (N)
continue;
N = ++AttrNum;
@@ -539,67 +551,65 @@ void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
// Emit an array of AttributeList. Most intrinsics will have at least one
// entry, for the function itself (index ~1), which is usually nounwind.
- OS << " static constexpr uint16_t IntrinsicsToAttributesMap[] = {\n";
-
- for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
- const CodeGenIntrinsic &intrinsic = Ints[i];
+ OS << " static constexpr uint16_t IntrinsicsToAttributesMap[] = {";
+ for (const CodeGenIntrinsic &Int : Ints)
+ OS << formatv("\n {0}, // {1}", UniqAttributes[&Int], Int.Name);
- OS << " " << UniqAttributes[&intrinsic] << ", // " << intrinsic.Name
- << "\n";
- }
- OS << " };\n\n";
-
- OS << " std::pair<unsigned, AttributeSet> AS[" << maxArgAttrs + 1 << "];\n";
- OS << " unsigned NumAttrs = 0;\n";
- OS << " if (id != 0) {\n";
- OS << " switch(IntrinsicsToAttributesMap[id - 1]) {\n";
- OS << " default: llvm_unreachable(\"Invalid attribute number\");\n";
- for (auto UniqAttribute : UniqAttributes) {
- OS << " case " << UniqAttribute.second << ": {\n";
+ OS << formatv(R"(
+ };
+ std::pair<unsigned, AttributeSet> AS[{0}];
+ unsigned NumAttrs = 0;
+ if (id != 0) {{
+ switch(IntrinsicsToAttributesMap[id - 1]) {{
+ default: llvm_unreachable("Invalid attribute number");
+)",
+ MaxArgAttrs + 1);
- const CodeGenIntrinsic &Intrinsic = *(UniqAttribute.first);
+ for (const auto [IntPtr, UniqueID] : UniqAttributes) {
+ OS << formatv(" case {0}:\n", UniqueID);
+ const CodeGenIntrinsic &Int = *IntPtr;
// Keep track of the number of attributes we're writing out.
- unsigned numAttrs = 0;
+ unsigned NumAttrs = 0;
- for (const auto &[AttrIdx, Attrs] :
- enumerate(Intrinsic.ArgumentAttributes)) {
+ for (const auto &[AttrIdx, Attrs] : enumerate(Int.ArgumentAttributes)) {
if (Attrs.empty())
continue;
- unsigned ID = UniqArgAttributes.find(Attrs)->second;
- OS << " AS[" << numAttrs++ << "] = {" << AttrIdx
- << ", getIntrinsicArgAttributeSet(C, " << ID << ")};\n";
+ unsigned ArgAttrID = UniqArgAttributes.find(Attrs)->second;
+ OS << formatv(
+ " AS[{0}] = {{{1}, getIntrinsicArgAttributeSet(C, {2})};\n",
+ NumAttrs++, AttrIdx, ArgAttrID);
}
- if (!Intrinsic.canThrow ||
- (Intrinsic.ME != MemoryEffects::unknown() &&
- !Intrinsic.hasSideEffects) ||
- Intrinsic.isNoReturn || Intrinsic.isNoCallback || Intrinsic.isNoSync ||
- Intrinsic.isNoFree || Intrinsic.isWillReturn || Intrinsic.isCold ||
- Intrinsic.isNoDuplicate || Intrinsic.isNoMerge ||
- Intrinsic.isConvergent || Intrinsic.isSpeculatable ||
- Intrinsic.isStrictFP) {
- unsigned ID = UniqFnAttributes.find(&Intrinsic)->second;
- OS << " AS[" << numAttrs++ << "] = {AttributeList::FunctionIndex, "
- << "getIntrinsicFnAttributeSet(C, " << ID << ")};\n";
+ if (!Int.canThrow ||
+ (Int.ME != MemoryEffects::unknown() && !Int.hasSideEffects) ||
+ Int.isNoReturn || Int.isNoCallback || Int.isNoSync || Int.isNoFree ||
+ Int.isWillReturn || Int.isCold || Int.isNoDuplicate || Int.isNoMerge ||
+ Int.isConvergent || Int.isSpeculatable || Int.isStrictFP) {
+ unsigned FnAttrID = UniqFnAttributes.find(&Int)->second;
+ OS << formatv(" AS[{0}] = {{AttributeList::FunctionIndex, "
+ "getIntrinsicFnAttributeSet(C, {1})};\n",
+ NumAttrs++, FnAttrID);
}
- if (numAttrs) {
- OS << " NumAttrs = " << numAttrs << ";\n";
- OS << " break;\n";
- OS << " }\n";
+ if (NumAttrs) {
+ OS << formatv(R"( NumAttrs = {0};
+ break;
+)",
+ NumAttrs);
} else {
OS << " return AttributeList();\n";
- OS << " }\n";
}
}
- OS << " }\n";
- OS << " }\n";
- OS << " return AttributeList::get(C, ArrayRef(AS, NumAttrs));\n";
- OS << "}\n";
- OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
+ OS << R"( }
+ }
+ return AttributeList::get(C, ArrayRef(AS, NumAttrs));
+}
+#endif // GET_INTRINSIC_ATTRIBUTES
+
+)";
}
void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
More information about the llvm-commits
mailing list