29#include <system_error>
37lto::DTLTO::BackgroundDeletion::BackgroundDeletion()
40lto::DTLTO::BackgroundDeletion::~BackgroundDeletion() { waitForTasks(); }
42void lto::DTLTO::BackgroundDeletion::waitForTasks() {
44 for (
const std::string &
Warning : Warnings)
45 errs() <<
"warning: could not remove the file " <<
Warning <<
"\n";
49void lto::DTLTO::BackgroundDeletion::removeFiles(
50 std::vector<std::string> &&Files,
const Config &
Conf) {
54 async([
this, Files = std::move(Files), TTE =
Conf.TimeTraceEnabled,
55 TTG =
Conf.TimeTraceGranularity] {
56 if (LLVM_ENABLE_THREADS && TTE)
57 timeTraceProfilerInitialize(TTG,
"Remove DTLTO temporary files");
59 TimeTraceScope TimeScope(
"Remove DTLTO temporary files");
60 for (const std::string &Path : Files) {
61 std::error_code EC = sys::fs::remove(Path, true);
63 EC == std::make_error_code(std::errc::no_such_file_or_directory))
66 Warnings.emplace_back(
"'" + Path +
"': " + EC.message());
69 if (LLVM_ENABLE_THREADS && TTE)
81 BackgroundDeleter.removeFiles(std::move(CleanupList),
Conf);
86Error lto::DTLTO::performThinLink() {
88 SummaryIndexFiles.resize(NumTasks);
89 ImportsFilesList.resize(NumTasks);
90 CacheKeysList.resize(NumTasks);
94 [&](
size_t task) -> std::unique_ptr<raw_svector_ostream> {
95 return std::make_unique<raw_svector_ostream>(SummaryIndexFiles[task]);
98 return CacheKeysList[task];
101 [&](
size_t task) -> std::vector<std::string> & {
102 return ImportsFilesList[task];
111 AddStreamFunc = AddStream;
112 Cache = std::move(CacheParam);
116 if (
Error Err = performThinLink())
119 ThinLTOTaskOffset =
RegularLTO.ParallelCodeGenParallelismLevel;
120 DistributorParams.TargetTriple =
RegularLTO.CombinedModule->getTargetTriple();
122 if (
Error Err = prepareDtltoJobs())
124 if (
Error Err = extractLTOInputs())
126 if (
Error Err = performCodegen())
128 if (
Error Err = addObjectFilesToLink())
134Error lto::DTLTO::checkCacheHit(Job &J) {
135 if (!Cache.isValid())
138 TimeTraceScope TimeScope(
"Check cache for DTLTO", J.SummaryIndexPath);
140 auto CacheAddStreamExp = Cache(J.Task, J.CacheKey, J.ModuleID);
141 if (
Error Err = CacheAddStreamExp.takeError())
146 if (!CacheAddStream) {
148 CachedJobs.fetch_add(1);
153 J.CacheAddStream = std::move(CacheAddStream);
159Error lto::DTLTO::prepareDtltoJob(StringRef ModulePath,
unsigned Task) {
160 assert(Task >= ThinLTOTaskOffset && Task - ThinLTOTaskOffset < Jobs.size() &&
161 "Task index out of range for Jobs");
162 assert(Task < SummaryIndexFiles.size() &&
"Task index out of range");
164 SString ObjFilePath =
167 itostr(Task) +
"." + UID +
".native.o");
169 SString SummaryIndexPathStr = ObjFilePath;
170 SummaryIndexPathStr +=
".thinlto.bc";
171 SString ImportsPathStr = ModulePath;
172 ImportsPathStr +=
".imports";
174 Job &J = Jobs[Task - ThinLTOTaskOffset];
177 Saver.save(ObjFilePath.str()),
178 Saver.save(SummaryIndexPathStr.str()),
179 Saver.save(ImportsPathStr.str()),
180 ImportsFilesList[Task],
185 if (
Error Err = checkCacheHit(J))
188 InputModuleIDsToExtract.insert(J.ModuleID);
189 for (StringRef ImportPath : J.ImportsFilesList)
190 InputModuleIDsToExtract.insert(ImportPath);
192 TimeTraceScope JobScope(
"Emit individual index for DTLTO",
194 if (
Error Err = save(SummaryIndexFiles[Task], J.SummaryIndexPath))
198 OnIndexWriteCb(J.SummaryIndexPath.str());
200 if (ShouldEmitImportFiles)
201 if (
Error Err = save(
join(J.ImportsFilesList,
"\n"), J.ImportsPath))
206 addToCleanup(J.NativeObjectPath.str());
207 if (!ShouldEmitIndexFiles)
208 addToCleanup(J.SummaryIndexPath.str());
209 if (!ShouldEmitImportFiles)
210 addToCleanup(J.ImportsPath.str());
217void lto::DTLTO::buildCommonRemoteCompilerOptions() {
219 auto &
Ops = DistributorParams.CodegenOptions;
221 Ops.push_back(Saver.save(
"-O" + Twine(
C.OptLevel)));
223 if (
C.Options.EmitAddrsig)
224 Ops.push_back(
"-faddrsig");
225 if (
C.Options.FunctionSections)
226 Ops.push_back(
"-ffunction-sections");
227 if (
C.Options.DataSections)
228 Ops.push_back(
"-fdata-sections");
229 if (
C.PTO.LoopInterchange)
230 Ops.push_back(
"-floop-interchange");
234 if (!DistributorParams.TargetTriple.isOSBinFormatCOFF())
235 Ops.push_back(
"-fpic");
239 if (!
C.PGOWarnMismatch) {
240 Ops.push_back(
"-mllvm");
241 Ops.push_back(
"-no-pgo-warn-mismatch");
246 if (!
C.SampleProfile.empty()) {
247 Ops.push_back(Saver.save(
"-fprofile-sample-use=" + Twine(
C.SampleProfile)));
248 DistributorParams.CommonInputs.insert(
C.SampleProfile);
252 Ops.push_back(
"-Wno-unused-command-line-argument");
255 if (!DistributorParams.RemoteCompilerArgs.empty())
256 for (
auto &a : DistributorParams.RemoteCompilerArgs)
261Error lto::DTLTO::prepareDtltoJobs() {
265 InputModuleIDsToExtract.clear();
267 if (ModuleMap.empty())
270 Jobs.resize(ModuleMap.size());
273 if (
Error E = prepareDtltoJob(
Mod.first, ThinLTOTaskOffset +
I))
280Error lto::DTLTO::performCodegen() {
284 buildCommonRemoteCompilerOptions();
286 DistributionDriver Distributor(DistributorParams, Jobs, SaveTemps,
287 [&](StringRef S) { addToCleanup(S); });
289 if (CachedJobs.load() < Jobs.size()) {
290 if (
Error E = Distributor())
297Error lto::DTLTO::addObjectFilesToLink() {
298 TimeTraceScope FilesScope(
"Add DTLTO files to the link");
299 for (
auto &
Job : Jobs) {
306 auto ObjFileMbOrErr =
309 if (std::error_code EC = ObjFileMbOrErr.getError())
315 MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get()->getMemBufferRef();
316 if (Cache.isValid()) {
322 if (!CachedFileStreamOrErr)
324 CachedFileStreamOrErr.takeError(),
326 "Cannot get a cache file stream: %s",
329 auto &CacheStream = *(CachedFileStreamOrErr->get());
330 *(CacheStream.OS) << ObjFileMbRef.
getBuffer();
331 if (
Error Err = CacheStream.commit())
338 if (
Error Err = StreamOrErr.takeError())
340 auto &Stream = *StreamOrErr->get();
342 if (
Error Err = Stream.commit())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
Provides a library for accessing information about this process and other processes on the operating ...
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
StringRef getBuffer() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
constexpr const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
virtual Error run(AddStreamFn AddStream, FileCache Cache={}) override
Runs the DTLTO pipeline.
void waitForCleanup() override
Wait for LTO cleanup.
struct llvm::lto::LTO::RegularLTOState RegularLTO
struct llvm::lto::LTO::ThinLTOState ThinLTO
unsigned getMaxTasks() const
Returns an upper bound on the number of tasks that the client may expect.
virtual Error run(AddStreamFn AddStream, FileCache Cache={})
Runs the LTO pipeline.
static LLVM_ABI Pid getProcessId()
Get the process's identifier.
LLVM_ABI StringRef stem(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get stem.
LLVM_ABI StringRef parent_path(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get parent path.
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
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,...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI void timeTraceProfilerFinishThread()
Finish a time trace profiler running on a worker thread.
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Mod
The access may modify the value stored in memory.
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
SingleThreadExecutor DefaultThreadPool
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.
std::string itostr(int64_t X)
This type represents a file cache system that manages caching of files.
std::function< std::string &(size_t Task)> GetCacheKeyOutputString
Called by WriteIndexesThinBackend when it needs to store a bitcode module's cache key.
std::function< std::vector< std::string > &(size_t Task)> GetImportsListOutputArray
Called by WriteIndexesThinBackend when it needs to store a bitcode module's imports list.
std::function< std::unique_ptr< raw_pwrite_stream >(size_t Task)> GetSummaryIndexOutputStream
Called by WriteIndexesThinBackend when it needs to write a bitcode module's summary index.
AddStreamFn CacheAddStream
StringRef NativeObjectPath