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 llvm-svn: 357614
This commit is contained in:
parent
8a497a958b
commit
27a83e99f4
|
@ -73,12 +73,12 @@ struct AllDiffTypes : EnumValuesAsTuple<AllDiffTypes, DiffType, 4> {
|
|||
"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* getSmallString(DiffType D) {
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue