[llvm] [NFC][TableGen] Adopt CodeGenHelpers in SubtargetEmitter (PR #163820)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 29 12:43:55 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-tablegen
Author: Rahul Joshi (jurahul)
<details>
<summary>Changes</summary>
- Adopt ifdef and namespace emitters in SubtargeEmitter.
- To aid that, factor out emission of different sections of the code into individual helper functions.
---
Full diff: https://github.com/llvm/llvm-project/pull/163820.diff
2 Files Affected:
- (modified) llvm/include/llvm/TableGen/CodeGenHelpers.h (+37-7)
- (modified) llvm/utils/TableGen/SubtargetEmitter.cpp (+68-70)
``````````diff
diff --git a/llvm/include/llvm/TableGen/CodeGenHelpers.h b/llvm/include/llvm/TableGen/CodeGenHelpers.h
index e22c6d4f6d390..053f7e4aab866 100644
--- a/llvm/include/llvm/TableGen/CodeGenHelpers.h
+++ b/llvm/include/llvm/TableGen/CodeGenHelpers.h
@@ -20,18 +20,37 @@
#include <string>
namespace llvm {
-// Simple RAII helper for emitting ifdef-undef-endif scope.
+// Simple RAII helper for emitting ifdef-undef-endif scope. `LateUndef` controls
+// whether the undef is emitted at the start of the scope (false) or at the end
+// of the scope (true).
class IfDefEmitter {
public:
- IfDefEmitter(raw_ostream &OS, StringRef Name) : Name(Name.str()), OS(OS) {
- OS << "#ifdef " << Name << "\n"
- << "#undef " << Name << "\n\n";
+ IfDefEmitter(raw_ostream &OS, StringRef Name, bool LateUndef = false)
+ : Name(Name.str()), OS(OS), LateUndef(LateUndef) {
+ OS << "#ifdef " << Name << "\n";
+ if (!LateUndef)
+ OS << "#undef " << Name << "\n";
+ OS << "\n";
+ }
+ ~IfDefEmitter() { close(); }
+
+ // Explicit function to close the ifdef scopes.
+ void close() {
+ if (Closed)
+ return;
+
+ OS << "\n";
+ if (LateUndef)
+ OS << "#undef " << Name << "\n";
+ OS << "#endif // " << Name << "\n\n";
+ Closed = true;
}
- ~IfDefEmitter() { OS << "\n#endif // " << Name << "\n\n"; }
private:
std::string Name;
raw_ostream &OS;
+ bool LateUndef;
+ bool Closed = false;
};
// Simple RAII helper for emitting header include guard (ifndef-define-endif).
@@ -42,11 +61,20 @@ class IncludeGuardEmitter {
OS << "#ifndef " << Name << "\n"
<< "#define " << Name << "\n\n";
}
- ~IncludeGuardEmitter() { OS << "\n#endif // " << Name << "\n"; }
+ ~IncludeGuardEmitter() { close(); }
+
+ // Explicit function to close the ifdef scopes.
+ void close() {
+ if (Closed)
+ return;
+ OS << "\n#endif // " << Name << "\n\n";
+ Closed = true;
+ }
private:
std::string Name;
raw_ostream &OS;
+ bool Closed = false;
};
// Simple RAII helper for emitting namespace scope. Name can be a single
@@ -64,7 +92,9 @@ class NamespaceEmitter {
// Explicit function to close the namespace scopes.
void close() {
- if (!Closed && !Name.empty())
+ if (Closed)
+ return;
+ if (!Name.empty())
OS << "} // namespace " << Name << "\n";
Closed = true;
}
diff --git a/llvm/utils/TableGen/SubtargetEmitter.cpp b/llvm/utils/TableGen/SubtargetEmitter.cpp
index 2f15cc8c76548..c3fb089d3f608 100644
--- a/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -27,6 +27,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/CodeGenHelpers.h"
#include "llvm/TableGen/Error.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringToOffsetTable.h"
@@ -75,7 +76,15 @@ class SubtargetEmitter : TargetFeaturesEmitter {
CodeGenTarget TGT;
CodeGenSchedModels &SchedModels;
+ FeatureMapTy emitEnums(raw_ostream &OS);
void emitSubtargetInfoMacroCalls(raw_ostream &OS);
+ std::tuple<unsigned, unsigned, unsigned>
+ emitMCDesc(raw_ostream &OS, const FeatureMapTy &FeatureMap);
+ void emitTargetDesc(raw_ostream &OS);
+ void emitHeader(raw_ostream &OS);
+ void emitCtor(raw_ostream &OS, unsigned NumNames, unsigned NumFeatures,
+ unsigned NumProcs);
+
unsigned featureKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
unsigned cpuKeyValues(raw_ostream &OS, const FeatureMapTy &FeatureMap);
unsigned cpuNames(raw_ostream &OS);
@@ -141,7 +150,9 @@ class SubtargetEmitter : TargetFeaturesEmitter {
/// Emit some information about the SubtargetFeature as calls to a macro so
/// that they can be used from C++.
void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) {
- OS << "\n#ifdef GET_SUBTARGETINFO_MACRO\n";
+ // Undef the GET_SUBTARGETINFO_MACRO macro at the end of the scope since its
+ // used within the scope.
+ IfDefEmitter IfDefMacro(OS, "GET_SUBTARGETINFO_MACRO", /*LateUndef=*/true);
std::vector<const Record *> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
@@ -167,14 +178,6 @@ void SubtargetEmitter::emitSubtargetInfoMacroCalls(raw_ostream &OS) {
OS << "GET_SUBTARGETINFO_MACRO(" << FieldName << ", " << Default << ", "
<< Getter << ")\n";
}
- OS << "#undef GET_SUBTARGETINFO_MACRO\n";
- OS << "#endif // GET_SUBTARGETINFO_MACRO\n\n";
-
- OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
- OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
-
- if (Target == "AArch64")
- OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n";
}
//
@@ -440,26 +443,24 @@ void SubtargetEmitter::emitStageAndOperandCycleData(
continue;
StringRef Name = ProcModel.ItinsDef->getName();
- OS << "\n// Functional units for \"" << Name << "\"\n"
- << "namespace " << Name << "FU {\n";
+ OS << "\n// Functional units for \"" << Name << "\"\n";
+ NamespaceEmitter FUNamespace(OS, (Name + Twine("FU")).str());
for (const auto &[Idx, FU] : enumerate(FUs))
OS << " const InstrStage::FuncUnits " << FU->getName() << " = 1ULL << "
<< Idx << ";\n";
- OS << "} // end namespace " << Name << "FU\n";
+ FUNamespace.close();
ConstRecVec BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
if (BPs.empty())
continue;
- OS << "\n// Pipeline forwarding paths for itineraries \"" << Name << "\"\n"
- << "namespace " << Name << "Bypass {\n";
+ OS << "\n// Pipeline forwarding paths for itineraries \"" << Name << "\"\n";
+ NamespaceEmitter BypassNamespace(OS, (Name + Twine("Bypass")).str());
OS << " const unsigned NoBypass = 0;\n";
for (const auto &[Idx, BP] : enumerate(BPs))
OS << " const unsigned " << BP->getName() << " = 1 << " << Idx << ";\n";
-
- OS << "} // end namespace " << Name << "Bypass\n";
}
// Begin stages table
@@ -1940,13 +1941,13 @@ void SubtargetEmitter::parseFeaturesFunction(raw_ostream &OS) {
}
void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
- OS << "namespace " << Target << "_MC {\n"
- << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n"
+ NamespaceEmitter NS(OS, (Target + Twine("_MC")).str());
+ OS << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,\n"
<< " const MCInst *MI, const MCInstrInfo *MCII, "
<< "const MCSubtargetInfo &STI, unsigned CPUID) {\n";
emitSchedModelHelpersImpl(OS, /* OnlyExpandMCPredicates */ true);
OS << "}\n";
- OS << "} // end namespace " << Target << "_MC\n\n";
+ NS.close();
OS << "struct " << Target
<< "GenMCSubtargetInfo : public MCSubtargetInfo {\n";
@@ -1982,8 +1983,7 @@ void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
}
void SubtargetEmitter::emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS) {
- OS << "\n#ifdef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n";
- OS << "#undef GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n";
+ IfDefEmitter IfDefDecls(OS, "GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS");
STIPredicateExpander PE(Target, /*Indent=*/0);
PE.setExpandForMC(true);
@@ -1991,37 +1991,29 @@ void SubtargetEmitter::emitMcInstrAnalysisPredicateFunctions(raw_ostream &OS) {
for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
PE.expandSTIPredicate(OS, Fn);
- OS << "#endif // GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS\n\n";
-
- OS << "\n#ifdef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n";
- OS << "#undef GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n";
+ IfDefDecls.close();
+ IfDefEmitter IfDefDefs(OS, "GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS");
std::string ClassPrefix = Target + "MCInstrAnalysis";
PE.setExpandDefinition(true);
PE.setClassPrefix(ClassPrefix);
for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
PE.expandSTIPredicate(OS, Fn);
-
- OS << "#endif // GET_STIPREDICATE_DEFS_FOR_MC_ANALYSIS\n\n";
}
-//
-// SubtargetEmitter::run - Main subtarget enumeration emitter.
-//
-void SubtargetEmitter::run(raw_ostream &OS) {
- emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
-
- OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
- OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
-
- OS << "namespace llvm {\n";
- auto FeatureMap = enumeration(OS);
- OS << "} // end namespace llvm\n\n";
- OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+FeatureMapTy SubtargetEmitter::emitEnums(raw_ostream &OS) {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_ENUM");
+ NamespaceEmitter NS(OS, "llvm");
+ return enumeration(OS);
+}
- emitSubtargetInfoMacroCalls(OS);
+std::tuple<unsigned, unsigned, unsigned>
+SubtargetEmitter::emitMCDesc(raw_ostream &OS, const FeatureMapTy &FeatureMap) {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_MC_DESC");
+ if (Target == "AArch64")
+ OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n";
+ NamespaceEmitter LlvmNS(OS, "llvm");
- OS << "namespace llvm {\n";
unsigned NumFeatures = featureKeyValues(OS, FeatureMap);
OS << "\n";
emitSchedModel(OS);
@@ -2067,13 +2059,11 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "nullptr, nullptr, nullptr";
}
OS << ");\n}\n\n";
+ return {NumNames, NumFeatures, NumProcs};
+}
- OS << "} // end namespace llvm\n\n";
-
- OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
-
- OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
- OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n";
+void SubtargetEmitter::emitTargetDesc(raw_ostream &OS) {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_TARGET_DESC");
OS << "#include \"llvm/ADT/BitmaskEnum.h\"\n";
OS << "#include \"llvm/Support/Debug.h\"\n";
@@ -2081,21 +2071,21 @@ void SubtargetEmitter::run(raw_ostream &OS) {
if (Target == "AArch64")
OS << "#include \"llvm/TargetParser/AArch64TargetParser.h\"\n\n";
parseFeaturesFunction(OS);
+}
- OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
-
+void SubtargetEmitter::emitHeader(raw_ostream &OS) {
// Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
- OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
- OS << "#undef GET_SUBTARGETINFO_HEADER\n\n";
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_HEADER");
+ NamespaceEmitter LLVMNS(OS, "llvm");
std::string ClassName = Target + "GenSubtargetInfo";
- OS << "namespace llvm {\n";
OS << "class DFAPacketizer;\n";
- OS << "namespace " << Target << "_MC {\n"
- << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,"
- << " const MCInst *MI, const MCInstrInfo *MCII, "
- << "const MCSubtargetInfo &STI, unsigned CPUID);\n"
- << "} // end namespace " << Target << "_MC\n\n";
+ {
+ NamespaceEmitter MCNS(OS, (Target + Twine("_MC")).str());
+ OS << "unsigned resolveVariantSchedClassImpl(unsigned SchedClass,"
+ << " const MCInst *MI, const MCInstrInfo *MCII, "
+ << "const MCSubtargetInfo &STI, unsigned CPUID);\n";
+ }
OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
<< " explicit " << ClassName << "(const Triple &TT, StringRef CPU, "
<< "StringRef TuneCPU, StringRef FS);\n"
@@ -2140,17 +2130,15 @@ void SubtargetEmitter::run(raw_ostream &OS) {
PE.setByRef(false);
for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
PE.expandSTIPredicate(OS, Fn);
+ OS << "};\n";
+}
- OS << "};\n"
- << "} // end namespace llvm\n\n";
-
- OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
-
- OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
- OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
-
+void SubtargetEmitter::emitCtor(raw_ostream &OS, unsigned NumNames,
+ unsigned NumFeatures, unsigned NumProcs) {
+ IfDefEmitter IfDef(OS, "GET_SUBTARGETINFO_CTOR");
OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
- OS << "namespace llvm {\n";
+
+ NamespaceEmitter LLVMNS(OS, "llvm");
OS << "extern const llvm::StringRef " << Target << "Names[];\n";
OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
OS << "extern const llvm::SubtargetSubTypeKV " << Target << "SubTypeKV[];\n";
@@ -2167,6 +2155,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
}
+ std::string ClassName = Target + "GenSubtargetInfo";
OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, "
<< "StringRef TuneCPU, StringRef FS)\n";
@@ -2204,11 +2193,20 @@ void SubtargetEmitter::run(raw_ostream &OS) {
emitSchedModelHelpers(ClassName, OS);
emitHwModeCheck(ClassName, OS, /*IsMC=*/false);
emitGetMacroFusions(ClassName, OS);
+}
- OS << "} // end namespace llvm\n\n";
-
- OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
+//
+// SubtargetEmitter::run - Main subtarget enumeration emitter.
+//
+void SubtargetEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+ auto FeatureMap = emitEnums(OS);
+ emitSubtargetInfoMacroCalls(OS);
+ auto [NumNames, NumFeatures, NumProcs] = emitMCDesc(OS, FeatureMap);
+ emitTargetDesc(OS);
+ emitHeader(OS);
+ emitCtor(OS, NumNames, NumFeatures, NumProcs);
emitMcInstrAnalysisPredicateFunctions(OS);
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/163820
More information about the llvm-commits
mailing list