LLVM 23.0.0git
DTLTO.h
Go to the documentation of this file.
1//===- DTLTO.h - Integrated Distributed ThinLTO implementation ------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// Declarations for Integrated Distributed ThinLTO, including the DTLTO class
11// and the distribution driver. The implementation focuses on preparing input
12// files for distribution.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef LLVM_DTLTO_DTLTO_H
17#define LLVM_DTLTO_DTLTO_H
18
19#include "llvm/ADT/DenseSet.h"
21#include "llvm/LTO/LTO.h"
24
25#include <functional>
26#include <vector>
27
28namespace llvm {
29namespace lto {
30
31/// Prepares inputs for Distributed ThinLTO so that backend compilations can use
32/// individual bitcode paths and consistent module IDs.
33///
34/// Each input must exist as an individual bitcode file on disk and be loadable
35/// via its ModuleID. Archive members and FatLTO objects do not satisfy that by
36/// default; this class writes bitcode out when needed and updates ModuleID.
37/// On Windows, module IDs are normalized to remove short 8.3 path components
38/// that are machine-local and break distribution; other normalization is left
39/// to DTLTO distributors.
40///
41/// Input files are kept until the pipeline has determined per-module ThinLTO
42/// participation and cache status. addInput() performs: (1) register the
43/// input; (2) on Windows, normalize module ID for standalone bitcode; (3) for
44/// thin archive members, set module ID to the on-disk member path; (4) for
45/// other archives and FatLTO, set module ID to a unique path whose content is
46/// serialized later by serializeLTOInputs().
47class LLVM_ABI DTLTO : public LTO {
48 using Base = LTO;
49
50public:
51 DTLTO(Config Conf, unsigned ParallelCodeGenParallelismLevel, LTOKind LTOMode,
52 IndexWriteCallback OnWrite, bool EmitIndexFiles, bool EmitImportsFiles,
53 StringRef LinkerOutputFile, StringRef Distributor,
54 ArrayRef<StringRef> DistributorArgs, StringRef RemoteCompiler,
55 ArrayRef<StringRef> RemoteCompilerPrependArgs,
56 ArrayRef<StringRef> RemoteCompilerArgs, AddBufferFn AddBufferArg,
57 bool SaveTempsArg)
59 ParallelCodeGenParallelismLevel, LTOMode),
60 AddBuffer(AddBufferArg), SaveTemps(SaveTempsArg),
61 ShouldEmitIndexFiles(EmitIndexFiles),
62 ShouldEmitImportFiles(EmitImportsFiles), OnIndexWriteCb(OnWrite),
63 DistributorParams{Distributor, DistributorArgs,
64 RemoteCompiler, RemoteCompilerPrependArgs,
65 RemoteCompilerArgs, LinkerOutputFile} {
66 assert(!LinkerOutputFile.empty() && "expected a valid linker output file");
68 }
69
70 // Create an instance of WriteIndexesBackend class.
73 "", true, nullptr, nullptr);
74 }
75
76 /// Add an input file and prepare it for distribution.
77 ///
78 /// This function performs the following tasks:
79 /// 1. Add the input file to the LTO object's list of input files.
80 /// 2. For individual bitcode file inputs on Windows only, overwrite the
81 /// module ID with a normalized path to remove short 8.3 form components.
82 /// 3. For thin archive members, overwrite the module ID with the path
83 /// (normalized on Windows) to the member file on disk.
84 /// 4. For archive members and FatLTO objects, overwrite the module ID with a
85 /// unique path (normalized on Windows) naming a file that will contain the
86 /// member content. The file is created and populated later (see
87 /// serializeInputs()).
89 addInput(std::unique_ptr<InputFile> InputPtr) override;
90
91 /// Runs the DTLTO pipeline. This function calls the supplied AddStream
92 /// function to add native object files to the link.
93 ///
94 /// The Cache parameter is optional. If supplied, it will be used to cache
95 /// native object files and add them to the link.
96 ///
97 /// The client will receive at most one callback (via either AddStream or
98 /// Cache) for each task identifier.
99 virtual Error run(AddStreamFn AddStream, FileCache Cache = {}) override;
100
101private:
102 /// DTLTO archive support.
103 ///
104 /// Save the contents of ThinLTO-enabled input files that must be serialized
105 /// for distribution, such as archive members and FatLTO objects, to
106 /// individual bitcode files named after the module ID.
107 ///
108 /// Must be called after all input files are added and cache hits are known,
109 /// but before optimization begins. Existing files are overwritten because
110 /// they are likely leftovers from a previously terminated linker process and
111 /// can be safely replaced.
112 LLVM_ABI Error serializeLTOInputs();
113
114 // Remove temporary files created to enable distribution.
115 void cleanup() override;
116
117public:
118 // Mutable and const accessors to the LTO configuration object.
119 Config &getConfig() { return Conf; }
120 const Config &getConfig() const { return Conf; }
121
122private:
123 // Bump allocator for saving updated module IDs.
124 BumpPtrAllocator PtrAlloc;
125 // String saver backed by PtrAlloc.
126 StringSaver Saver{PtrAlloc};
127
128 using SString = SmallString<128>;
129
130 // Function pointer that defines the callback to add a pre-existing file.
131 AddBufferFn AddBuffer;
132 // Count of jobs that hit the cache.
133 std::atomic<size_t> CachedJobs{0};
134 // Normalized output directory from LinkerOutputFile.
135 SString LinkerOutputDir;
136 // Keep temporary files when true.
137 bool SaveTemps = false;
138
139 // Saves the content of Buffer to Path overwriting any existing file.
140 static Error save(StringRef Buffer, StringRef Path);
141
142public:
143 struct Job {
144 // Task index (combines RegularLTO parallel codegen offset with module
145 // index).
146 unsigned Task;
147 // Module identifier (bitcode path) for the ThinLTO module.
149 // Native object path.
151 // Per-module summary index path.
153 // Per-module imports list path.
155 // Bitcode files from which this module imports.
157 // Cache key from thin link.
158 std::string CacheKey;
159 // On cache miss, stream used to store the compiled object in the cache.
161 // Set when the object was already supplied via the cache callback.
162 bool Cached = false;
163 };
164
165private:
166 // Backend compilation jobs, one per module.
167 SmallVector<Job> Jobs;
168 // Input module IDs that must be serialized to individual files.
169 DenseSet<StringRef> InputModuleIDsToSerialize;
170 // Task index offset for first ThinLTO job.
171 unsigned ThinLTOTaskOffset;
172 // Optional cache for native objects.
173 FileCache Cache;
174 // Keep summary index files when true.
175 bool ShouldEmitIndexFiles = false;
176 // Keep summary import files when true.
177 bool ShouldEmitImportFiles = false;
178 // On index file write callback.
179 IndexWriteCallback OnIndexWriteCb;
180
181 /// Probes the LTO cache for a compiled native object for the given job.
182 ///
183 /// If no cache is configured (Cache.isValid() is false), returns immediately
184 /// without modifying the job.
185 ///
186 /// Otherwise, looks up the cache using J.CacheKey. On a cache hit, the cached
187 /// object has already been passed to the linker via the Cache callback, so
188 /// J.Cached is set to true, CachedJobs is incremented, and the distributor
189 /// can skip this job. On a cache miss, the cache returns an AddStreamFn; we
190 /// store it in J.CacheAddStream for use when storing the freshly compiled
191 /// object after the distributor runs.
192 ///
193 /// \param J The job to check. Must have Task, CacheKey, and ModuleID set.
194 /// On return, J.Cached and J.CacheAddStream may be updated.
195 ///
196 /// \returns Error::success() on success, or an Error from the cache lookup.
197 Error checkCacheHit(Job &J);
198
199 /// Prepares a single DTLTO backend compilation job for a ThinLTO module.
200 ///
201 /// Called once per module during performCodegen(). This function:
202 ///
203 /// 1. Computes output paths for the native object and summary index files.
204 /// Both are placed in the linker output directory with names of the form
205 /// stem.Task.UID.native.o and stem.Task.UID.thinlto.bc, where stem is
206 /// derived from ModulePath.
207 ///
208 /// 2. Initializes the Job struct with Task, ModuleID (ModulePath), paths,
209 /// ImportsFilesList and CacheKey from thin link results, and default
210 /// values for CacheAddStream and Cached.
211 ///
212 /// 3. Calls checkCacheHit() to probe the cache. On a cache hit, J.Cached is
213 /// set and the cached object has already been passed to the linker; the
214 /// distributor will skip this job. On a cache miss, J.CacheAddStream is
215 /// set for later use when storing the compiled object.
216 ///
217 /// 4. Records the module ID and imported module IDs that must be serialized
218 /// to individual files.
219 ///
220 /// 5. Writes the per-module summary index to disk only on cache miss. The
221 /// remote compiler will read this via -fthinlto-index=.
222 ///
223 /// 6. Registers the job's temporary files for removal on abnormal process
224 /// exit when SaveTemps is false (only for files that will be created).
225 ///
226 /// \param ModulePath The module identifier (bitcode path) for the ThinLTO
227 /// module.
228 /// \param Task The task index (combines RegularLTO.ParallelCodeGen
229 /// parallelism offset with the module index).
230 ///
231 /// \returns Error::success() on success, or an Error from saveBuffer() or
232 /// checkCacheHit().
233 Error prepareDtltoJob(StringRef ModulePath, unsigned Task);
234
235 /// Initializes DTLTO state and prepares a job for each ThinLTO module.
236 ///
237 /// Sets task offset, target triple, UID, and Jobs. For each module, calls
238 /// prepareDtltoJob() to assign output paths, check the cache, and write
239 /// summary index shards to disk when needed.
240 ///
241 /// \returns Error::success() on success, or an Error from prepareDtltoJob.
242 Error prepareDtltoJobs();
243
244 /// Runs the DTLTO code generation phase. Must be invoked after thinLink().
245 ///
246 /// Builds Clang options, emits a JSON manifest describing compilation jobs,
247 /// and invokes the distributor to compile ThinLTO modules remotely. Cache
248 /// hits are skipped; the distributor runs only when there are uncached jobs.
249 ///
250 /// \returns Error::success() on success, or an Error on manifest or
251 /// distributor failure.
252 Error performCodegen();
253
254 /// Adds compiled object files to the link for each non-cached job.
255 ///
256 /// Loads each native object from disk, then either writes it to the cache
257 /// (which adds it to the link via the cache callback) or passes it to
258 /// AddStreamFunc directly when caching is disabled.
259 ///
260 /// \returns Error::success() on success, or an Error if a file cannot be read
261 /// or a cache stream cannot be obtained.
262 Error addObjectFilesToLink();
263
264 // Determines if a file at the given path is a thin archive file.
265 //
266 // Uses a cache to avoid repeatedly reading the same file; reads only the
267 // header (magic bytes) to identify the archive type.
268 Expected<bool> isThinArchive(const StringRef ArchivePath);
269
270 // Unique ID for this link (process ID as string).
271 std::string UID;
272
273 // Input files registered for this link (same order as addInput).
274 std::vector<std::shared_ptr<lto::InputFile>> InputFiles;
275 // Cache for isThinArchive() results keyed by archive path.
276 StringMap<bool> ArchiveIsThinCache;
277 // Callback used by run() to add native objects to the link.
278 AddStreamFn AddStreamFunc = nullptr;
279 // Per-task summary index shards from the thin link (in-memory buffers).
280 std::vector<SmallString<0>> SummaryIndexFiles;
281 // Per-task imported bitcode paths from the thin link.
282 std::vector<std::vector<std::string>> ImportsFilesList;
283 // Per-task cache keys for incremental builds from the thin link.
284 std::vector<std::string> CacheKeysList;
285
286 /// Runs the DTLTO thin link phase, producing per-module summary indices,
287 /// import lists, and cache keys for distribution.
288 ///
289 /// This function configures a WriteIndexesThinBackend and invokes the base
290 /// LTO run, which performs the thin link. The thin link resolves cross-module
291 /// references and produces:
292 ///
293 /// - SummaryIndexFiles: per-module summary index shards (in-memory buffers)
294 /// - ImportsFilesList: per-module lists of imported bitcode files
295 /// - CacheKeysList: per-module cache keys for incremental builds
296 /// - ModuleNames: per-module identifiers
297 ///
298 /// The Config callbacks (GetSummaryIndexStreamFunc, GetCacheKeysListRefFunc,
299 /// GetImportsListRefFunc) are installed so the WriteIndexesThinBackend
300 /// populates these arrays. performCodegen() later uses them to prepare
301 /// backend jobs.
302 ///
303 /// \returns Error::success() if the thin link completes, or an Error from
304 /// Base::run().
305 Error performThinLink();
306
307 /// Derive a set of Clang options that will be shared/common for all DTLTO
308 /// backend compilations. We are intentionally minimal here as these options
309 /// must remain synchronized with the behavior of Clang. DTLTO does not
310 /// support all the features available with in-process LTO. More features are
311 /// expected to be added over time. Users can specify Clang options directly
312 /// if a feature is not supported. Note that explicitly specified options that
313 /// imply additional input or output file dependencies must be communicated to
314 /// the distribution system, potentially by setting extra options on the
315 /// distributor program.
316 void buildCommonRemoteCompilerOptions();
317
318public:
319 // Parameters and shared state for DistributorDriver class.
321
324 ArrayRef<StringRef> DistributorArgsArg,
325 StringRef RemoteCompilerArg,
326 ArrayRef<StringRef> RemoteCompilerPrependArgsArg,
327 ArrayRef<StringRef> RemoteCompilerArgsArg,
328 StringRef LinkerOutputFileArg)
329 : LinkerOutputFile(LinkerOutputFileArg),
330 DistributorPath(DistributorArg), DistributorArgs(DistributorArgsArg),
331 RemoteCompiler(RemoteCompilerArg),
332 RemoteCompilerPrependArgs(RemoteCompilerPrependArgsArg),
333 RemoteCompilerArgs(RemoteCompilerArgsArg) {}
334
335 // Output linker file path.
337 // Path to the distributor executable.
339 // Arguments passed to the distributor.
341 // Compiler executabl invoked by the distributor (e.g., Clang).
343 // Options prepended to remote compiler args.
345 // User-supplied options passed to remote compiler.
347
348 // Common Clang options for all compilation jobs.
350 // Input paths shared across compilation jobs.
352 // Target triple for compilations.
354 };
355
356private:
357 // Distributor configuration class instance.
358 DistributionDriverParams DistributorParams;
359
360 // Cleanup files list.
361 std::vector<std::string> CleanupList;
362
363 // Record a file for cleanup and register signal-time removal if requested.
364 void addToCleanup(StringRef Filename) {
365 CleanupList.push_back(Filename.str());
367 }
368};
369
370namespace {
371constexpr StringRef BCError = "DTLTO backend compilation: ";
372}
373
375public:
377 ArrayRef<DTLTO::Job> JobsArg, bool SaveTempsArg,
378 std::function<void(StringRef)> AddToClenupArg)
379 : Params{ParamsArg}, SaveTemps{SaveTempsArg},
380 AddToCleanup{AddToClenupArg}, Jobs{JobsArg} {};
381
382private:
384 // Keep temporary files when true.
385 bool SaveTemps = false;
386 std::function<void(StringRef)> AddToCleanup;
388 SmallString<128> DistributorJsonFile;
389
390 // Generates a JSON file describing the compilations
391 Error emitJson();
392 // Saves JSON file on a filesystem.
393 Error saveJson();
394
395public:
396 /// Invokes the distributor to compile bitcode modules remotely.
397 ///
398 /// Runs the distributor with the
399 /// JSON manifest path; the distributor spawns remote compiler processes.
400 ///
401 /// \returns Error::success() on success, or an Error if the distributor
402 /// fails.
404};
405
406} // namespace lto
407} // namespace llvm
408
409#endif // LLVM_DTLTO_DTLTO_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static void cleanup(BlockFrequencyInfoImplBase &BFI)
Clear all memory not needed downstream.
#define LLVM_ABI
Definition Compiler.h:215
This file defines the DenseSet and SmallDenseSet classes.
static constexpr StringLiteral Filename
This file defines the SmallString class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Implements a dense probed hash-table based set.
Definition DenseSet.h:289
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:128
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer.
Definition StringSaver.h:22
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
const Config & getConfig() const
Definition DTLTO.h:120
Config & getConfig()
Definition DTLTO.h:119
static lto::ThinBackend writeIndexesBackendInstance()
Definition DTLTO.h:71
DTLTO(Config Conf, unsigned ParallelCodeGenParallelismLevel, LTOKind LTOMode, IndexWriteCallback OnWrite, bool EmitIndexFiles, bool EmitImportsFiles, StringRef LinkerOutputFile, StringRef Distributor, ArrayRef< StringRef > DistributorArgs, StringRef RemoteCompiler, ArrayRef< StringRef > RemoteCompilerPrependArgs, ArrayRef< StringRef > RemoteCompilerArgs, AddBufferFn AddBufferArg, bool SaveTempsArg)
Definition DTLTO.h:51
DistributionDriver(DTLTO::DistributionDriverParams &ParamsArg, ArrayRef< DTLTO::Job > JobsArg, bool SaveTempsArg, std::function< void(StringRef)> AddToClenupArg)
Definition DTLTO.h:376
LLVM_ABI Error operator()()
Invokes the distributor to compile bitcode modules remotely.
LTO(Config Conf, ThinBackend Backend={}, unsigned ParallelCodeGenParallelismLevel=1, LTOKind LTOMode=LTOK_Default)
Create an LTO object.
Definition LTO.cpp:688
Config Conf
Definition LTO.h:457
LTOKind
Unified LTO modes.
Definition LTO.h:395
@ LTOK_UnifiedThin
ThinLTO, with Unified LTO enabled.
Definition LTO.h:403
LTOKind LTOMode
Definition LTO.h:618
std::function< void(const std::string &)> IndexWriteCallback
Definition LTO.h:244
LLVM_ABI ThinBackend createWriteIndexesThinBackend(ThreadPoolStrategy Parallelism, std::string OldPrefix, std::string NewPrefix, std::string NativeObjectPrefix, bool ShouldEmitImportsFiles, raw_fd_ostream *LinkedObjectsFile, IndexWriteCallback OnWrite)
This ThinBackend writes individual module indexes to files, instead of running the individual backend...
Definition LTO.cpp:2022
LLVM_ABI bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
This is an optimization pass for GlobalISel generic memory operations.
ThreadPoolStrategy hardware_concurrency(unsigned ThreadCount=0)
Returns a default thread strategy where all available hardware resources are to be used,...
Definition Threading.h:190
std::function< void(unsigned Task, const Twine &ModuleName, std::unique_ptr< MemoryBuffer > MB)> AddBufferFn
This type defines the callback to add a pre-existing file (e.g.
Definition Caching.h:107
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
Definition Allocator.h:390
std::function< Expected< std::unique_ptr< CachedFileStream > >( unsigned Task, const Twine &ModuleName)> AddStreamFn
This type defines the callback to add a file that is generated on the fly.
Definition Caching.h:58
LLVM_ABI Error EmitImportsFiles(StringRef ModulePath, StringRef OutputFilename, const ModuleToSummariesForIndexTy &ModuleToSummariesForIndex)
Emit into OutputFilename the files module ModulePath will import from.
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:860
This type represents a file cache system that manages caching of files.
Definition Caching.h:84
LTO configuration.
Definition Config.h:43
ArrayRef< StringRef > DistributorArgs
Definition DTLTO.h:340
ArrayRef< StringRef > RemoteCompilerArgs
Definition DTLTO.h:346
SmallVector< StringRef, 0 > CodegenOptions
Definition DTLTO.h:349
DistributionDriverParams(StringRef DistributorArg, ArrayRef< StringRef > DistributorArgsArg, StringRef RemoteCompilerArg, ArrayRef< StringRef > RemoteCompilerPrependArgsArg, ArrayRef< StringRef > RemoteCompilerArgsArg, StringRef LinkerOutputFileArg)
Definition DTLTO.h:323
DenseSet< StringRef > CommonInputs
Definition DTLTO.h:351
ArrayRef< StringRef > RemoteCompilerPrependArgs
Definition DTLTO.h:344
StringRef SummaryIndexPath
Definition DTLTO.h:152
AddStreamFn CacheAddStream
Definition DTLTO.h:160
StringRef NativeObjectPath
Definition DTLTO.h:150
StringRef ModuleID
Definition DTLTO.h:148
ArrayRef< std::string > ImportsFilesList
Definition DTLTO.h:156
StringRef ImportsPath
Definition DTLTO.h:154
std::string CacheKey
Definition DTLTO.h:158
This type defines the behavior following the thin-link phase during ThinLTO.
Definition LTO.h:319