Skip to content

Commit 1b53aae

Browse files
authored
[ThinLTO][NFC] Refactor ThinBackend (#110461)
This is a prep for #90933. - Change `ThinBackend` from a function to a type. - Store the parallelism level in the type, which will be used when creating two-codegen round backends that inherit this value. - `ThinBackendProc` is hoisted to `LTO.h` from `LTO.cpp` to provide its body for `ThinBackend`. However, `emitFiles()` is still implemented separately in `LTO.cpp`, distinct from its parent class.
1 parent 1ad3180 commit 1b53aae

File tree

2 files changed

+116
-81
lines changed

2 files changed

+116
-81
lines changed

llvm/include/llvm/LTO/LTO.h

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "llvm/Support/Caching.h"
2727
#include "llvm/Support/Error.h"
2828
#include "llvm/Support/StringSaver.h"
29+
#include "llvm/Support/ThreadPool.h"
2930
#include "llvm/Support/thread.h"
3031
#include "llvm/Transforms/IPO/FunctionAttrs.h"
3132
#include "llvm/Transforms/IPO/FunctionImport.h"
@@ -105,7 +106,6 @@ void updateMemProfAttributes(Module &Mod, const ModuleSummaryIndex &Index);
105106

106107
class LTO;
107108
struct SymbolResolution;
108-
class ThinBackendProc;
109109

110110
/// An input file. This is a symbol table wrapper that only exposes the
111111
/// information that an LTO client should need in order to do symbol resolution.
@@ -194,14 +194,90 @@ class InputFile {
194194
}
195195
};
196196

197-
/// A ThinBackend defines what happens after the thin-link phase during ThinLTO.
198-
/// The details of this type definition aren't important; clients can only
199-
/// create a ThinBackend using one of the create*ThinBackend() functions below.
200-
using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>(
197+
using IndexWriteCallback = std::function<void(const std::string &)>;
198+
199+
/// This class defines the interface to the ThinLTO backend.
200+
class ThinBackendProc {
201+
protected:
202+
const Config &Conf;
203+
ModuleSummaryIndex &CombinedIndex;
204+
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries;
205+
IndexWriteCallback OnWrite;
206+
bool ShouldEmitImportsFiles;
207+
DefaultThreadPool BackendThreadPool;
208+
std::optional<Error> Err;
209+
std::mutex ErrMu;
210+
211+
public:
212+
ThinBackendProc(
213+
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
214+
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
215+
lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles,
216+
ThreadPoolStrategy ThinLTOParallelism)
217+
: Conf(Conf), CombinedIndex(CombinedIndex),
218+
ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries),
219+
OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles),
220+
BackendThreadPool(ThinLTOParallelism) {}
221+
222+
virtual ~ThinBackendProc() = default;
223+
virtual Error start(
224+
unsigned Task, BitcodeModule BM,
225+
const FunctionImporter::ImportMapTy &ImportList,
226+
const FunctionImporter::ExportSetTy &ExportList,
227+
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
228+
MapVector<StringRef, BitcodeModule> &ModuleMap) = 0;
229+
Error wait() {
230+
BackendThreadPool.wait();
231+
if (Err)
232+
return std::move(*Err);
233+
return Error::success();
234+
}
235+
unsigned getThreadCount() { return BackendThreadPool.getMaxConcurrency(); }
236+
virtual bool isSensitiveToInputOrder() { return false; }
237+
238+
// Write sharded indices and (optionally) imports to disk
239+
Error emitFiles(const FunctionImporter::ImportMapTy &ImportList,
240+
llvm::StringRef ModulePath,
241+
const std::string &NewModulePath) const;
242+
};
243+
244+
/// This callable defines the behavior of a ThinLTO backend after the thin-link
245+
/// phase. It accepts a configuration \p C, a combined module summary index
246+
/// \p CombinedIndex, a map of module identifiers to global variable summaries
247+
/// \p ModuleToDefinedGVSummaries, a function to add output streams \p
248+
/// AddStream, and a file cache \p Cache. It returns a unique pointer to a
249+
/// ThinBackendProc, which can be used to launch backends in parallel.
250+
using ThinBackendFunction = std::function<std::unique_ptr<ThinBackendProc>(
201251
const Config &C, ModuleSummaryIndex &CombinedIndex,
202-
DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
252+
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
203253
AddStreamFn AddStream, FileCache Cache)>;
204254

255+
/// This type defines the behavior following the thin-link phase during ThinLTO.
256+
/// It encapsulates a backend function and a strategy for thread pool
257+
/// parallelism. Clients should use one of the provided create*ThinBackend()
258+
/// functions to instantiate a ThinBackend. Parallelism defines the thread pool
259+
/// strategy to be used for processing.
260+
struct ThinBackend {
261+
ThinBackend(ThinBackendFunction Func, ThreadPoolStrategy Parallelism)
262+
: Func(std::move(Func)), Parallelism(std::move(Parallelism)) {}
263+
ThinBackend() = default;
264+
265+
std::unique_ptr<ThinBackendProc> operator()(
266+
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
267+
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
268+
AddStreamFn AddStream, FileCache Cache) {
269+
assert(isValid() && "Invalid backend function");
270+
return Func(Conf, CombinedIndex, ModuleToDefinedGVSummaries,
271+
std::move(AddStream), std::move(Cache));
272+
}
273+
ThreadPoolStrategy getParallelism() const { return Parallelism; }
274+
bool isValid() const { return static_cast<bool>(Func); }
275+
276+
private:
277+
ThinBackendFunction Func = nullptr;
278+
ThreadPoolStrategy Parallelism;
279+
};
280+
205281
/// This ThinBackend runs the individual backend jobs in-process.
206282
/// The default value means to use one job per hardware core (not hyper-thread).
207283
/// OnWrite is callback which receives module identifier and notifies LTO user
@@ -210,7 +286,6 @@ using ThinBackend = std::function<std::unique_ptr<ThinBackendProc>(
210286
/// to the same path as the input module, with suffix ".thinlto.bc"
211287
/// ShouldEmitImportsFiles is true it also writes a list of imported files to a
212288
/// similar path with ".imports" appended instead.
213-
using IndexWriteCallback = std::function<void(const std::string &)>;
214289
ThinBackend createInProcessThinBackend(ThreadPoolStrategy Parallelism,
215290
IndexWriteCallback OnWrite = nullptr,
216291
bool ShouldEmitIndexFiles = false,
@@ -276,7 +351,7 @@ class LTO {
276351
/// this constructor.
277352
/// FIXME: We do currently require the DiagHandler field to be set in Conf.
278353
/// Until that is fixed, a Config argument is required.
279-
LTO(Config Conf, ThinBackend Backend = nullptr,
354+
LTO(Config Conf, ThinBackend Backend = {},
280355
unsigned ParallelCodeGenParallelismLevel = 1,
281356
LTOKind LTOMode = LTOK_Default);
282357
~LTO();

llvm/lib/LTO/LTO.cpp

Lines changed: 33 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -578,10 +578,10 @@ LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
578578
CombinedModule->IsNewDbgInfoFormat = UseNewDbgInfoFormat;
579579
}
580580

581-
LTO::ThinLTOState::ThinLTOState(ThinBackend Backend)
582-
: Backend(Backend), CombinedIndex(/*HaveGVs*/ false) {
583-
if (!Backend)
584-
this->Backend =
581+
LTO::ThinLTOState::ThinLTOState(ThinBackend BackendParam)
582+
: Backend(std::move(BackendParam)), CombinedIndex(/*HaveGVs*/ false) {
583+
if (!Backend.isValid())
584+
Backend =
585585
createInProcessThinBackend(llvm::heavyweight_hardware_concurrency());
586586
}
587587

@@ -1368,75 +1368,33 @@ SmallVector<const char *> LTO::getRuntimeLibcallSymbols(const Triple &TT) {
13681368
return LibcallSymbols;
13691369
}
13701370

1371-
/// This class defines the interface to the ThinLTO backend.
1372-
class lto::ThinBackendProc {
1373-
protected:
1374-
const Config &Conf;
1375-
ModuleSummaryIndex &CombinedIndex;
1376-
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries;
1377-
lto::IndexWriteCallback OnWrite;
1378-
bool ShouldEmitImportsFiles;
1379-
DefaultThreadPool BackendThreadPool;
1380-
std::optional<Error> Err;
1381-
std::mutex ErrMu;
1371+
Error ThinBackendProc::emitFiles(
1372+
const FunctionImporter::ImportMapTy &ImportList, llvm::StringRef ModulePath,
1373+
const std::string &NewModulePath) const {
1374+
ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
1375+
GVSummaryPtrSet DeclarationSummaries;
13821376

1383-
public:
1384-
ThinBackendProc(
1385-
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
1386-
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
1387-
lto::IndexWriteCallback OnWrite, bool ShouldEmitImportsFiles,
1388-
ThreadPoolStrategy ThinLTOParallelism)
1389-
: Conf(Conf), CombinedIndex(CombinedIndex),
1390-
ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries),
1391-
OnWrite(OnWrite), ShouldEmitImportsFiles(ShouldEmitImportsFiles),
1392-
BackendThreadPool(ThinLTOParallelism) {}
1393-
1394-
virtual ~ThinBackendProc() = default;
1395-
virtual Error start(
1396-
unsigned Task, BitcodeModule BM,
1397-
const FunctionImporter::ImportMapTy &ImportList,
1398-
const FunctionImporter::ExportSetTy &ExportList,
1399-
const std::map<GlobalValue::GUID, GlobalValue::LinkageTypes> &ResolvedODR,
1400-
MapVector<StringRef, BitcodeModule> &ModuleMap) = 0;
1401-
Error wait() {
1402-
BackendThreadPool.wait();
1403-
if (Err)
1404-
return std::move(*Err);
1405-
return Error::success();
1406-
}
1407-
unsigned getThreadCount() { return BackendThreadPool.getMaxConcurrency(); }
1408-
virtual bool isSensitiveToInputOrder() { return false; }
1409-
1410-
// Write sharded indices and (optionally) imports to disk
1411-
Error emitFiles(const FunctionImporter::ImportMapTy &ImportList,
1412-
llvm::StringRef ModulePath,
1413-
const std::string &NewModulePath) const {
1414-
ModuleToSummariesForIndexTy ModuleToSummariesForIndex;
1415-
GVSummaryPtrSet DeclarationSummaries;
1416-
1417-
std::error_code EC;
1418-
gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
1419-
ImportList, ModuleToSummariesForIndex,
1420-
DeclarationSummaries);
1421-
1422-
raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
1423-
sys::fs::OpenFlags::OF_None);
1424-
if (EC)
1425-
return createFileError("cannot open " + NewModulePath + ".thinlto.bc",
1426-
EC);
1427-
1428-
writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex,
1429-
&DeclarationSummaries);
1430-
1431-
if (ShouldEmitImportsFiles) {
1432-
Error ImportFilesError = EmitImportsFiles(
1433-
ModulePath, NewModulePath + ".imports", ModuleToSummariesForIndex);
1434-
if (ImportFilesError)
1435-
return ImportFilesError;
1436-
}
1437-
return Error::success();
1377+
std::error_code EC;
1378+
gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
1379+
ImportList, ModuleToSummariesForIndex,
1380+
DeclarationSummaries);
1381+
1382+
raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
1383+
sys::fs::OpenFlags::OF_None);
1384+
if (EC)
1385+
return createFileError("cannot open " + NewModulePath + ".thinlto.bc", EC);
1386+
1387+
writeIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex,
1388+
&DeclarationSummaries);
1389+
1390+
if (ShouldEmitImportsFiles) {
1391+
Error ImportFilesError = EmitImportsFiles(
1392+
ModulePath, NewModulePath + ".imports", ModuleToSummariesForIndex);
1393+
if (ImportFilesError)
1394+
return ImportFilesError;
14381395
}
1439-
};
1396+
return Error::success();
1397+
}
14401398

14411399
namespace {
14421400
class InProcessThinBackend : public ThinBackendProc {
@@ -1561,7 +1519,7 @@ ThinBackend lto::createInProcessThinBackend(ThreadPoolStrategy Parallelism,
15611519
lto::IndexWriteCallback OnWrite,
15621520
bool ShouldEmitIndexFiles,
15631521
bool ShouldEmitImportsFiles) {
1564-
return
1522+
auto Func =
15651523
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
15661524
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
15671525
AddStreamFn AddStream, FileCache Cache) {
@@ -1570,6 +1528,7 @@ ThinBackend lto::createInProcessThinBackend(ThreadPoolStrategy Parallelism,
15701528
AddStream, Cache, OnWrite, ShouldEmitIndexFiles,
15711529
ShouldEmitImportsFiles);
15721530
};
1531+
return ThinBackend(Func, Parallelism);
15731532
}
15741533

15751534
StringLiteral lto::getThinLTODefaultCPU(const Triple &TheTriple) {
@@ -1681,7 +1640,7 @@ ThinBackend lto::createWriteIndexesThinBackend(
16811640
std::string NewPrefix, std::string NativeObjectPrefix,
16821641
bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile,
16831642
IndexWriteCallback OnWrite) {
1684-
return
1643+
auto Func =
16851644
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
16861645
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
16871646
AddStreamFn AddStream, FileCache Cache) {
@@ -1690,6 +1649,7 @@ ThinBackend lto::createWriteIndexesThinBackend(
16901649
OldPrefix, NewPrefix, NativeObjectPrefix, ShouldEmitImportsFiles,
16911650
LinkedObjectsFile, OnWrite);
16921651
};
1652+
return ThinBackend(Func, Parallelism);
16931653
}
16941654

16951655
Error LTO::runThinLTO(AddStreamFn AddStream, FileCache Cache,

0 commit comments

Comments
 (0)