30#include <system_error>
38lto::DTLTO::BackgroundDeletion::BackgroundDeletion()
41lto::DTLTO::BackgroundDeletion::~BackgroundDeletion() { waitForTasks(); }
43void lto::DTLTO::BackgroundDeletion::waitForTasks() {
45 for (
const std::string &
Warning : Warnings)
46 errs() <<
"warning: could not remove the file " <<
Warning <<
"\n";
50void lto::DTLTO::BackgroundDeletion::removeFiles(
51 std::vector<std::string> &&Files,
const Config &
Conf) {
55 async([
this, Files = std::move(Files), TTE =
Conf.TimeTraceEnabled,
56 TTG =
Conf.TimeTraceGranularity] {
57 if (LLVM_ENABLE_THREADS && TTE)
58 timeTraceProfilerInitialize(TTG,
"Remove DTLTO temporary files");
60 TimeTraceScope TimeScope(
"Remove DTLTO temporary files");
61 for (const std::string &Path : Files) {
62 std::error_code EC = sys::fs::remove(Path, true);
64 EC == std::make_error_code(std::errc::no_such_file_or_directory))
67 Warnings.emplace_back(
"'" + Path +
"': " + EC.message());
70 if (LLVM_ENABLE_THREADS && TTE)
82 BackgroundDeleter.removeFiles(std::move(CleanupList),
Conf);
87Error lto::DTLTO::performThinLink() {
89 SummaryIndexFiles.resize(NumTasks);
90 ImportsFilesList.resize(NumTasks);
91 CacheKeysList.resize(NumTasks);
95 [&](
size_t task) -> std::unique_ptr<raw_svector_ostream> {
96 return std::make_unique<raw_svector_ostream>(SummaryIndexFiles[task]);
99 return CacheKeysList[task];
102 [&](
size_t task) -> std::vector<std::string> & {
103 return ImportsFilesList[task];
112 AddStreamFunc = AddStream;
113 Cache = std::move(CacheParam);
117 if (
Error Err = performThinLink())
120 ThinLTOTaskOffset =
RegularLTO.ParallelCodeGenParallelismLevel;
121 DistributorParams.TargetTriple =
RegularLTO.CombinedModule->getTargetTriple();
123 if (
Error Err = prepareDtltoJobs())
125 if (
Error Err = extractLTOInputs())
127 if (
Error Err = performCodegen())
129 if (
Error Err = addObjectFilesToLink())
135Error lto::DTLTO::checkCacheHit(Job &J) {
136 if (!Cache.isValid())
139 TimeTraceScope TimeScope(
"Check cache for DTLTO", J.SummaryIndexPath);
141 auto CacheAddStreamExp = Cache(J.Task, J.CacheKey, J.ModuleID);
142 if (
Error Err = CacheAddStreamExp.takeError())
147 if (!CacheAddStream) {
149 CachedJobs.fetch_add(1);
154 J.CacheAddStream = std::move(CacheAddStream);
160Error lto::DTLTO::prepareDtltoJob(StringRef ModulePath,
unsigned Task) {
161 assert(Task >= ThinLTOTaskOffset && Task - ThinLTOTaskOffset < Jobs.size() &&
162 "Task index out of range for Jobs");
163 assert(Task < SummaryIndexFiles.size() &&
"Task index out of range");
165 SString ObjFilePath =
168 itostr(Task) +
"." + UID +
".native.o");
170 SString SummaryIndexPathStr = ObjFilePath;
171 SummaryIndexPathStr +=
".thinlto.bc";
172 SString ImportsPathStr = ModulePath;
173 ImportsPathStr +=
".imports";
175 Job &J = Jobs[Task - ThinLTOTaskOffset];
178 Saver.save(ObjFilePath.str()),
179 Saver.save(SummaryIndexPathStr.str()),
180 Saver.save(ImportsPathStr.str()),
181 ImportsFilesList[Task],
186 if (
Error Err = checkCacheHit(J))
189 InputModuleIDsToExtract.insert(J.ModuleID);
190 for (StringRef ImportPath : J.ImportsFilesList)
191 InputModuleIDsToExtract.insert(ImportPath);
193 TimeTraceScope JobScope(
"Emit individual index for DTLTO",
195 if (
Error Err = save(SummaryIndexFiles[Task], J.SummaryIndexPath))
199 OnIndexWriteCb(J.SummaryIndexPath.str());
201 if (ShouldEmitImportFiles)
202 if (
Error Err = save(
join(J.ImportsFilesList,
"\n"), J.ImportsPath))
207 addToCleanup(J.NativeObjectPath.str());
208 if (!ShouldEmitIndexFiles)
209 addToCleanup(J.SummaryIndexPath.str());
210 if (!ShouldEmitImportFiles)
211 addToCleanup(J.ImportsPath.str());
218void lto::DTLTO::buildCommonRemoteCompilerOptions() {
220 auto &
Ops = DistributorParams.CodegenOptions;
222 Ops.push_back(Saver.save(
"-O" + Twine(
C.OptLevel)));
224 if (
C.Options.EmitAddrsig)
225 Ops.push_back(
"-faddrsig");
226 if (
C.Options.FunctionSections)
227 Ops.push_back(
"-ffunction-sections");
228 if (
C.Options.DataSections)
229 Ops.push_back(
"-fdata-sections");
230 if (
C.PTO.LoopInterchange)
231 Ops.push_back(
"-floop-interchange");
235 if (!DistributorParams.TargetTriple.isOSBinFormatCOFF())
236 Ops.push_back(
"-fpic");
240 if (!
C.PGOWarnMismatch) {
241 Ops.push_back(
"-mllvm");
242 Ops.push_back(
"-no-pgo-warn-mismatch");
247 if (!
C.SampleProfile.empty()) {
248 Ops.push_back(Saver.save(
"-fprofile-sample-use=" + Twine(
C.SampleProfile)));
249 DistributorParams.CommonInputs.insert(
C.SampleProfile);
253 Ops.push_back(
"-Wno-unused-command-line-argument");
256 if (!DistributorParams.RemoteCompilerArgs.empty())
257 for (
auto &a : DistributorParams.RemoteCompilerArgs)
262Error lto::DTLTO::prepareDtltoJobs() {
266 InputModuleIDsToExtract.clear();
268 if (ModuleMap.empty())
271 Jobs.resize(ModuleMap.size());
274 if (
Error E = prepareDtltoJob(
Mod.first, ThinLTOTaskOffset +
I))
281Error lto::DTLTO::performCodegen() {
285 buildCommonRemoteCompilerOptions();
287 DistributionDriver Distributor(DistributorParams, Jobs, SaveTemps,
288 [&](StringRef S) { addToCleanup(S); });
290 if (CachedJobs.load() < Jobs.size()) {
291 if (
Error E = Distributor())
298Error lto::DTLTO::addObjectFilesToLink() {
299 TimeTraceScope FilesScope(
"Add DTLTO files to the link");
300 for (
auto &
Job : Jobs) {
307 auto ObjFileMbOrErr =
310 if (std::error_code EC = ObjFileMbOrErr.getError())
316 MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get()->getMemBufferRef();
317 if (Cache.isValid()) {
323 if (!CachedFileStreamOrErr)
325 CachedFileStreamOrErr.takeError(),
327 "Cannot get a cache file stream: %s",
330 auto &CacheStream = *(CachedFileStreamOrErr->get());
331 *(CacheStream.OS) << ObjFileMbRef.
getBuffer();
332 if (
Error Err = CacheStream.commit())
339 if (
Error Err = StreamOrErr.takeError())
341 auto &Stream = *StreamOrErr->get();
343 if (
Error Err = Stream.commit())
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 make_scope_exit function, which executes user-defined cleanup logic at scope ex...
This file defines the SmallString class.
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.
@ C
The default llvm calling convention, compatible with C.
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