Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 37 additions & 7 deletions llvm/include/llvm/TableGen/CodeGenHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,37 @@

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).
Expand All @@ -43,11 +62,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
Expand All @@ -65,7 +93,9 @@ class NamespaceEmitter {

// Explicit function to close the namespace scopes.
void close() {
if (!Closed && !Name.empty())
if (Closed)
return;
if (!Name.empty())
OS << "\n} // namespace " << Name << "\n";
Closed = true;
}
Expand Down
165 changes: 82 additions & 83 deletions llvm/utils/TableGen/SubtargetEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 it's
// used within the scope.
IfDefEmitter IfDefMacro(OS, "GET_SUBTARGETINFO_MACRO", /*LateUndef=*/true);

std::vector<const Record *> FeatureList =
Records.getAllDerivedDefinitions("SubtargetFeature");
Expand All @@ -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";
}

//
Expand Down Expand Up @@ -440,26 +443,24 @@ void SubtargetEmitter::emitStageAndOperandCycleData(
continue;

StringRef Name = ProcModel.ItinsDef->getName();
OS << "\n// Functional units for \"" << Name << "\"\n"
<< "namespace " << Name << "FU {\n";

for (const auto &[Idx, FU] : enumerate(FUs))
OS << " const InstrStage::FuncUnits " << FU->getName() << " = 1ULL << "
<< Idx << ";\n";
{
OS << "\n// Functional units for \"" << Name << "\"\n";
NamespaceEmitter FUNamespace(OS, (Name + Twine("FU")).str());

OS << "} // end namespace " << Name << "FU\n";
for (const auto &[Idx, FU] : enumerate(FUs))
OS << " const InstrStage::FuncUnits " << FU->getName() << " = 1ULL << "
<< Idx << ";\n";
}

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
Expand Down Expand Up @@ -1940,13 +1941,14 @@ void SubtargetEmitter::parseFeaturesFunction(raw_ostream &OS) {
}

void SubtargetEmitter::emitGenMCSubtargetInfo(raw_ostream &OS) {
OS << "namespace " << Target << "_MC {\n"
<< "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";
{
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 << "struct " << Target
<< "GenMCSubtargetInfo : public MCSubtargetInfo {\n";
Expand Down Expand Up @@ -1982,46 +1984,37 @@ 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";

STIPredicateExpander PE(Target, /*Indent=*/0);
PE.setExpandForMC(true);
PE.setByRef(true);
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";
{
IfDefEmitter IfDefDecls(OS, "GET_STIPREDICATE_DECLS_FOR_MC_ANALYSIS");
PE.setExpandForMC(true);
PE.setByRef(true);
for (const STIPredicateFunction &Fn : SchedModels.getSTIPredicates())
PE.expandSTIPredicate(OS, Fn);
}

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);
Expand Down Expand Up @@ -2067,35 +2060,33 @@ 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";
OS << "#include \"llvm/Support/raw_ostream.h\"\n\n";
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"
Expand Down Expand Up @@ -2140,17 +2131,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";
Expand All @@ -2167,6 +2156,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";

Expand Down Expand Up @@ -2204,11 +2194,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);
}

Expand Down