119 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/IR/RuntimeLibcalls.h"10#include "benchmark/benchmark.h"11#include "llvm/IR/DataLayout.h"12#include "llvm/Support/Error.h"13#include "llvm/Support/LineIterator.h"14#include "llvm/Support/MemoryBuffer.h"15#include "llvm/TargetParser/Triple.h"16#include <random>17#include <string>18using namespace llvm;19 20static constexpr unsigned MaxFuncNameSize = 53;21 22static std::vector<StringRef> getLibcallNameStringRefs() {23 std::vector<StringRef> Names(RTLIB::NumLibcallImpls);24 // Keep the strlens on the StringRef construction out of the benchmark loop.25 for (RTLIB::LibcallImpl LC : RTLIB::libcall_impls())26 Names[LC] = RTLIB::RuntimeLibcallsInfo::getLibcallImplName(LC);27 28 return Names;29}30 31static std::vector<std::string> getRandomFuncNames() {32 std::mt19937_64 Rng;33 std::uniform_int_distribution<> StringLengthDistribution(1, MaxFuncNameSize);34 std::uniform_int_distribution<> CharDistribution(1, 255);35 int NumTestFuncs = 1 << 10;36 std::vector<std::string> TestFuncNames(NumTestFuncs);37 38 for (std::string &TestFuncName : TestFuncNames) {39 for (int I = 0, E = StringLengthDistribution(Rng); I != E; ++I)40 TestFuncName += static_cast<char>(CharDistribution(Rng));41 }42 43 return TestFuncNames;44}45 46#ifdef SYMBOL_TEST_DATA_FILE47static std::vector<std::string> readSymbolsFromFile(StringRef InputFile) {48 auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFile, /*IsText=*/true);49 if (!BufOrError) {50 reportFatalUsageError("failed to open \'" + Twine(InputFile) +51 "\': " + BufOrError.getError().message());52 }53 54 // Hackily figure out if there's a prefix on the symbol names - llvm-nm55 // appears to not have a flag to skip this.56 llvm::Triple HostTriple(LLVM_HOST_TRIPLE);57 DataLayout DL(HostTriple.computeDataLayout());58 char GlobalPrefix = DL.getGlobalPrefix();59 60 std::vector<std::string> Lines;61 for (line_iterator LineIt(**BufOrError, /*SkipBlanks=*/true);62 !LineIt.is_at_eof(); ++LineIt) {63 StringRef SymbolName = *LineIt;64 SymbolName.consume_front(StringRef(&GlobalPrefix, 1));65 66 Lines.push_back(SymbolName.str());67 }68 return Lines;69}70#endif71 72static void BM_LookupRuntimeLibcallByNameKnownCalls(benchmark::State &State) {73 std::vector<StringRef> Names = getLibcallNameStringRefs();74 75 for (auto _ : State) {76 for (StringRef Name : Names) {77 benchmark::DoNotOptimize(78 RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(Name).empty());79 }80 }81}82 83static void BM_LookupRuntimeLibcallByNameRandomCalls(benchmark::State &State) {84 std::vector<std::string> TestFuncNames = getRandomFuncNames();85 86 for (auto _ : State) {87 for (const std::string &Name : TestFuncNames) {88 benchmark::DoNotOptimize(89 RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name))90 .empty());91 }92 }93}94 95#ifdef SYMBOL_TEST_DATA_FILE96// This isn't fully representative, it doesn't include any anonymous functions.97// nm -n --no-demangle --format=just-symbols sample-binary > sample.txt98static void BM_LookupRuntimeLibcallByNameSampleData(benchmark::State &State) {99 std::vector<std::string> TestFuncNames =100 readSymbolsFromFile(SYMBOL_TEST_DATA_FILE);101 for (auto _ : State) {102 for (const std::string &Name : TestFuncNames) {103 benchmark::DoNotOptimize(104 RTLIB::RuntimeLibcallsInfo::lookupLibcallImplName(StringRef(Name))105 .empty());106 }107 }108}109#endif110 111BENCHMARK(BM_LookupRuntimeLibcallByNameKnownCalls);112BENCHMARK(BM_LookupRuntimeLibcallByNameRandomCalls);113 114#ifdef SYMBOL_TEST_DATA_FILE115BENCHMARK(BM_LookupRuntimeLibcallByNameSampleData);116#endif117 118BENCHMARK_MAIN();119