@@ -168,6 +168,7 @@ std::string llvm::computeLTOCacheKey(
168
168
AddString (Conf.OverrideTriple );
169
169
AddString (Conf.DefaultTriple );
170
170
AddString (Conf.DwoDir );
171
+ AddUint8 (Conf.Dtlto );
171
172
172
173
// Include the hash for the current module
173
174
auto ModHash = Index.getModuleHash (ModuleID);
@@ -2244,14 +2245,17 @@ class OutOfProcessThinBackend : public CGThinBackend {
2244
2245
2245
2246
SmallVector<StringRef, 0 > CodegenOptions;
2246
2247
DenseSet<StringRef> CommonInputs;
2247
-
2248
+ std::atomic< uint64_t > CachedJobs{ 0 };
2248
2249
// Information specific to individual backend compilation job.
2249
2250
struct Job {
2250
2251
unsigned Task;
2251
2252
StringRef ModuleID;
2252
2253
StringRef NativeObjectPath;
2253
2254
StringRef SummaryIndexPath;
2254
2255
ImportsFilesContainer ImportsFiles;
2256
+ std::string CacheKey;
2257
+ AddStreamFn CacheAddStream;
2258
+ bool Cached = false ;
2255
2259
};
2256
2260
// The set of backend compilations jobs.
2257
2261
SmallVector<Job> Jobs;
@@ -2265,12 +2269,15 @@ class OutOfProcessThinBackend : public CGThinBackend {
2265
2269
// The target triple to supply for backend compilations.
2266
2270
llvm::Triple Triple;
2267
2271
2272
+ // Cache
2273
+ FileCache Cache;
2274
+
2268
2275
public:
2269
2276
OutOfProcessThinBackend (
2270
2277
const Config &Conf, ModuleSummaryIndex &CombinedIndex,
2271
2278
ThreadPoolStrategy ThinLTOParallelism,
2272
2279
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
2273
- AddStreamFn AddStream, lto::IndexWriteCallback OnWrite,
2280
+ AddStreamFn AddStream, FileCache CacheFn, lto::IndexWriteCallback OnWrite,
2274
2281
bool ShouldEmitIndexFiles, bool ShouldEmitImportsFiles,
2275
2282
StringRef LinkerOutputFile, StringRef Distributor,
2276
2283
ArrayRef<StringRef> DistributorArgs, StringRef RemoteCompiler,
@@ -2280,14 +2287,16 @@ class OutOfProcessThinBackend : public CGThinBackend {
2280
2287
ShouldEmitImportsFiles, ThinLTOParallelism),
2281
2288
LinkerOutputFile (LinkerOutputFile), DistributorPath(Distributor),
2282
2289
DistributorArgs(DistributorArgs), RemoteCompiler(RemoteCompiler),
2283
- RemoteCompilerArgs(RemoteCompilerArgs), SaveTemps(SaveTemps) {}
2290
+ RemoteCompilerArgs(RemoteCompilerArgs), SaveTemps(SaveTemps),
2291
+ Cache(std::move(CacheFn)) {}
2284
2292
2285
2293
virtual void setup (unsigned ThinLTONumTasks, unsigned ThinLTOTaskOffset,
2286
2294
llvm::Triple Triple) override {
2287
2295
UID = itostr (sys::Process::getProcessId ());
2288
2296
Jobs.resize ((size_t )ThinLTONumTasks);
2289
2297
this ->ThinLTOTaskOffset = ThinLTOTaskOffset;
2290
2298
this ->Triple = Triple;
2299
+ this ->Conf .Dtlto = 1 ;
2291
2300
}
2292
2301
2293
2302
Error start (
@@ -2304,13 +2313,14 @@ class OutOfProcessThinBackend : public CGThinBackend {
2304
2313
itostr (Task) + " ." + UID + " .native.o" );
2305
2314
2306
2315
Job &J = Jobs[Task - ThinLTOTaskOffset];
2307
- J = {
2308
- Task,
2309
- ModulePath,
2310
- Saver.save (ObjFilePath.str ()),
2311
- Saver.save (ObjFilePath.str () + " .thinlto.bc" ),
2312
- {} // Filled in by emitFiles below.
2313
- };
2316
+ J = {Task,
2317
+ ModulePath,
2318
+ Saver.save (ObjFilePath.str ()),
2319
+ Saver.save (ObjFilePath.str () + " .thinlto.bc" ),
2320
+ {}, // Filled in by emitFiles below.
2321
+ " " ,
2322
+ nullptr ,
2323
+ false };
2314
2324
2315
2325
assert (ModuleToDefinedGVSummaries.count (ModulePath));
2316
2326
@@ -2326,6 +2336,35 @@ class OutOfProcessThinBackend : public CGThinBackend {
2326
2336
else
2327
2337
Err = std::move (E);
2328
2338
}
2339
+
2340
+ if (Cache.isValid () &&
2341
+ CombinedIndex.modulePaths ().count (J.ModuleID ) &&
2342
+ all_of (CombinedIndex.getModuleHash (J.ModuleID ),
2343
+ [](uint32_t V) { return V != 0 ; })) {
2344
+
2345
+ const GVSummaryMapTy &DefinedGlobals =
2346
+ ModuleToDefinedGVSummaries.find (ModulePath)->second ;
2347
+
2348
+ // Compute and store a bitcode module cache key.
2349
+ J.CacheKey = computeLTOCacheKey (
2350
+ Conf, CombinedIndex, ModulePath, ImportList, ExportList,
2351
+ ResolvedODR, DefinedGlobals, CfiFunctionDefs, CfiFunctionDecls);
2352
+
2353
+ // Check if we have something in the cache.
2354
+ auto CacheAddStreamExp = Cache (J.Task , J.CacheKey , J.ModuleID );
2355
+ if (Error E = CacheAddStreamExp.takeError ()) {
2356
+ Err = joinErrors (std::move (*Err), std::move (E));
2357
+ } else {
2358
+ AddStreamFn &CacheAddStream = *CacheAddStreamExp;
2359
+ if (!CacheAddStream) {
2360
+ J.Cached = true ; // Cache hit, mark the job as cached.
2361
+ CachedJobs.fetch_add (1 );
2362
+ } else {
2363
+ // Cache miss, save cache 'add stream' function for a later use.
2364
+ J.CacheAddStream = std::move (CacheAddStream);
2365
+ }
2366
+ }
2367
+ }
2329
2368
},
2330
2369
std::ref (J), std::ref (ImportList));
2331
2370
@@ -2417,6 +2456,9 @@ class OutOfProcessThinBackend : public CGThinBackend {
2417
2456
for (const auto &J : Jobs) {
2418
2457
assert (J.Task != 0 );
2419
2458
2459
+ if (!Cache.getCacheDirectoryPath ().empty () && J.Cached )
2460
+ continue ;
2461
+
2420
2462
SmallVector<StringRef, 2 > Inputs;
2421
2463
SmallVector<StringRef, 1 > Outputs;
2422
2464
@@ -2488,20 +2530,26 @@ class OutOfProcessThinBackend : public CGThinBackend {
2488
2530
removeFile (JsonFile);
2489
2531
});
2490
2532
2491
- SmallVector<StringRef, 3 > Args = {DistributorPath};
2492
- llvm::append_range (Args, DistributorArgs);
2493
- Args.push_back (JsonFile);
2494
- std::string ErrMsg;
2495
- if (sys::ExecuteAndWait (Args[0 ], Args,
2496
- /* Env=*/ std::nullopt , /* Redirects=*/ {},
2497
- /* SecondsToWait=*/ 0 , /* MemoryLimit=*/ 0 , &ErrMsg)) {
2498
- return make_error<StringError>(
2499
- BCError + " distributor execution failed" +
2500
- (!ErrMsg.empty () ? " : " + ErrMsg + Twine (" ." ) : Twine (" ." )),
2501
- inconvertibleErrorCode ());
2533
+ if (CachedJobs.load () < Jobs.size ()) {
2534
+ SmallVector<StringRef, 3 > Args = {DistributorPath};
2535
+ llvm::append_range (Args, DistributorArgs);
2536
+ Args.push_back (JsonFile);
2537
+ std::string ErrMsg;
2538
+ if (sys::ExecuteAndWait (Args[0 ], Args,
2539
+ /* Env=*/ std::nullopt , /* Redirects=*/ {},
2540
+ /* SecondsToWait=*/ 0 , /* MemoryLimit=*/ 0 ,
2541
+ &ErrMsg)) {
2542
+ return make_error<StringError>(
2543
+ BCError + " distributor execution failed" +
2544
+ (!ErrMsg.empty () ? " : " + ErrMsg + Twine (" ." ) : Twine (" ." )),
2545
+ inconvertibleErrorCode ());
2546
+ }
2502
2547
}
2503
2548
2504
2549
for (auto &Job : Jobs) {
2550
+ if (Cache.isValid () && !Job.CacheKey .empty ())
2551
+ if (Job.Cached )
2552
+ continue ;
2505
2553
// Load the native object from a file into a memory buffer
2506
2554
// and store its contents in the output buffer.
2507
2555
auto ObjFileMbOrErr =
@@ -2512,15 +2560,32 @@ class OutOfProcessThinBackend : public CGThinBackend {
2512
2560
BCError + " cannot open native object file: " +
2513
2561
Job.NativeObjectPath + " : " + EC.message (),
2514
2562
inconvertibleErrorCode ());
2515
- auto StreamOrErr = AddStream (Job.Task , Job.ModuleID );
2516
- if (Error Err = StreamOrErr.takeError ())
2517
- report_fatal_error (std::move (Err));
2518
- auto &Stream = *StreamOrErr->get ();
2519
- *Stream.OS << ObjFileMbOrErr->get ()->getMemBufferRef ().getBuffer ();
2520
- if (Error Err = Stream.commit ())
2521
- report_fatal_error (std::move (Err));
2522
- }
2523
2563
2564
+ MemoryBufferRef ObjFileMbRef = ObjFileMbOrErr->get ()->getMemBufferRef ();
2565
+ if (Cache.isValid () && Job.CacheAddStream ) {
2566
+ // Obtain a file stream for a storing a cache entry.
2567
+ auto CachedFileStreamOrErr = Job.CacheAddStream (Job.Task , Job.ModuleID );
2568
+ if (!CachedFileStreamOrErr)
2569
+ return joinErrors (
2570
+ CachedFileStreamOrErr.takeError (),
2571
+ createStringError (inconvertibleErrorCode (),
2572
+ " Cannot get a cache file stream: %s" ,
2573
+ Job.NativeObjectPath .data ()));
2574
+ // Store a file buffer into the cache stream.
2575
+ auto &CacheStream = *(CachedFileStreamOrErr->get ());
2576
+ *(CacheStream.OS ) << ObjFileMbRef.getBuffer ();
2577
+ if (Error Err = CacheStream.commit ())
2578
+ return Err;
2579
+ } else {
2580
+ auto StreamOrErr = AddStream (Job.Task , Job.ModuleID );
2581
+ if (Error Err = StreamOrErr.takeError ())
2582
+ report_fatal_error (std::move (Err));
2583
+ auto &Stream = *StreamOrErr->get ();
2584
+ *Stream.OS << ObjFileMbRef.getBuffer ();
2585
+ if (Error Err = Stream.commit ())
2586
+ report_fatal_error (std::move (Err));
2587
+ }
2588
+ }
2524
2589
return Error::success ();
2525
2590
}
2526
2591
};
@@ -2535,12 +2600,12 @@ ThinBackend lto::createOutOfProcessThinBackend(
2535
2600
auto Func =
2536
2601
[=](const Config &Conf, ModuleSummaryIndex &CombinedIndex,
2537
2602
const DenseMap<StringRef, GVSummaryMapTy> &ModuleToDefinedGVSummaries,
2538
- AddStreamFn AddStream, FileCache /* Cache*/ ) {
2603
+ AddStreamFn AddStream, FileCache Cache) {
2539
2604
return std::make_unique<OutOfProcessThinBackend>(
2540
2605
Conf, CombinedIndex, Parallelism, ModuleToDefinedGVSummaries,
2541
- AddStream, OnWrite, ShouldEmitIndexFiles, ShouldEmitImportsFiles ,
2542
- LinkerOutputFile, Distributor, DistributorArgs, RemoteCompiler ,
2543
- RemoteCompilerArgs, SaveTemps);
2606
+ AddStream, Cache, OnWrite, ShouldEmitIndexFiles ,
2607
+ ShouldEmitImportsFiles, LinkerOutputFile, Distributor ,
2608
+ DistributorArgs, RemoteCompiler, RemoteCompilerArgs, SaveTemps);
2544
2609
};
2545
2610
return ThinBackend (Func, Parallelism);
2546
2611
}
0 commit comments