Skip to content

Commit 71eaf14

Browse files
authored
[TableGen] Split *GenRegisterInfo.inc. (#167700)
Reduces memory usage compiling backend sources, most notably for AMDGPU by ~98 MB per source on average. AMDGPUGenRegisterInfo.inc is tens of megabytes in size now, and is even larger downstream. At the same time, it is included in nearly all backend sources, typically just for a small portion of its content, resulting in compilation being unnecessarily memory-hungry, which in turn stresses buildbots and wastes their resources. Splitting .inc files also helps avoiding extra ccache misses where changes in .td files don't cause changes in all parts of what previously was a single .inc file. It is thought that rather than building on top of the current single-output-file design of TableGen, e.g., using `split-file`, it would be more preferable to recognise the need for multi-file outputs and give it a proper first-class support directly in TableGen.
1 parent 0e1152e commit 71eaf14

File tree

14 files changed

+201
-73
lines changed

14 files changed

+201
-73
lines changed

llvm/docs/TableGen/index.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ TableGen runs just like any other LLVM tool. The first (optional) argument
5555
specifies the file to read. If a filename is not specified, ``llvm-tblgen``
5656
reads from standard input.
5757

58+
The ``-o`` option specifies the output file or ``-`` to output to
59+
stdout. Where TableGen produces multiple output files, the option
60+
specifies the name of the main output file, which also works as the
61+
name prefix for other output files.
62+
5863
To be useful, one of the `backends`_ must be used. These backends are
5964
selectable on the command line (type '``llvm-tblgen -help``' for a list). For
6065
example, to get a list of all of the definitions that subclass a particular type

llvm/include/llvm/TableGen/Main.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,34 @@
1515

1616
#include "llvm/Support/CommandLine.h"
1717
#include <functional>
18+
#include <map>
1819

1920
namespace llvm {
2021

2122
class raw_ostream;
2223
class RecordKeeper;
2324

24-
/// Perform the action using Records, and write output to OS.
25+
struct TableGenOutputFiles {
26+
std::string MainFile;
27+
28+
// Translates additional output file names to their contents.
29+
std::map<StringRef, std::string> AdditionalFiles;
30+
};
31+
2532
/// Returns true on error, false otherwise.
2633
using TableGenMainFn = bool(raw_ostream &OS, const RecordKeeper &Records);
2734

35+
/// Perform the action using Records, and store output in OutFiles.
36+
/// Returns true on error, false otherwise.
37+
using MultiFileTableGenMainFn = bool(TableGenOutputFiles &OutFiles,
38+
const RecordKeeper &Records);
39+
2840
int TableGenMain(const char *argv0,
2941
std::function<TableGenMainFn> MainFn = nullptr);
3042

43+
int TableGenMain(const char *argv0,
44+
std::function<MultiFileTableGenMainFn> MainFn = nullptr);
45+
3146
/// Controls emitting large character arrays as strings or character arrays.
3247
/// Typically set to false when building with MSVC.
3348
extern cl::opt<bool> EmitLongStrLiterals;

llvm/include/llvm/TableGen/TableGenBackend.h

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#include "llvm/ADT/STLFunctionalExtras.h"
1717
#include "llvm/ADT/StringRef.h"
18+
#include "llvm/TableGen/Main.h"
1819
#include "llvm/TableGen/Record.h"
1920

2021
namespace llvm {
@@ -23,7 +24,27 @@ class RecordKeeper;
2324
class raw_ostream;
2425

2526
namespace TableGen::Emitter {
26-
using FnT = function_ref<void(const RecordKeeper &Records, raw_ostream &OS)>;
27+
28+
/// Represents the emitting function. Can produce a single or multple output
29+
/// files.
30+
struct FnT {
31+
using SingleFileGeneratorType = void(const RecordKeeper &Records,
32+
raw_ostream &OS);
33+
using MultiFileGeneratorType = TableGenOutputFiles(
34+
StringRef FilenamePrefix, const RecordKeeper &Records);
35+
36+
SingleFileGeneratorType *SingleFileGenerator = nullptr;
37+
MultiFileGeneratorType *MultiFileGenerator = nullptr;
38+
39+
FnT() = default;
40+
FnT(SingleFileGeneratorType *Gen) : SingleFileGenerator(Gen) {}
41+
FnT(MultiFileGeneratorType *Gen) : MultiFileGenerator(Gen) {}
42+
43+
bool operator==(const FnT &Other) const {
44+
return SingleFileGenerator == Other.SingleFileGenerator &&
45+
MultiFileGenerator == Other.MultiFileGenerator;
46+
}
47+
};
2748

2849
/// Creating an `Opt` object registers the command line option \p Name with
2950
/// TableGen backend and associates the callback \p CB with that option. If
@@ -36,17 +57,33 @@ struct Opt {
3657
/// Convienence wrapper around `Opt` that registers `EmitterClass::run` as the
3758
/// callback.
3859
template <class EmitterC> class OptClass : Opt {
39-
static void run(const RecordKeeper &RK, raw_ostream &OS) {
60+
static TableGenOutputFiles run(StringRef /*FilenamePrefix*/,
61+
const RecordKeeper &RK) {
62+
std::string S;
63+
raw_string_ostream OS(S);
4064
EmitterC(RK).run(OS);
65+
return {S, {}};
4166
}
4267

4368
public:
4469
OptClass(StringRef Name, StringRef Desc) : Opt(Name, run, Desc) {}
4570
};
4671

72+
/// A version of the wrapper for backends emitting multiple files.
73+
template <class EmitterC> class MultiFileOptClass : Opt {
74+
static TableGenOutputFiles run(StringRef FilenamePrefix,
75+
const RecordKeeper &RK) {
76+
return EmitterC(RK).run(FilenamePrefix);
77+
}
78+
79+
public:
80+
MultiFileOptClass(StringRef Name, StringRef Desc) : Opt(Name, run, Desc) {}
81+
};
82+
4783
/// Apply callback for any command line option registered above. Returns false
4884
/// is no callback was applied.
49-
bool ApplyCallback(const RecordKeeper &Records, raw_ostream &OS);
85+
bool ApplyCallback(const RecordKeeper &Records, TableGenOutputFiles &OutFiles,
86+
StringRef FilenamePrefix);
5087

5188
} // namespace TableGen::Emitter
5289

llvm/lib/TableGen/Main.cpp

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "llvm/Support/ErrorOr.h"
2424
#include "llvm/Support/FileSystem.h"
2525
#include "llvm/Support/MemoryBuffer.h"
26+
#include "llvm/Support/Path.h"
2627
#include "llvm/Support/SMLoc.h"
2728
#include "llvm/Support/SourceMgr.h"
2829
#include "llvm/Support/ToolOutputFile.h"
@@ -104,8 +105,30 @@ static int createDependencyFile(const TGParser &Parser, const char *argv0) {
104105
return 0;
105106
}
106107

108+
static int WriteOutput(const TGParser &Parser, const char *argv0,
109+
StringRef Filename, StringRef Content) {
110+
if (WriteIfChanged) {
111+
// Only updates the real output file if there are any differences.
112+
// This prevents recompilation of all the files depending on it if there
113+
// aren't any.
114+
if (auto ExistingOrErr = MemoryBuffer::getFile(Filename, /*IsText=*/true))
115+
if (std::move(ExistingOrErr.get())->getBuffer() == Content)
116+
return 0;
117+
}
118+
std::error_code EC;
119+
ToolOutputFile OutFile(Filename, EC, sys::fs::OF_Text);
120+
if (EC)
121+
return reportError(argv0, "error opening " + Filename + ": " +
122+
EC.message() + "\n");
123+
OutFile.os() << Content;
124+
if (ErrorsPrinted == 0)
125+
OutFile.keep();
126+
127+
return 0;
128+
}
129+
107130
int llvm::TableGenMain(const char *argv0,
108-
std::function<TableGenMainFn> MainFn) {
131+
std::function<MultiFileTableGenMainFn> MainFn) {
109132
RecordKeeper Records;
110133
TGTimer &Timer = Records.getTimer();
111134

@@ -144,13 +167,14 @@ int llvm::TableGenMain(const char *argv0,
144167

145168
// Write output to memory.
146169
Timer.startBackendTimer("Backend overall");
147-
std::string OutString;
148-
raw_string_ostream Out(OutString);
170+
SmallString<128> FilenamePrefix(OutputFilename);
171+
sys::path::replace_extension(FilenamePrefix, "");
172+
TableGenOutputFiles OutFiles;
149173
unsigned status = 0;
150174
// ApplyCallback will return true if it did not apply any callback. In that
151175
// case, attempt to apply the MainFn.
152-
if (TableGen::Emitter::ApplyCallback(Records, Out))
153-
status = MainFn ? MainFn(Out, Records) : 1;
176+
if (TableGen::Emitter::ApplyCallback(Records, OutFiles, FilenamePrefix))
177+
status = MainFn ? MainFn(OutFiles, Records) : 1;
154178
Timer.stopBackendTimer();
155179
if (status)
156180
return 1;
@@ -165,25 +189,17 @@ int llvm::TableGenMain(const char *argv0,
165189
}
166190

167191
Timer.startTimer("Write output");
168-
bool WriteFile = true;
169-
if (WriteIfChanged) {
170-
// Only updates the real output file if there are any differences.
171-
// This prevents recompilation of all the files depending on it if there
172-
// aren't any.
173-
if (auto ExistingOrErr =
174-
MemoryBuffer::getFile(OutputFilename, /*IsText=*/true))
175-
if (std::move(ExistingOrErr.get())->getBuffer() == OutString)
176-
WriteFile = false;
177-
}
178-
if (WriteFile) {
179-
std::error_code EC;
180-
ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_Text);
181-
if (EC)
182-
return reportError(argv0, "error opening " + OutputFilename + ": " +
183-
EC.message() + "\n");
184-
OutFile.os() << OutString;
185-
if (ErrorsPrinted == 0)
186-
OutFile.keep();
192+
if (int Ret = WriteOutput(Parser, argv0, OutputFilename, OutFiles.MainFile))
193+
return Ret;
194+
for (auto [Suffix, Content] : OutFiles.AdditionalFiles) {
195+
SmallString<128> Filename(OutputFilename);
196+
// TODO: Format using the split-file convention when writing to stdout?
197+
if (Filename != "-") {
198+
Filename = FilenamePrefix;
199+
Filename.append(Suffix);
200+
}
201+
if (int Ret = WriteOutput(Parser, argv0, Filename, Content))
202+
return Ret;
187203
}
188204

189205
Timer.stopTimer();
@@ -193,3 +209,15 @@ int llvm::TableGenMain(const char *argv0,
193209
return reportError(argv0, Twine(ErrorsPrinted) + " errors.\n");
194210
return 0;
195211
}
212+
213+
int llvm::TableGenMain(const char *argv0,
214+
std::function<TableGenMainFn> MainFn) {
215+
return TableGenMain(argv0, [&MainFn](TableGenOutputFiles &OutFiles,
216+
const RecordKeeper &Records) {
217+
std::string S;
218+
raw_string_ostream OS(S);
219+
int Res = MainFn(OS, Records);
220+
OutFiles = {S, {}};
221+
return Res;
222+
});
223+
}

llvm/lib/TableGen/TableGenBackend.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,21 @@ Opt::Opt(StringRef Name, FnT CB, StringRef Desc, bool ByDefault) {
6161
/// Apply callback specified on the command line. Returns true if no callback
6262
/// was applied.
6363
bool llvm::TableGen::Emitter::ApplyCallback(const RecordKeeper &Records,
64-
raw_ostream &OS) {
64+
TableGenOutputFiles &OutFiles,
65+
StringRef FilenamePrefix) {
6566
FnT Fn = CallbackFunction->getValue();
66-
if (!Fn)
67-
return true;
68-
Fn(Records, OS);
69-
return false;
67+
if (Fn.SingleFileGenerator) {
68+
std::string S;
69+
raw_string_ostream OS(S);
70+
Fn.SingleFileGenerator(Records, OS);
71+
OutFiles = {S, {}};
72+
return false;
73+
}
74+
if (Fn.MultiFileGenerator) {
75+
OutFiles = Fn.MultiFileGenerator(FilenamePrefix, Records);
76+
return false;
77+
}
78+
return true;
7079
}
7180

7281
static void printLine(raw_ostream &OS, const Twine &Prefix, char Fill,

llvm/lib/Target/AMDGPU/SIFoldOperands.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,7 @@ void SIFoldOperandsImpl::foldOperand(
13581358
// Remove this if 16-bit SGPRs (i.e. SGPR_LO16) are added to the
13591359
// VS_16RegClass
13601360
//
1361-
// Excerpt from AMDGPUGenRegisterInfo.inc
1361+
// Excerpt from AMDGPUGenRegisterInfoEnums.inc
13621362
// NoSubRegister, //0
13631363
// hi16, // 1
13641364
// lo16, // 2

llvm/test/TableGen/ArtificialSubregs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK
1+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK
22
include "llvm/Target/Target.td"
33

44
// This file tests that when using `isArtificial` for subregisters in

llvm/test/TableGen/ConcatenatedSubregs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s
1+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s
22
// Checks that tablegen correctly and completely infers subregister relations.
33
include "llvm/Target/Target.td"
44

llvm/test/TableGen/HwModeBitSet.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// This is to test the scenario where different HwMode attributes coexist.
2-
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-REG
2+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s --check-prefix=CHECK-REG
33
// RUN: llvm-tblgen -gen-subtarget -I %p/../../include %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-SUBTARGET
44

55

llvm/test/TableGen/HwModeSubRegs.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o /dev/null 2>&1 | FileCheck %s
1+
// RUN: llvm-tblgen -gen-register-info -register-info-debug -I %p/../../include %s -o - 2>&1 >/dev/null | FileCheck %s
22
include "llvm/Target/Target.td"
33

44
def HasFeat : Predicate<"Subtarget->hasFeat()">;

0 commit comments

Comments
 (0)