[Clang][CoverageMapping] Fix compile time explosions by adjusting only appropriated skipped ranges

D83592 added comments to be part of skipped regions, and as part of that, it
also shrinks a skipped range if it spans a line that contains a non-comment
token. This is done by `adjustSkippedRange`.

The `adjustSkippedRange` currently runs on skipped regions that are not
comments, causing a 5min regression while building a big C++ files without any
comments.

Fix the compile time introduced in D83592 by tagging SkippedRange with kind
information and use that to decide what needs additional processing.

Differential Revision: https://reviews.llvm.org/D127338
This commit is contained in:
Bruno Cardoso Lopes 2022-06-08 00:54:05 -07:00
parent a4c97e1937
commit e6a76a4935
2 changed files with 32 additions and 10 deletions

View File

@ -60,26 +60,27 @@ CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) {
return CoverageInfo; return CoverageInfo;
} }
void CoverageSourceInfo::AddSkippedRange(SourceRange Range) { void CoverageSourceInfo::AddSkippedRange(SourceRange Range,
SkippedRange::Kind RangeKind) {
if (EmptyLineCommentCoverage && !SkippedRanges.empty() && if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
PrevTokLoc == SkippedRanges.back().PrevTokLoc && PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(), SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
Range.getBegin())) Range.getBegin()))
SkippedRanges.back().Range.setEnd(Range.getEnd()); SkippedRanges.back().Range.setEnd(Range.getEnd());
else else
SkippedRanges.push_back({Range, PrevTokLoc}); SkippedRanges.push_back({Range, RangeKind, PrevTokLoc});
} }
void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
AddSkippedRange(Range); AddSkippedRange(Range, SkippedRange::PPIfElse);
} }
void CoverageSourceInfo::HandleEmptyline(SourceRange Range) { void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
AddSkippedRange(Range); AddSkippedRange(Range, SkippedRange::EmptyLine);
} }
bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) { bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
AddSkippedRange(Range); AddSkippedRange(Range, SkippedRange::Comment);
return false; return false;
} }
@ -335,6 +336,8 @@ public:
/// This shrinks the skipped range if it spans a line that contains a /// This shrinks the skipped range if it spans a line that contains a
/// non-comment token. If shrinking the skipped range would make it empty, /// non-comment token. If shrinking the skipped range would make it empty,
/// this returns None. /// this returns None.
/// Note this function can potentially be expensive because
/// getSpellingLineNumber uses getLineNumber, which is expensive.
Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM, Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
SourceLocation LocStart, SourceLocation LocStart,
SourceLocation LocEnd, SourceLocation LocEnd,
@ -382,8 +385,13 @@ public:
auto CovFileID = getCoverageFileID(LocStart); auto CovFileID = getCoverageFileID(LocStart);
if (!CovFileID) if (!CovFileID)
continue; continue;
Optional<SpellingRegion> SR = Optional<SpellingRegion> SR;
adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc); if (I.isComment())
SR = adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc,
I.NextTokLoc);
else if (I.isPPIfElse() || I.isEmptyLine())
SR = {SM, LocStart, LocEnd};
if (!SR.hasValue()) if (!SR.hasValue())
continue; continue;
auto Region = CounterMappingRegion::makeSkipped( auto Region = CounterMappingRegion::makeSkipped(

View File

@ -31,15 +31,29 @@ class Decl;
class Stmt; class Stmt;
struct SkippedRange { struct SkippedRange {
enum Kind {
PPIfElse, // Preprocessor #if/#else ...
EmptyLine,
Comment,
};
SourceRange Range; SourceRange Range;
// The location of token before the skipped source range. // The location of token before the skipped source range.
SourceLocation PrevTokLoc; SourceLocation PrevTokLoc;
// The location of token after the skipped source range. // The location of token after the skipped source range.
SourceLocation NextTokLoc; SourceLocation NextTokLoc;
// The nature of this skipped range
Kind RangeKind;
SkippedRange(SourceRange Range, SourceLocation PrevTokLoc = SourceLocation(), bool isComment() { return RangeKind == Comment; }
bool isEmptyLine() { return RangeKind == EmptyLine; }
bool isPPIfElse() { return RangeKind == PPIfElse; }
SkippedRange(SourceRange Range, Kind K,
SourceLocation PrevTokLoc = SourceLocation(),
SourceLocation NextTokLoc = SourceLocation()) SourceLocation NextTokLoc = SourceLocation())
: Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc) {} : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc),
RangeKind(K) {}
}; };
/// Stores additional source code information like skipped ranges which /// Stores additional source code information like skipped ranges which
@ -62,7 +76,7 @@ public:
std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; } std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; }
void AddSkippedRange(SourceRange Range); void AddSkippedRange(SourceRange Range, SkippedRange::Kind RangeKind);
void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override; void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;