Skip to content

Commit f0a39e9

Browse files
committed
Add support for collecting various SIL optimizer counters
This patch implements collection and dumping of statistics about SILModules, SILFunctions and memory consumption during the execution of SIL optimization pipelines. The following statistics can be collected: * For SILFunctions: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, duration of a pass * For SILModules: the number of SIL basic blocks, the number of SIL instructions, the number of SIL instructions of a specific kind, the number of SILFunctions, the amount of memory used by the compiler, duration of a pass By default, any collection of statistics is disabled to avoid affecting compile times. One can enable the collection of statistics and dumping of these statistics for the whole SILModule and/or for SILFunctions. To reduce the amount of produced data, one can set thresholds in such a way that changes in the statistics are only reported if the delta between the old and the new values are at least X%. The deltas are computed as using the following formula: Delta = (NewValue - OldValue) / OldValue Thresholds provide a simple way to perform a simple filtering of the collected statistics during the compilation. But if there is a need for a more complex analysis of collected data (e.g. aggregation by a pipeline stage or by the type of a transformation), it is often better to dump as much data as possible into a file using e.g. -sil-stats-dump-all -sil-stats-modules -sil-stats-functions and then e.g. use the helper scripts to store the collected data into a database and then perform complex queries on it. Many kinds of analysis can be then formulated pretty easily as SQL queries.
1 parent 0cebfc3 commit f0a39e9

File tree

8 files changed

+1088
-4
lines changed

8 files changed

+1088
-4
lines changed

include/swift/SIL/SILInstruction.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,21 @@ class SILInstruction : public ValueBase,public llvm::ilist_node<SILInstruction>{
9696
/// SILClonerWithScope instead.
9797
void setDebugScope(SILBuilder &B, const SILDebugScope *DS);
9898

99+
/// Total number of created and deleted SILInstructions.
100+
/// It is used only for collecting the compiler statistics.
101+
static int NumCreatedInstructions;
102+
static int NumDeletedInstructions;
103+
99104
protected:
100105
SILInstruction(ValueKind Kind, SILDebugLocation DebugLoc,
101106
SILType Ty = SILType())
102-
: ValueBase(Kind, Ty), ParentBB(0), Location(DebugLoc) {}
107+
: ValueBase(Kind, Ty), ParentBB(0), Location(DebugLoc) {
108+
NumCreatedInstructions++;
109+
}
110+
111+
~SILInstruction() {
112+
NumDeletedInstructions++;
113+
}
103114

104115
public:
105116
/// Instructions should be allocated using a dedicated instruction allocation
@@ -335,6 +346,16 @@ class SILInstruction : public ValueBase,public llvm::ilist_node<SILInstruction>{
335346
/// Verify that all operands of this instruction have compatible ownership
336347
/// with this instruction.
337348
void verifyOperandOwnership() const;
349+
350+
/// Get the number of created SILInstructions.
351+
static int getNumCreatedInstructions() {
352+
return NumCreatedInstructions;
353+
}
354+
355+
/// Get the number of deleted SILInstructions.
356+
static int getNumDeletedInstructions() {
357+
return NumDeletedInstructions;
358+
}
338359
};
339360

340361
/// Returns the combined behavior of \p B1 and \p B2.

include/swift/SILOptimizer/Analysis/Analysis.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ ANALYSIS(Escape)
3636
ANALYSIS(InductionVariable)
3737
ANALYSIS(Loop)
3838
ANALYSIS(LoopRegion)
39+
ANALYSIS(OptimizerStats)
3940
ANALYSIS(PostDominance)
4041
ANALYSIS(PostOrder)
4142
ANALYSIS(RCIdentity)

include/swift/SILOptimizer/PassManager/PassManager.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,9 +211,16 @@ class SILPassManager {
211211
/// owned by the pass manager. Analysis passes will be kept.
212212
void resetAndRemoveTransformations();
213213

214-
// Sets the name of the current optimization stage used for debugging.
214+
/// \brief Set the name of the current optimization stage.
215+
///
216+
/// This is useful for debugging.
215217
void setStageName(llvm::StringRef NextStage = "");
216218

219+
/// \brief Get the name of the current optimization stage.
220+
///
221+
/// This is useful for debugging.
222+
StringRef getStageName() const;
223+
217224
/// D'tor.
218225
~SILPassManager();
219226

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- OptimizerStatsUtils.h - Utils for collecting stats --*- C++ ---*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_OPTIMIZER_STATS_UTILS_H
14+
#define SWIFT_OPTIMIZER_STATS_UTILS_H
15+
16+
namespace swift {
17+
class SILModule;
18+
class SILTransform;
19+
class SILPassManager;
20+
21+
/// Updates SILModule stats before executing the transform \p Transform.
22+
///
23+
/// \param M SILModule to be processed
24+
/// \param Transform the SIL transformation that was just executed
25+
/// \param PM the PassManager being used
26+
void updateSILModuleStatsBeforeTransform(SILModule &M, SILTransform *Transform,
27+
SILPassManager &PM, int PassNumber);
28+
29+
/// Updates SILModule stats after finishing executing the
30+
/// transform \p Transform.
31+
///
32+
/// \param M SILModule to be processed
33+
/// \param Transform the SIL transformation that was just executed
34+
/// \param PM the PassManager being used
35+
void updateSILModuleStatsAfterTransform(SILModule &M, SILTransform *Transform,
36+
SILPassManager &PM, int PassNumber,
37+
int Duration);
38+
39+
} // end namespace swift
40+
41+
#endif

lib/SIL/SILInstruction.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ void SILInstruction::dropAllReferences() {
168168
}
169169
}
170170

171+
// Initialize the static members of SILInstruction.
172+
int SILInstruction::NumCreatedInstructions = 0;
173+
int SILInstruction::NumDeletedInstructions = 0;
174+
171175
namespace {
172176
class InstructionDestroyer
173177
: public SILInstructionVisitor<InstructionDestroyer> {

lib/SILOptimizer/PassManager/PassManager.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "swift/SILOptimizer/Analysis/FunctionOrder.h"
2121
#include "swift/SILOptimizer/PassManager/PrettyStackTrace.h"
2222
#include "swift/SILOptimizer/PassManager/Transforms.h"
23+
#include "swift/SILOptimizer/Utils/OptimizerStatsUtils.h"
2324
#include "llvm/ADT/DenseMap.h"
2425
#include "llvm/ADT/Statistic.h"
2526
#include "llvm/ADT/StringSwitch.h"
@@ -316,6 +317,8 @@ void SILPassManager::runPassOnFunction(SILFunctionTransform *SFT,
316317
return;
317318
}
318319

320+
updateSILModuleStatsBeforeTransform(F->getModule(), SFT, *this, NumPassesRun);
321+
319322
CurrentPassHasInvalidated = false;
320323

321324
if (SILPrintPassName)
@@ -338,8 +341,8 @@ void SILPassManager::runPassOnFunction(SILFunctionTransform *SFT,
338341
assert(analysesUnlocked() && "Expected all analyses to be unlocked!");
339342
Mod->removeDeleteNotificationHandler(SFT);
340343

344+
auto Delta = (std::chrono::system_clock::now() - StartTime).count();
341345
if (SILPrintPassTime) {
342-
auto Delta = (std::chrono::system_clock::now() - StartTime).count();
343346
llvm::dbgs() << Delta << " (" << SFT->getName() << "," << F->getName()
344347
<< ")\n";
345348
}
@@ -352,6 +355,9 @@ void SILPassManager::runPassOnFunction(SILFunctionTransform *SFT,
352355
F->dump(getOptions().EmitVerboseSIL);
353356
}
354357

358+
updateSILModuleStatsAfterTransform(F->getModule(), SFT, *this, NumPassesRun,
359+
Delta);
360+
355361
// Remember if this pass didn't change anything.
356362
if (!CurrentPassHasInvalidated)
357363
completedPasses.set((size_t)SFT->getPassKind());
@@ -440,6 +446,8 @@ void SILPassManager::runModulePass(SILModuleTransform *SMT) {
440446
SMT->injectPassManager(this);
441447
SMT->injectModule(Mod);
442448

449+
updateSILModuleStatsBeforeTransform(*Mod, SMT, *this, NumPassesRun);
450+
443451
CurrentPassHasInvalidated = false;
444452

445453
if (SILPrintPassName)
@@ -460,8 +468,8 @@ void SILPassManager::runModulePass(SILModuleTransform *SMT) {
460468
Mod->removeDeleteNotificationHandler(SMT);
461469
assert(analysesUnlocked() && "Expected all analyses to be unlocked!");
462470

471+
auto Delta = (std::chrono::system_clock::now() - StartTime).count();
463472
if (SILPrintPassTime) {
464-
auto Delta = (std::chrono::system_clock::now() - StartTime).count();
465473
llvm::dbgs() << Delta << " (" << SMT->getName() << ",Module)\n";
466474
}
467475

@@ -474,6 +482,8 @@ void SILPassManager::runModulePass(SILModuleTransform *SMT) {
474482
printModule(Mod, Options.EmitVerboseSIL);
475483
}
476484

485+
updateSILModuleStatsAfterTransform(*Mod, SMT, *this, NumPassesRun, Delta);
486+
477487
if (Options.VerifyAll &&
478488
(CurrentPassHasInvalidated || !SILVerifyWithoutInvalidation)) {
479489
Mod->verify();
@@ -608,6 +618,10 @@ void SILPassManager::setStageName(llvm::StringRef NextStage) {
608618
StageName = NextStage;
609619
}
610620

621+
StringRef SILPassManager::getStageName() const {
622+
return StageName;
623+
}
624+
611625
const SILOptions &SILPassManager::getOptions() const {
612626
return Mod->getOptions();
613627
}

lib/SILOptimizer/Utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(UTILS_SOURCES
99
Utils/LoadStoreOptUtils.cpp
1010
Utils/Local.cpp
1111
Utils/LoopUtils.cpp
12+
Utils/OptimizerStatsUtils.cpp
1213
Utils/PerformanceInlinerUtils.cpp
1314
Utils/SILInliner.cpp
1415
Utils/SILSSAUpdater.cpp

0 commit comments

Comments
 (0)