djasper created this revision. djasper added a reviewer: rsmith. djasper added a subscriber: cfe-commits. Herald added a subscriber: sanjoy.
In many translation units I have tested, many of the calls to DiagnosticsEngine::GetDiagStatePointForLoc are for source locations before the first diag state point. AFAICT, this happens frequently for locations in the STL and other base libraries. This patch adds a fast path for this case to avoid the costly binary search. This binary search is costly, because the relatively slow SourceManager::isBeforeInTranslationUnit() is used to compare DiagStatePoints. https://reviews.llvm.org/D28207 Files: lib/Basic/Diagnostic.cpp Index: lib/Basic/Diagnostic.cpp =================================================================== --- lib/Basic/Diagnostic.cpp +++ lib/Basic/Diagnostic.cpp @@ -163,21 +163,28 @@ assert(DiagStatePoints.front().Loc.isInvalid() && "Should have created a DiagStatePoint for command-line"); - if (!SourceMgr) + if (!SourceMgr || DiagStatePoints.size() == 1) return DiagStatePoints.end() - 1; FullSourceLoc Loc(L, *SourceMgr); if (Loc.isInvalid()) return DiagStatePoints.end() - 1; - DiagStatePointsTy::iterator Pos = DiagStatePoints.end(); + // Most frequent case: L is after the last diag state change. FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; - if (LastStateChangePos.isValid() && - Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) - Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), - DiagStatePoint(nullptr, Loc)); - --Pos; - return Pos; + assert(LastStateChangePos.isValid()); + if (!Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) + return DiagStatePoints.end() - 1; + + // 2nd most frequent case: L is before the first diag state change. + FullSourceLoc FirstStateChangePos = DiagStatePoints[1].Loc; + assert(FirstStateChangePos.isValid()); + if (Loc.isBeforeInTranslationUnitThan(FirstStateChangePos)) + return DiagStatePoints.begin(); + + // Fall back to binary search. + return std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), + DiagStatePoint(nullptr, Loc)) - 1; } void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
Index: lib/Basic/Diagnostic.cpp =================================================================== --- lib/Basic/Diagnostic.cpp +++ lib/Basic/Diagnostic.cpp @@ -163,21 +163,28 @@ assert(DiagStatePoints.front().Loc.isInvalid() && "Should have created a DiagStatePoint for command-line"); - if (!SourceMgr) + if (!SourceMgr || DiagStatePoints.size() == 1) return DiagStatePoints.end() - 1; FullSourceLoc Loc(L, *SourceMgr); if (Loc.isInvalid()) return DiagStatePoints.end() - 1; - DiagStatePointsTy::iterator Pos = DiagStatePoints.end(); + // Most frequent case: L is after the last diag state change. FullSourceLoc LastStateChangePos = DiagStatePoints.back().Loc; - if (LastStateChangePos.isValid() && - Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) - Pos = std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), - DiagStatePoint(nullptr, Loc)); - --Pos; - return Pos; + assert(LastStateChangePos.isValid()); + if (!Loc.isBeforeInTranslationUnitThan(LastStateChangePos)) + return DiagStatePoints.end() - 1; + + // 2nd most frequent case: L is before the first diag state change. + FullSourceLoc FirstStateChangePos = DiagStatePoints[1].Loc; + assert(FirstStateChangePos.isValid()); + if (Loc.isBeforeInTranslationUnitThan(FirstStateChangePos)) + return DiagStatePoints.begin(); + + // Fall back to binary search. + return std::upper_bound(DiagStatePoints.begin(), DiagStatePoints.end(), + DiagStatePoint(nullptr, Loc)) - 1; } void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits