Skip to content

Commit 81d77a6

Browse files
authored
Merge pull request #70786 from eeckstein/passcount-config-file
PassManager: add the `-sil-pass-count-config-file` for easier bisecting pass counts in large projects
2 parents 73182be + 4aa51ff commit 81d77a6

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ class SILPassManager {
418418
static bool disablePassesForFunction(SILFunction *function);
419419

420420
private:
421+
void parsePassCount(StringRef countsStr);
422+
421423
bool doPrintBefore(SILTransform *T, SILFunction *F);
422424

423425
bool doPrintAfter(SILTransform *T, SILFunction *F, bool PassChangedSIL);

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#include "llvm/Support/GraphWriter.h"
4242
#include "llvm/Support/ManagedStatic.h"
4343

44+
#include <fstream>
45+
4446
using namespace swift;
4547

4648
llvm::cl::opt<bool> SILPrintAll(
@@ -67,6 +69,20 @@ llvm::cl::opt<std::string> SILNumOptPassesToRun(
6769
"sil-opt-pass-count", llvm::cl::init(""),
6870
llvm::cl::desc("Stop optimizing after <N> passes or <N>.<M> passes/sub-passes"));
6971

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+
7086
llvm::cl::opt<unsigned> SILOptProfileRepeat(
7187
"sil-opt-profile-repeat", llvm::cl::init(1),
7288
llvm::cl::desc("repeat passes N times and report the run time"));
@@ -382,19 +398,25 @@ SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
382398
#include "swift/SILOptimizer/Analysis/Analysis.def"
383399

384400
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";
396407
exit(1);
397408
}
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();
398420
}
399421

400422
for (SILAnalysis *A : Analyses) {
@@ -407,6 +429,21 @@ SILPassManager::SILPassManager(SILModule *M, bool isMandatory,
407429
M->registerDeserializationNotificationHandler(std::move(handler));
408430
}
409431

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+
410447
bool SILPassManager::continueTransforming() {
411448
if (isMandatory)
412449
return true;

0 commit comments

Comments
 (0)