diff --git a/clang-tools-extra/pseudo/CMakeLists.txt b/clang-tools-extra/pseudo/CMakeLists.txt --- a/clang-tools-extra/pseudo/CMakeLists.txt +++ b/clang-tools-extra/pseudo/CMakeLists.txt @@ -3,6 +3,7 @@ add_subdirectory(lib) add_subdirectory(tool) add_subdirectory(fuzzer) +add_subdirectory(benchmarks) if(CLANG_INCLUDE_TESTS) add_subdirectory(unittests) add_subdirectory(test) diff --git a/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/pseudo/benchmarks/Benchmark.cpp @@ -0,0 +1,107 @@ +//===--- Benchmark.cpp - clang pseudoparser benchmarks ---------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "benchmark/benchmark.h" +#include "clang-pseudo/DirectiveTree.h" +#include "clang-pseudo/Forest.h" +#include "clang-pseudo/GLR.h" +#include "clang-pseudo/Grammar.h" +#include "clang-pseudo/LRTable.h" +#include "clang-pseudo/Token.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace clang { +namespace pseudo { +namespace { + +llvm::StringRef GrammarFile; +llvm::StringRef SourceFile; + +std::string readFile(llvm::StringRef FilePath) { + llvm::ErrorOr> GrammarText = + llvm::MemoryBuffer::getFile(FilePath); + if (std::error_code EC = GrammarText.getError()) { + llvm::errs() << "Error: can't read file '" << FilePath + << "': " << EC.message() << "\n"; + std::exit(1); + } + return GrammarText.get()->getBuffer().str(); +} +std::unique_ptr buildGrammar(llvm::StringRef GrammarText) { + std::vector Diags; + return Grammar::parseBNF(GrammarText, Diags); +} +LRTable buildLR(const Grammar &G) { + return clang::pseudo::LRTable::buildSLR(G); +} + +static void runParseGrammar(benchmark::State &State) { + std::string GrammarText = readFile(GrammarFile); + for (auto _ : State) + buildGrammar(GrammarText); +} +BENCHMARK(runParseGrammar); + +static void runLRBuild(benchmark::State &State) { + std::string GrammarText = readFile(GrammarFile); + std::unique_ptr G = buildGrammar(GrammarText); + + for (auto _ : State) + buildLR(*G); +} +BENCHMARK(runLRBuild); + +static void runGLRParse(benchmark::State &State) { + std::string GrammarText = readFile(GrammarFile); + std::unique_ptr G = buildGrammar(GrammarText); + LRTable Table = buildLR(*G); + std::string SourceText = readFile(SourceFile); + clang::LangOptions LangOpts = genericLangOpts(); + + for (auto _ : State) { + pseudo::ForestArena Forest; + pseudo::GSS GSS; + TokenStream RawStream = clang::pseudo::lex(SourceText, LangOpts); + TokenStream Preprocessed = + DirectiveTree::parse(RawStream).stripDirectives(RawStream); + TokenStream ParseableStream = + clang::pseudo::stripComments(cook(Preprocessed, LangOpts)); + glrParse(ParseableStream, ParseParams{*G, Table, Forest, GSS}); + } + State.SetBytesProcessed(static_cast(State.iterations()) * + SourceText.size()); +} +BENCHMARK(runGLRParse); + +} // namespace +} // namespace pseudo +} // namespace clang + +int main(int argc, char *argv[]) { + if (argc < 3) { + llvm::errs() << "Usage: " << argv[0] + << " /path/to/grammar.bnf /path/to/source.cpp " + "BENCHMARK_OPTIONS...\n"; + return 1; + } + + clang::pseudo::GrammarFile = argv[1]; + clang::pseudo::SourceFile = argv[2]; + // The first two arguments are not related to benchmark invocation. + argv[2] = argv[0]; + argv += 2; + argc -= 2; + benchmark::Initialize(&argc, argv); + benchmark::RunSpecifiedBenchmarks(); + return 0; +} diff --git a/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt b/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/clang-tools-extra/pseudo/benchmarks/CMakeLists.txt @@ -0,0 +1,8 @@ + +add_benchmark(ClangPseudoBenchmark Benchmark.cpp) + +target_link_libraries(ClangPseudoBenchmark + PRIVATE + clangPseudo + LLVMSupport + )