68
68
#include " llvm/Support/CommandLine.h"
69
69
#include " llvm/Support/FileSystem.h"
70
70
#include " llvm/Support/Process.h"
71
- #include " swift/SIL/SILValue.h"
71
+ #include " swift/Basic/SourceManager.h"
72
+ #include " swift/SIL/DebugUtils.h"
72
73
#include " swift/SIL/SILVisitor.h"
73
74
#include " swift/SILOptimizer/Analysis/Analysis.h"
74
75
#include " swift/SILOptimizer/PassManager/PassManager.h"
@@ -186,6 +187,11 @@ llvm::cl::opt<bool> SILStatsFunctions(
186
187
" sil-stats-functions" , llvm::cl::init(false ),
187
188
llvm::cl::desc(" Enable computation of statistics for SIL functions" ));
188
189
190
+ // / Dump statistics about lost debug variables.
191
+ llvm::cl::opt<bool > SILStatsLostVariables (
192
+ " sil-stats-lost-variables" , llvm::cl::init(false ),
193
+ llvm::cl::desc(" Dump lost debug variables stats" ));
194
+
189
195
// / The name of the output file for optimizer counters.
190
196
llvm::cl::opt<std::string> SILStatsOutputFile (
191
197
" sil-stats-output-file" , llvm::cl::init(" " ),
@@ -272,16 +278,28 @@ struct FunctionStat {
272
278
// / Instruction counts per SILInstruction kind.
273
279
InstructionCounts InstCounts;
274
280
281
+ using VarID = std::tuple<const SILDebugScope *, llvm::StringRef,
282
+ unsigned , unsigned >;
283
+ llvm::StringSet<> VarNames;
284
+ llvm::DenseSet<FunctionStat::VarID> DebugVariables;
285
+
275
286
FunctionStat (SILFunction *F);
276
287
FunctionStat () {}
277
288
289
+ // The DebugVariables set contains pointers to VarNames. Disallow copy.
290
+ FunctionStat (const FunctionStat &) = delete ;
291
+ FunctionStat (FunctionStat &&) = default ;
292
+ FunctionStat &operator =(const FunctionStat &) = delete ;
293
+ FunctionStat &operator =(FunctionStat &&) = default ;
294
+
278
295
void print (llvm::raw_ostream &stream) const {
279
296
stream << " FunctionStat("
280
297
<< " blocks = " << BlockCount << " , Inst = " << InstCount << " )\n " ;
281
298
}
282
299
283
300
bool operator ==(const FunctionStat &rhs) const {
284
- return BlockCount == rhs.BlockCount && InstCount == rhs.InstCount ;
301
+ return BlockCount == rhs.BlockCount && InstCount == rhs.InstCount
302
+ && DebugVariables == rhs.DebugVariables ;
285
303
}
286
304
287
305
bool operator !=(const FunctionStat &rhs) const { return !(*this == rhs); }
@@ -360,14 +378,20 @@ struct ModuleStat {
360
378
bool operator !=(const ModuleStat &rhs) const { return !(*this == rhs); }
361
379
};
362
380
363
- // A helper type to collect the stats about the number of instructions and basic
364
- // blocks .
381
+ // / A helper type to collect the stats about a function ( instructions, blocks,
382
+ // / debug variables) .
365
383
struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
366
384
int BlockCount = 0 ;
367
385
int InstCount = 0 ;
368
386
InstructionCounts &InstCounts;
369
387
370
- InstCountVisitor (InstructionCounts &InstCounts) : InstCounts(InstCounts) {}
388
+ llvm::StringSet<> &VarNames;
389
+ llvm::DenseSet<FunctionStat::VarID> &DebugVariables;
390
+
391
+ InstCountVisitor (InstructionCounts &InstCounts,
392
+ llvm::StringSet<> &VarNames,
393
+ llvm::DenseSet<FunctionStat::VarID> &DebugVariables)
394
+ : InstCounts(InstCounts), VarNames(VarNames), DebugVariables(DebugVariables) {}
371
395
372
396
int getBlockCount () const {
373
397
return BlockCount;
@@ -385,6 +409,29 @@ struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
385
409
void visit (SILInstruction *I) {
386
410
++InstCount;
387
411
++InstCounts[I->getKind ()];
412
+
413
+ if (!SILStatsLostVariables)
414
+ return ;
415
+ // Check the debug variable.
416
+ DebugVarCarryingInst inst (I);
417
+ if (!inst)
418
+ return ;
419
+ std::optional<SILDebugVariable> varInfo = inst.getVarInfo ();
420
+ if (!varInfo)
421
+ return ;
422
+
423
+ llvm::StringRef UniqueName = VarNames.insert (varInfo->Name ).first ->getKey ();
424
+ if (!varInfo->Loc )
425
+ varInfo->Loc = inst->getLoc ();
426
+ unsigned line = 0 , col = 0 ;
427
+ if (varInfo->Loc && varInfo->Loc ->getSourceLoc ().isValid ()) {
428
+ std::tie (line, col) = inst->getModule ().getSourceManager ()
429
+ .getPresumedLineAndColumnForLoc (varInfo->Loc ->getSourceLoc (), 0 );
430
+ }
431
+ FunctionStat::VarID key (
432
+ varInfo->Scope ? varInfo->Scope : inst->getDebugScope (),
433
+ UniqueName, line, col);
434
+ DebugVariables.insert (key);
388
435
}
389
436
};
390
437
@@ -549,7 +596,7 @@ class NewLineInserter {
549
596
std::unique_ptr<llvm::raw_ostream, void (*)(llvm::raw_ostream *)>
550
597
stats_output_stream = {nullptr , nullptr };
551
598
552
- // / Return the output streamm to be used for logging the collected statistics.
599
+ // / Return the output stream to be used for logging the collected statistics.
553
600
llvm::raw_ostream &stats_os () {
554
601
// Initialize the stream if it is not initialized yet.
555
602
if (!stats_output_stream) {
@@ -664,6 +711,18 @@ bool isFirstTimeData(int Old, int New) {
664
711
return Old == 0 && New != Old;
665
712
}
666
713
714
+ int computeLostVariables (llvm::DenseSet<FunctionStat::VarID> &Old,
715
+ llvm::DenseSet<FunctionStat::VarID> &New) {
716
+ unsigned count = 0 ;
717
+ for (auto &var : Old) {
718
+ if (New.contains (var))
719
+ continue ;
720
+ // llvm::dbgs() << "Lost variable: " << std::get<1>(var) << "\n";
721
+ count++;
722
+ }
723
+ return count;
724
+ }
725
+
667
726
// / Dump statistics for a SILFunction. It is only used if a user asked to
668
727
// / produce detailed stats about transformations of SILFunctions. This
669
728
// / information is dumped unconditionally, for each transformation that changed
@@ -710,7 +769,7 @@ void processFuncStatsChanges(SILFunction *F, FunctionStat &OldStat,
710
769
TransformationContext &Ctx) {
711
770
processFuncStatHistory (F, NewStat, Ctx);
712
771
713
- if (!SILStatsFunctions && !SILStatsDumpAll)
772
+ if (!SILStatsFunctions && !SILStatsLostVariables && ! SILStatsDumpAll)
714
773
return ;
715
774
716
775
if (OldStat == NewStat)
@@ -724,6 +783,8 @@ void processFuncStatsChanges(SILFunction *F, FunctionStat &OldStat,
724
783
// Compute deltas.
725
784
double DeltaBlockCount = computeDelta (OldStat.BlockCount , NewStat.BlockCount );
726
785
double DeltaInstCount = computeDelta (OldStat.InstCount , NewStat.InstCount );
786
+ int LostVariables = computeLostVariables (OldStat.DebugVariables ,
787
+ NewStat.DebugVariables );
727
788
728
789
NewLineInserter nl;
729
790
@@ -744,6 +805,11 @@ void processFuncStatsChanges(SILFunction *F, FunctionStat &OldStat,
744
805
printCounterChange (" function" , " inst" , DeltaInstCount, OldStat.InstCount ,
745
806
NewStat.InstCount , Ctx, F->getName ());
746
807
}
808
+
809
+ if ((SILStatsDumpAll || SILStatsLostVariables) && LostVariables) {
810
+ stats_os () << nl.get ();
811
+ printCounterValue (" function" , " lostvars" , LostVariables, F->getName (), Ctx);
812
+ }
747
813
}
748
814
749
815
// / Process SILModule's statistics changes.
@@ -867,10 +933,10 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
867
933
auto &FuncStat = getFunctionStat (&F);
868
934
FunctionStat NewFuncStat (&F);
869
935
processFuncStatHistory (&F, NewFuncStat, Ctx);
870
- // Update function stats.
871
- FuncStat = NewFuncStat;
872
936
// Update module stats.
873
937
NewModStat.addFunctionStat (NewFuncStat);
938
+ // Update function stats.
939
+ FuncStat = std::move (NewFuncStat);
874
940
}
875
941
} else {
876
942
// Go only over functions that were changed since the last computation.
@@ -893,20 +959,20 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
893
959
auto *F = InvalidatedFuncs.back ();
894
960
InvalidatedFuncs.pop_back ();
895
961
auto &FuncStat = getFunctionStat (F);
896
- auto OldFuncStat = FuncStat;
962
+ auto & OldFuncStat = FuncStat;
897
963
FunctionStat NewFuncStat (F);
898
964
processFuncStatsChanges (F, OldFuncStat, NewFuncStat, Ctx);
899
965
NewModStat.subFunctionStat (OldFuncStat);
900
966
NewModStat.addFunctionStat (NewFuncStat);
901
- FuncStat = NewFuncStat;
967
+ FuncStat = std::move ( NewFuncStat) ;
902
968
}
903
969
904
970
// Process deleted functions.
905
971
while (!DeletedFuncs.empty ()) {
906
972
auto *F = DeletedFuncs.back ();
907
973
DeletedFuncs.pop_back ();
908
974
auto &FuncStat = getFunctionStat (F);
909
- auto OldFuncStat = FuncStat;
975
+ auto & OldFuncStat = FuncStat;
910
976
FunctionStat NewFuncStat;
911
977
processFuncStatsChanges (F, OldFuncStat, NewFuncStat, Ctx);
912
978
NewModStat.subFunctionStat (OldFuncStat);
@@ -922,7 +988,7 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
922
988
FunctionStat NewFuncStat (F);
923
989
processFuncStatsChanges (F, OldFuncStat, NewFuncStat, Ctx);
924
990
NewModStat.addFunctionStat (NewFuncStat);
925
- FuncStat = NewFuncStat;
991
+ FuncStat = std::move ( NewFuncStat) ;
926
992
}
927
993
}
928
994
@@ -939,7 +1005,7 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
939
1005
}
940
1006
941
1007
FunctionStat::FunctionStat (SILFunction *F) {
942
- InstCountVisitor V (InstCounts);
1008
+ InstCountVisitor V (InstCounts, VarNames, DebugVariables );
943
1009
V.visitSILFunction (F);
944
1010
BlockCount = V.getBlockCount ();
945
1011
InstCount = V.getInstCount ();
@@ -957,7 +1023,8 @@ void swift::updateSILModuleStatsAfterTransform(SILModule &M,
957
1023
SILTransform *Transform,
958
1024
SILPassManager &PM,
959
1025
int PassNumber, int Duration) {
960
- if (!SILStatsModules && !SILStatsFunctions && !SILStatsDumpAll)
1026
+ if (!SILStatsModules && !SILStatsFunctions && !SILStatsLostVariables
1027
+ && !SILStatsDumpAll)
961
1028
return ;
962
1029
TransformationContext Ctx (M, PM, Transform, PassNumber, Duration);
963
1030
OptimizerStatsAnalysis *Stats = PM.getAnalysis <OptimizerStatsAnalysis>();
0 commit comments