diff --git a/libcxx/benchmarks/string.bench.cpp b/libcxx/benchmarks/string.bench.cpp --- a/libcxx/benchmarks/string.bench.cpp +++ b/libcxx/benchmarks/string.bench.cpp @@ -73,12 +73,12 @@ "ChangeMiddle", "ChangeLast"}; }; -static constexpr char kSmallStringLiteral[] = "012345678"; +static constexpr char SmallStringLiteral[] = "012345678"; TEST_ALWAYS_INLINE const char* getSmallString(DiffType D) { switch (D) { case DiffType::Control: - return kSmallStringLiteral; + return SmallStringLiteral; case DiffType::ChangeFirst: return "-12345678"; case DiffType::ChangeMiddle: @@ -88,6 +88,9 @@ } } +static constexpr char LargeStringLiteral[] = + "012345678901234567890123456789012345678901234567890123456789012"; + TEST_ALWAYS_INLINE const char* getLargeString(DiffType D) { #define LARGE_STRING_FIRST "123456789012345678901234567890" #define LARGE_STRING_SECOND "234567890123456789012345678901" @@ -263,21 +266,24 @@ } }; -template +template struct StringRelationalLiteral { static void run(benchmark::State& state) { auto Lhs = makeString(LHLength(), DiffType()); for (auto _ : state) { benchmark::DoNotOptimize(Lhs); + constexpr const char* Literal = RHLength::value == Length::Small + ? SmallStringLiteral + : LargeStringLiteral; switch (Rel()) { case Relation::Eq: - benchmark::DoNotOptimize(Lhs == kSmallStringLiteral); + benchmark::DoNotOptimize(Lhs == Literal); break; case Relation::Less: - benchmark::DoNotOptimize(Lhs < kSmallStringLiteral); + benchmark::DoNotOptimize(Lhs < Literal); break; case Relation::Compare: - benchmark::DoNotOptimize(Lhs.compare(kSmallStringLiteral)); + benchmark::DoNotOptimize(Lhs.compare(Literal)); break; } } @@ -285,17 +291,17 @@ static bool skip() { // Doesn't matter how they differ if they have different size. - if (LHLength() != Length::Small && DiffType() != ::DiffType::Control) + if (LHLength() != RHLength() && DiffType() != ::DiffType::Control) return true; // We don't need huge. Doensn't give anything different than Large. - if (LHLength() == Length::Huge) + if (LHLength() == Length::Huge || RHLength() == Length::Huge) return true; return false; } static std::string name() { return "BM_StringRelationalLiteral" + Rel::name() + LHLength::name() + - DiffType::name(); + RHLength::name() + DiffType::name(); } }; @@ -393,6 +399,22 @@ } } +// Some small codegen thunks to easily see generated code. +bool StringEqString(const std::string& a, const std::string& b) { + return a == b; +} +bool StringEqCStr(const std::string& a, const char* b) { return a == b; } +bool CStrEqString(const char* a, const std::string& b) { return a == b; } +bool StringEqCStrLiteralEmpty(const std::string& a) { + return a == ""; +} +bool StringEqCStrLiteralSmall(const std::string& a) { + return a == SmallStringLiteral; +} +bool StringEqCStrLiteralLarge(const std::string& a) { + return a == LargeStringLiteral; +} + int main(int argc, char** argv) { benchmark::Initialize(&argc, argv); if (benchmark::ReportUnrecognizedArguments(argc, argv)) @@ -408,8 +430,16 @@ makeCartesianProductBenchmark(); makeCartesianProductBenchmark(); + AllLengths, AllLengths, AllDiffTypes>(); makeCartesianProductBenchmark(); benchmark::RunSpecifiedBenchmarks(); + + if (argc < 0) { + // ODR-use the functions to force them being generated in the binary. + auto functions = std::make_tuple( + StringEqString, StringEqCStr, CStrEqString, StringEqCStrLiteralEmpty, + StringEqCStrLiteralSmall, StringEqCStrLiteralLarge); + printf("%p", &functions); + } }