41
41
#include " llvm/Support/GraphWriter.h"
42
42
#include " llvm/Support/ManagedStatic.h"
43
43
44
+ #include < fstream>
45
+
44
46
using namespace swift ;
45
47
46
48
llvm::cl::opt<bool > SILPrintAll (
@@ -67,6 +69,20 @@ llvm::cl::opt<std::string> SILNumOptPassesToRun(
67
69
" sil-opt-pass-count" , llvm::cl::init(" " ),
68
70
llvm::cl::desc(" Stop optimizing after <N> passes or <N>.<M> passes/sub-passes" ));
69
71
72
+ // Read pass counts for each module from a config file.
73
+ // Config file format:
74
+ // <module-name>:<pass-count>(.<sub-pass-count>)
75
+ //
76
+ // This is useful for bisecting passes in large projects:
77
+ // 1. create a config file from a full build log. E.g. with
78
+ // grep -e '-module-name' build.log | sed -e 's/.*-module-name \([^ ]*\) .*/\1:10000000/' | sort | uniq > config.txt
79
+ // 2. add the `-Xllvm -sil-pass-count-config-file config.txt` option to the project settings
80
+ // 3. bisect by modifying the counts in the config file
81
+ // 4. clean-rebuild after each bisecting step
82
+ llvm::cl::opt<std::string> SILPassCountConfigFile (
83
+ " sil-pass-count-config-file" , llvm::cl::init(" " ),
84
+ llvm::cl::desc(" Read optimization counts from file" ));
85
+
70
86
llvm::cl::opt<unsigned > SILOptProfileRepeat (
71
87
" sil-opt-profile-repeat" , llvm::cl::init(1 ),
72
88
llvm::cl::desc(" repeat passes N times and report the run time" ));
@@ -382,19 +398,25 @@ SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
382
398
#include " swift/SILOptimizer/Analysis/Analysis.def"
383
399
384
400
if (!SILNumOptPassesToRun.empty ()) {
385
- StringRef countsStr = SILNumOptPassesToRun;
386
- bool validFormat = true ;
387
- if (countsStr.consumeInteger (10 , maxNumPassesToRun))
388
- validFormat = false ;
389
- if (countsStr.startswith (" ." )) {
390
- countsStr = countsStr.drop_front (1 );
391
- if (countsStr.consumeInteger (10 , maxNumSubpassesToRun))
392
- validFormat = false ;
393
- }
394
- if (!validFormat || !countsStr.empty ()) {
395
- llvm::errs () << " error: wrong format of -sil-opt-pass-count option\n " ;
401
+ parsePassCount (SILNumOptPassesToRun);
402
+ } else if (!SILPassCountConfigFile.empty ()) {
403
+ StringRef moduleName = M->getSwiftModule ()->getName ().str ();
404
+ std::fstream fs (SILPassCountConfigFile);
405
+ if (!fs) {
406
+ llvm::errs () << " cannot open pass count config file\n " ;
396
407
exit (1 );
397
408
}
409
+ std::string line;
410
+ while (std::getline (fs, line)) {
411
+ auto pair = StringRef (line).split (" :" );
412
+ StringRef modName = pair.first ;
413
+ StringRef countsStr = pair.second ;
414
+ if (modName == moduleName) {
415
+ parsePassCount (countsStr);
416
+ break ;
417
+ }
418
+ }
419
+ fs.close ();
398
420
}
399
421
400
422
for (SILAnalysis *A : Analyses) {
@@ -407,6 +429,21 @@ SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
407
429
M->registerDeserializationNotificationHandler (std::move (handler));
408
430
}
409
431
432
+ void SILPassManager::parsePassCount (StringRef countsStr) {
433
+ bool validFormat = true ;
434
+ if (countsStr.consumeInteger (10 , maxNumPassesToRun))
435
+ validFormat = false ;
436
+ if (countsStr.startswith (" ." )) {
437
+ countsStr = countsStr.drop_front (1 );
438
+ if (countsStr.consumeInteger (10 , maxNumSubpassesToRun))
439
+ validFormat = false ;
440
+ }
441
+ if (!validFormat || !countsStr.empty ()) {
442
+ llvm::errs () << " error: wrong format of -sil-opt-pass-count option\n " ;
443
+ exit (1 );
444
+ }
445
+ }
446
+
410
447
bool SILPassManager::continueTransforming () {
411
448
if (isMandatory)
412
449
return true ;
0 commit comments