[libcxx-commits] [libcxx] r357614 - Add more benchmarks for literal strings.

Samuel Benzaquen via libcxx-commits libcxx-commits at lists.llvm.org
Wed Apr 3 10:40:52 PDT 2019


Author: sbenza
Date: Wed Apr  3 10:40:51 2019
New Revision: 357614

URL: http://llvm.org/viewvc/llvm-project?rev=357614&view=rev
Log:
Add more benchmarks for literal strings.

Summary:
Comparing against the empty string should generate much better code that
what it does today.
We can also generate better code when comparing against literals that
are larger than the SSO space.

Reviewers: EricWF

Subscribers: christof, jdoerfert, libcxx-commits

Tags: #libc

Differential Revision: https://reviews.llvm.org/D59781

Modified:
    libcxx/trunk/benchmarks/string.bench.cpp

Modified: libcxx/trunk/benchmarks/string.bench.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/benchmarks/string.bench.cpp?rev=357614&r1=357613&r2=357614&view=diff
==============================================================================
--- libcxx/trunk/benchmarks/string.bench.cpp (original)
+++ libcxx/trunk/benchmarks/string.bench.cpp Wed Apr  3 10:40:51 2019
@@ -73,12 +73,12 @@ struct AllDiffTypes : EnumValuesAsTuple<
                                           "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 @@ TEST_ALWAYS_INLINE const char* getSmallS
   }
 }
 
+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,26 @@ struct StringRelational {
   }
 };
 
-template <class Rel, class LHLength, class DiffType>
+template <class Rel, class LHLength, class RHLength, class DiffType>
 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::Empty
+                                          ? ""
+                                          : 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 +293,17 @@ struct StringRelationalLiteral {
 
   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 +401,22 @@ void sanityCheckGeneratedStrings() {
   }
 }
 
+// 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 +432,16 @@ int main(int argc, char** argv) {
   makeCartesianProductBenchmark<StringRelational, AllRelations, AllLengths,
                                 AllLengths, AllDiffTypes>();
   makeCartesianProductBenchmark<StringRelationalLiteral, AllRelations,
-                                AllLengths, AllDiffTypes>();
+                                AllLengths, AllLengths, AllDiffTypes>();
   makeCartesianProductBenchmark<StringRead, AllTemperatures, AllDepths,
                                 AllLengths>();
   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);
+  }
 }




More information about the libcxx-commits mailing list