| //===----------------------------------------------------------------------===// | |
| // | |
| // 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 "llvm/IR/RuntimeLibcalls.h" | |
| #include "benchmark/benchmark.h" | |
| #include "llvm/IR/DataLayout.h" | |
| #include "llvm/Support/Error.h" | |
| #include "llvm/Support/LineIterator.h" | |
| #include "llvm/Support/MemoryBuffer.h" | |
| #include "llvm/TargetParser/Triple.h" | |
| #include <random> | |
| #include <string> | |
| using namespace llvm; | |
| static constexpr unsigned MaxFuncNameSize = 53; | |
| static std::vector<StringRef> getLibcallNameStringRefs() { | |
| std::vector<StringRef> Names(RTLIB::NumLibcallImpls); | |
| // Keep the strlens on the StringRef construction out of the benchmark loop. | |
| for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls()) | |
| Names[LC] = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LC); | |
| return Names; | |
| } | |
| static std::vector<std::string> getRandomFuncNames() { | |
| std::mt19937_64 Rng; | |
| std::uniform_int_distribution<> StringLengthDistribution(1, MaxFuncNameSize); | |
| std::uniform_int_distribution<> CharDistribution(1, 255); | |
| int NumTestFuncs = 1 << 10; | |
| std::vector<std::string> TestFuncNames(NumTestFuncs); | |
| for (std::string &TestFuncName : TestFuncNames) { | |
| for (int I = 0, E = StringLengthDistribution(Rng); I != E; ++I) | |
| TestFuncName += static_cast<char>(CharDistribution(Rng)); | |
| } | |
| return TestFuncNames; | |
| } | |
| #ifdef SYMBOL_TEST_DATA_FILE | |
| static std::vector<std::string> readSymbolsFromFile(StringRef InputFile) { | |
| auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFile, /*IsText=*/true); | |
| if (!BufOrError) { | |
| reportFatalUsageError("failed to open \'" + Twine(InputFile) + | |
| "\': " + BufOrError.getError().message()); | |
| } | |
| // Hackily figure out if there's a prefix on the symbol names - llvm-nm | |
| // appears to not have a flag to skip this. | |
| llvm::Triple HostTriple(LLVM_HOST_TRIPLE); | |
| DataLayout DL(HostTriple.computeDataLayout()); | |
| char GlobalPrefix = DL.getGlobalPrefix(); | |
| std::vector<std::string> Lines; | |
| for (line_iterator LineIt(**BufOrError, /*SkipBlanks=*/true); | |
| !LineIt.is_at_eof(); ++LineIt) { | |
| StringRef SymbolName = *LineIt; | |
| SymbolName.consume_front(StringRef(&GlobalPrefix, 1)); | |
| Lines.push_back(SymbolName.str()); | |
| } | |
| return Lines; | |
| } | |
| #endif | |
| static void BM_LookupRuntimeLibcallByNameKnownCalls(benchmark::State &State) { | |
| std::vector<StringRef> Names = getLibcallNameStringRefs(); | |
| for (auto _ : State) { | |
| for (StringRef Name : Names) { | |
| benchmark::DoNotOptimize( | |
| RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name).empty()); | |
| } | |
| } | |
| } | |
| static void BM_LookupRuntimeLibcallByNameRandomCalls(benchmark::State &State) { | |
| std::vector<std::string> TestFuncNames = getRandomFuncNames(); | |
| for (auto _ : State) { | |
| for (const std::string &Name : TestFuncNames) { | |
| benchmark::DoNotOptimize( | |
| RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name)) | |
| .empty()); | |
| } | |
| } | |
| } | |
| #ifdef SYMBOL_TEST_DATA_FILE | |
| // This isn't fully representative, it doesn't include any anonymous functions. | |
| // nm -n --no-demangle --format=just-symbols sample-binary > sample.txt | |
| static void BM_LookupRuntimeLibcallByNameSampleData(benchmark::State &State) { | |
| std::vector<std::string> TestFuncNames = | |
| readSymbolsFromFile(SYMBOL_TEST_DATA_FILE); | |
| for (auto _ : State) { | |
| for (const std::string &Name : TestFuncNames) { | |
| benchmark::DoNotOptimize( | |
| RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name)) | |
| .empty()); | |
| } | |
| } | |
| } | |
| #endif | |
| BENCHMARK(BM_LookupRuntimeLibcallByNameKnownCalls); | |
| BENCHMARK(BM_LookupRuntimeLibcallByNameRandomCalls); | |
| #ifdef SYMBOL_TEST_DATA_FILE | |
| BENCHMARK(BM_LookupRuntimeLibcallByNameSampleData); | |
| #endif | |
| BENCHMARK_MAIN(); |