1 //===-- Benchmark memcmp implementation -----------------------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "LibcBenchmark.h"
10 #include "LibcMemoryBenchmark.h"
11 #include "LibcMemoryBenchmarkMain.h"
12 #include "llvm/ADT/StringSwitch.h"
13 #include "llvm/Support/raw_ostream.h"
14
15 namespace llvm {
16 namespace libc_benchmarks {
17
18 // The context encapsulates the buffers, parameters and the measure.
19 struct MemcmpContext : public BenchmarkRunner {
20 using FunctionPrototype = int (*)(const void *, const void *, size_t);
21
22 struct ParameterType {
23 uint16_t Offset = 0;
24 };
25
MemcmpContextllvm::libc_benchmarks::MemcmpContext26 explicit MemcmpContext(const StudyConfiguration &Conf)
27 : MOD(Conf), OD(Conf), ABuffer(Conf.BufferSize), BBuffer(Conf.BufferSize),
28 PP(*this) {
29 std::uniform_int_distribution<char> Dis;
30 // Generate random buffer A.
31 for (size_t I = 0; I < Conf.BufferSize; ++I)
32 ABuffer[I] = Dis(Gen);
33 // Copy buffer A to B.
34 ::memcpy(BBuffer.begin(), ABuffer.begin(), Conf.BufferSize);
35 if (Conf.MemcmpMismatchAt == 0)
36 return; // all same.
37 else if (Conf.MemcmpMismatchAt == 1)
38 for (char &c : BBuffer)
39 ++c; // all different.
40 else
41 for (const auto I : MOD.getMismatchIndices())
42 ++BBuffer[I];
43 }
44
45 // Needed by the ParameterProvider to update the current batch of parameter.
Randomizellvm::libc_benchmarks::MemcmpContext46 void Randomize(MutableArrayRef<ParameterType> Parameters) {
47 if (MOD)
48 for (auto &P : Parameters)
49 P.Offset = MOD(Gen, CurrentSize);
50 else
51 for (auto &P : Parameters)
52 P.Offset = OD(Gen);
53 }
54
getFunctionNamesllvm::libc_benchmarks::MemcmpContext55 ArrayRef<StringRef> getFunctionNames() const override {
56 static std::array<StringRef, 1> kFunctionNames = {"memcmp"};
57 return kFunctionNames;
58 }
59
benchmarkllvm::libc_benchmarks::MemcmpContext60 BenchmarkResult benchmark(const BenchmarkOptions &Options,
61 StringRef FunctionName, size_t Size) override {
62 CurrentSize = Size;
63 // FIXME: Add `bcmp` once we're guaranteed that the function is provided.
64 FunctionPrototype Function =
65 StringSwitch<FunctionPrototype>(FunctionName).Case("memcmp", &::memcmp);
66 return llvm::libc_benchmarks::benchmark(
67 Options, PP, [this, Function, Size](ParameterType p) {
68 return Function(ABuffer + p.Offset, BBuffer + p.Offset, Size);
69 });
70 }
71
72 private:
73 std::default_random_engine Gen;
74 MismatchOffsetDistribution MOD;
75 OffsetDistribution OD;
76 size_t CurrentSize = 0;
77 AlignedBuffer ABuffer;
78 AlignedBuffer BBuffer;
79 SmallParameterProvider<MemcmpContext> PP;
80 };
81
getRunner(const StudyConfiguration & Conf)82 std::unique_ptr<BenchmarkRunner> getRunner(const StudyConfiguration &Conf) {
83 return std::make_unique<MemcmpContext>(Conf);
84 }
85
86 } // namespace libc_benchmarks
87 } // namespace llvm
88