@@ -276,15 +276,22 @@ llvm::cl::opt<std::string> StatsOnlyFunctionsNamePattern(
276276struct FunctionStat {
277277 int BlockCount = 0 ;
278278 int InstCount = 0 ;
279+ // / True when the FunctionStat is created for a SIL Function after a SIL
280+ // / Optimization pass has been run on it. When it is a post optimization SIL
281+ // / Function, we do not want to store anything in the InlinedAts Map in
282+ // / InstCountVisitor.
283+ bool NewFunc = false ;
279284 // / Instruction counts per SILInstruction kind.
280285 InstructionCounts InstCounts;
281286
282287 using VarID = std::tuple<const SILDebugScope *, llvm::StringRef,
283288 unsigned , unsigned >;
284289 llvm::StringSet<> VarNames;
285290 llvm::DenseSet<FunctionStat::VarID> DebugVariables;
291+ llvm::DenseSet<const SILDebugScope *> VisitedScope;
292+ llvm::DenseMap<VarID, const SILDebugScope *> InlinedAts;
286293
287- FunctionStat (SILFunction *F);
294+ FunctionStat (SILFunction *F, bool NewFunc = false );
288295 FunctionStat () {}
289296
290297 // The DebugVariables set contains pointers to VarNames. Disallow copy.
@@ -384,15 +391,24 @@ struct ModuleStat {
384391struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
385392 int BlockCount = 0 ;
386393 int InstCount = 0 ;
394+ // / True when the InstCountVisitor is created for a SIL Function after a SIL
395+ // / Optimization pass has been run on it. When it is a post optimization SIL
396+ // / Function, we do not want to store anything in the InlinedAts Map in
397+ // / InstCountVisitor.
398+ const bool &NewFunc;
387399 InstructionCounts &InstCounts;
388400
389401 llvm::StringSet<> &VarNames;
390402 llvm::DenseSet<FunctionStat::VarID> &DebugVariables;
403+ llvm::DenseMap<FunctionStat::VarID, const SILDebugScope *> &InlinedAts;
391404
392- InstCountVisitor (InstructionCounts &InstCounts,
393- llvm::StringSet<> &VarNames,
394- llvm::DenseSet<FunctionStat::VarID> &DebugVariables)
395- : InstCounts(InstCounts), VarNames(VarNames), DebugVariables(DebugVariables) {}
405+ InstCountVisitor (
406+ InstructionCounts &InstCounts, llvm::StringSet<> &VarNames,
407+ llvm::DenseSet<FunctionStat::VarID> &DebugVariables,
408+ llvm::DenseMap<FunctionStat::VarID, const SILDebugScope *> &InlinedAts,
409+ bool &NewFunc)
410+ : NewFunc(NewFunc), InstCounts(InstCounts), VarNames(VarNames),
411+ DebugVariables (DebugVariables), InlinedAts(InlinedAts) {}
396412
397413 int getBlockCount () const {
398414 return BlockCount;
@@ -431,6 +447,8 @@ struct InstCountVisitor : SILInstructionVisitor<InstCountVisitor> {
431447 varInfo->Scope ? varInfo->Scope : inst->getDebugScope (),
432448 UniqueName, line, col);
433449 DebugVariables.insert (key);
450+ if (!NewFunc)
451+ InlinedAts.try_emplace (key, varInfo->Scope ->InlinedCallSite );
434452 }
435453};
436454
@@ -710,16 +728,85 @@ bool isFirstTimeData(int Old, int New) {
710728 return Old == 0 && New != Old;
711729}
712730
713- int computeLostVariables (llvm::DenseSet<FunctionStat::VarID> &Old,
714- llvm::DenseSet<FunctionStat::VarID> &New) {
715- unsigned count = 0 ;
716- for (auto &var : Old) {
717- if (New.contains (var))
731+ // / Return true if \p Scope is the same as \p DbgValScope or a child scope of
732+ // / \p DbgValScope, return false otherwise.
733+ bool isScopeChildOfOrEqualTo (const SILDebugScope *Scope,
734+ const SILDebugScope *DbgValScope) {
735+ llvm::DenseSet<const SILDebugScope *> VisitedScope;
736+ while (Scope != nullptr ) {
737+ if (VisitedScope.find (Scope) == VisitedScope.end ()) {
738+ VisitedScope.insert (Scope);
739+ if (Scope == DbgValScope) {
740+ return true ;
741+ }
742+ if (auto *S = dyn_cast<const SILDebugScope *>(Scope->Parent ))
743+ Scope = S;
744+ } else
745+ return false ;
746+ }
747+ return false ;
748+ }
749+
750+ // / Return true if \p InlinedAt is the same as \p DbgValInlinedAt or part of
751+ // / the InlinedAt chain, return false otherwise.
752+ bool isInlinedAtChildOfOrEqualTo (const SILDebugScope *InlinedAt,
753+ const SILDebugScope *DbgValInlinedAt) {
754+ if (DbgValInlinedAt == InlinedAt)
755+ return true ;
756+ if (!DbgValInlinedAt)
757+ return false ;
758+ if (!InlinedAt)
759+ return false ;
760+ auto *IA = InlinedAt;
761+ while (IA) {
762+ if (IA == DbgValInlinedAt)
763+ return true ;
764+ IA = IA->InlinedCallSite ;
765+ }
766+ return false ;
767+ }
768+
769+ int computeLostVariables (SILFunction *F, FunctionStat &Old, FunctionStat &New) {
770+ unsigned LostCount = 0 ;
771+ unsigned PrevLostCount = 0 ;
772+ auto &OldSet = Old.DebugVariables ;
773+ auto &NewSet = New.DebugVariables ;
774+ // Find an Instruction that shares the same scope as the dropped debug_value
775+ // or has a scope that is the child of the scope of the debug_value, and has
776+ // an inlinedAt equal to the inlinedAt of the debug_value or it's inlinedAt
777+ // chain contains the inlinedAt of the debug_value, if such an Instruction is
778+ // found, debug information is dropped.
779+ for (auto &Var : OldSet) {
780+ if (NewSet.contains (Var))
718781 continue ;
719- // llvm::dbgs() << "Lost variable: " << std::get<1>(var) << "\n";
720- count++;
782+ auto &DbgValScope = std::get<0 >(Var);
783+ for (auto &BB : *F) {
784+ for (auto &I : BB) {
785+ if (I.isDebugInstruction ()) {
786+ auto DbgLoc = I.getDebugLocation ();
787+ auto Scope = DbgLoc.getScope ();
788+ // If the Scope is a child of, or equal to the DbgValScope and is
789+ // inlined at the Var's InlinedAt location, return true to signify
790+ // that the Var has been dropped.
791+ if (isScopeChildOfOrEqualTo (Scope, DbgValScope)) {
792+ if (isInlinedAtChildOfOrEqualTo (Scope->InlinedCallSite ,
793+ Old.InlinedAts [Var])) {
794+ // Found another instruction in the variable's scope, so there
795+ // exists a break point at which the variable could be observed.
796+ // Count it as dropped.
797+ LostCount++;
798+ break ;
799+ }
800+ }
801+ }
802+ }
803+ if (PrevLostCount != LostCount) {
804+ PrevLostCount = LostCount;
805+ break ;
806+ }
807+ }
721808 }
722- return count ;
809+ return LostCount ;
723810}
724811
725812// / Dump statistics for a SILFunction. It is only used if a user asked to
@@ -782,8 +869,7 @@ void processFuncStatsChanges(SILFunction *F, FunctionStat &OldStat,
782869 // Compute deltas.
783870 double DeltaBlockCount = computeDelta (OldStat.BlockCount , NewStat.BlockCount );
784871 double DeltaInstCount = computeDelta (OldStat.InstCount , NewStat.InstCount );
785- int LostVariables = computeLostVariables (OldStat.DebugVariables ,
786- NewStat.DebugVariables );
872+ int LostVariables = computeLostVariables (F, OldStat, NewStat);
787873
788874 NewLineInserter nl;
789875
@@ -959,7 +1045,7 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
9591045 InvalidatedFuncs.pop_back ();
9601046 auto &FuncStat = getFunctionStat (F);
9611047 auto &OldFuncStat = FuncStat;
962- FunctionStat NewFuncStat (F);
1048+ FunctionStat NewFuncStat (F, true );
9631049 processFuncStatsChanges (F, OldFuncStat, NewFuncStat, Ctx);
9641050 NewModStat.subFunctionStat (OldFuncStat);
9651051 NewModStat.addFunctionStat (NewFuncStat);
@@ -984,7 +1070,7 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
9841070 AddedFuncs.pop_back ();
9851071 auto &FuncStat = getFunctionStat (F);
9861072 FunctionStat OldFuncStat;
987- FunctionStat NewFuncStat (F);
1073+ FunctionStat NewFuncStat (F, true );
9881074 processFuncStatsChanges (F, OldFuncStat, NewFuncStat, Ctx);
9891075 NewModStat.addFunctionStat (NewFuncStat);
9901076 FuncStat = std::move (NewFuncStat);
@@ -1003,8 +1089,8 @@ void OptimizerStatsAnalysis::updateModuleStats(TransformationContext &Ctx) {
10031089 ModStat = NewModStat;
10041090}
10051091
1006- FunctionStat::FunctionStat (SILFunction *F) {
1007- InstCountVisitor V (InstCounts, VarNames, DebugVariables);
1092+ FunctionStat::FunctionStat (SILFunction *F, bool NewFunc) : NewFunc(NewFunc ) {
1093+ InstCountVisitor V (InstCounts, VarNames, DebugVariables, InlinedAts, NewFunc );
10081094 V.visitSILFunction (F);
10091095 BlockCount = V.getBlockCount ();
10101096 InstCount = V.getInstCount ();
0 commit comments