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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits