summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2019-09-11 20:40:31 +0000
committerAlex Lorenz <arphaman@gmail.com>2019-09-11 20:40:31 +0000
commitca6e60971e9578acb0561df7797283474291f9d9 (patch)
tree7befe213930939771810d9aa830ce7323c119389 /clang/lib/Lex
parent2f843616849963e8df7a561ce5179ed29a767057 (diff)
downloadbcm5719-llvm-ca6e60971e9578acb0561df7797283474291f9d9.tar.gz
bcm5719-llvm-ca6e60971e9578acb0561df7797283474291f9d9.zip
[clang-scan-deps] add skip excluded conditional preprocessor block preprocessing optimization
This commit adds an optimization to clang-scan-deps and clang's preprocessor that skips excluded preprocessor blocks by bumping the lexer pointer, and not lexing the tokens until reaching appropriate #else/#endif directive. The skip positions and lexer offsets are computed when the file is minimized, directly from the minimized tokens. On an 18-core iMacPro with macOS Catalina Beta I got 10-15% speed-up from this optimization when running clang-scan-deps on the compilation database for a recent LLVM and Clang (3511 files). Differential Revision: https://reviews.llvm.org/D67127 llvm-svn: 371656
Diffstat (limited to 'clang/lib/Lex')
-rw-r--r--clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp48
-rw-r--r--clang/lib/Lex/Lexer.cpp9
-rw-r--r--clang/lib/Lex/PPDirectives.cpp36
-rw-r--r--clang/lib/Lex/Preprocessor.cpp5
4 files changed, 98 insertions, 0 deletions
diff --git a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
index a350481df9a..0a0656699ab 100644
--- a/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
+++ b/clang/lib/Lex/DependencyDirectivesSourceMinimizer.cpp
@@ -865,6 +865,54 @@ bool Minimizer::minimize() {
return Error;
}
+bool clang::minimize_source_to_dependency_directives::computeSkippedRanges(
+ ArrayRef<Token> Input, llvm::SmallVectorImpl<SkippedRange> &Range) {
+ struct Directive {
+ enum DirectiveKind {
+ If, // if/ifdef/ifndef
+ Else // elif,else
+ };
+ int Offset;
+ DirectiveKind Kind;
+ };
+ llvm::SmallVector<Directive, 32> Offsets;
+ for (const Token &T : Input) {
+ switch (T.K) {
+ case pp_if:
+ case pp_ifdef:
+ case pp_ifndef:
+ Offsets.push_back({T.Offset, Directive::If});
+ break;
+
+ case pp_elif:
+ case pp_else: {
+ if (Offsets.empty())
+ return true;
+ int PreviousOffset = Offsets.back().Offset;
+ Range.push_back({PreviousOffset, T.Offset - PreviousOffset});
+ Offsets.push_back({T.Offset, Directive::Else});
+ break;
+ }
+
+ case pp_endif: {
+ if (Offsets.empty())
+ return true;
+ int PreviousOffset = Offsets.back().Offset;
+ Range.push_back({PreviousOffset, T.Offset - PreviousOffset});
+ do {
+ Directive::DirectiveKind Kind = Offsets.pop_back_val().Kind;
+ if (Kind == Directive::If)
+ break;
+ } while (!Offsets.empty());
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
bool clang::minimizeSourceToDependencyDirectives(
StringRef Input, SmallVectorImpl<char> &Output,
SmallVectorImpl<Token> &Tokens, DiagnosticsEngine *Diags,
diff --git a/clang/lib/Lex/Lexer.cpp b/clang/lib/Lex/Lexer.cpp
index db53e6bec04..17f5ab1e035 100644
--- a/clang/lib/Lex/Lexer.cpp
+++ b/clang/lib/Lex/Lexer.cpp
@@ -218,6 +218,15 @@ Lexer *Lexer::Create_PragmaLexer(SourceLocation SpellingLoc,
return L;
}
+bool Lexer::skipOver(unsigned NumBytes) {
+ IsAtPhysicalStartOfLine = true;
+ IsAtStartOfLine = true;
+ if ((BufferPtr + NumBytes) > BufferEnd)
+ return true;
+ BufferPtr += NumBytes;
+ return false;
+}
+
template <typename T> static void StringifyImpl(T &Str, char Quote) {
typename T::size_type i = 0, e = Str.size();
while (i < e) {
diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp
index d9a98dc4eff..a4ac9506e13 100644
--- a/clang/lib/Lex/PPDirectives.cpp
+++ b/clang/lib/Lex/PPDirectives.cpp
@@ -370,6 +370,37 @@ SourceLocation Preprocessor::CheckEndOfDirective(const char *DirType,
return DiscardUntilEndOfDirective().getEnd();
}
+Optional<unsigned> Preprocessor::getSkippedRangeForExcludedConditionalBlock(
+ SourceLocation HashLoc) {
+ if (!ExcludedConditionalDirectiveSkipMappings)
+ return None;
+ if (!HashLoc.isFileID())
+ return None;
+
+ std::pair<FileID, unsigned> HashFileOffset =
+ SourceMgr.getDecomposedLoc(HashLoc);
+ const llvm::MemoryBuffer *Buf = SourceMgr.getBuffer(HashFileOffset.first);
+ auto It = ExcludedConditionalDirectiveSkipMappings->find(Buf);
+ if (It == ExcludedConditionalDirectiveSkipMappings->end())
+ return None;
+
+ const PreprocessorSkippedRangeMapping &SkippedRanges = *It->getSecond();
+ // Check if the offset of '#' is mapped in the skipped ranges.
+ auto MappingIt = SkippedRanges.find(HashFileOffset.second);
+ if (MappingIt == SkippedRanges.end())
+ return None;
+
+ unsigned BytesToSkip = MappingIt->getSecond();
+ unsigned CurLexerBufferOffset = CurLexer->getCurrentBufferOffset();
+ assert(CurLexerBufferOffset >= HashFileOffset.second &&
+ "lexer is before the hash?");
+ // Take into account the fact that the lexer has already advanced, so the
+ // number of bytes to skip must be adjusted.
+ unsigned LengthDiff = CurLexerBufferOffset - HashFileOffset.second;
+ assert(BytesToSkip >= LengthDiff && "lexer is after the skipped range?");
+ return BytesToSkip - LengthDiff;
+}
+
/// SkipExcludedConditionalBlock - We just read a \#if or related directive and
/// decided that the subsequent tokens are in the \#if'd out portion of the
/// file. Lex the rest of the file, until we see an \#endif. If
@@ -396,6 +427,11 @@ void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc,
// disabling warnings, etc.
CurPPLexer->LexingRawMode = true;
Token Tok;
+ if (auto SkipLength =
+ getSkippedRangeForExcludedConditionalBlock(HashTokenLoc)) {
+ // Skip to the next '#endif' / '#else' / '#elif'.
+ CurLexer->skipOver(*SkipLength);
+ }
while (true) {
CurLexer->Lex(Tok);
diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp
index 3abd0c76d0f..82007732a9b 100644
--- a/clang/lib/Lex/Preprocessor.cpp
+++ b/clang/lib/Lex/Preprocessor.cpp
@@ -158,6 +158,11 @@ Preprocessor::Preprocessor(std::shared_ptr<PreprocessorOptions> PPOpts,
if (this->PPOpts->GeneratePreamble)
PreambleConditionalStack.startRecording();
+
+ ExcludedConditionalDirectiveSkipMappings =
+ this->PPOpts->ExcludedConditionalDirectiveSkipMappings;
+ if (ExcludedConditionalDirectiveSkipMappings)
+ ExcludedConditionalDirectiveSkipMappings->clear();
}
Preprocessor::~Preprocessor() {
OpenPOWER on IntegriCloud