1 //===-- Benchmark memory specific tools -----------------------------------===//
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 "LibcMemoryBenchmark.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/Support/ErrorHandling.h"
12 #include "llvm/Support/MathExtras.h"
13 #include <algorithm>
14 
15 namespace llvm {
16 namespace libc_benchmarks {
17 
18 // Returns a distribution that samples the buffer to satisfy the required
19 // alignment.
20 // When alignment is set, the distribution is scaled down by `Factor` and scaled
21 // up again by the same amount during sampling.
22 static std::uniform_int_distribution<uint32_t>
GetOffsetDistribution(const StudyConfiguration & Conf)23 GetOffsetDistribution(const StudyConfiguration &Conf) {
24   if (Conf.AddressAlignment &&
25       *Conf.AddressAlignment > AlignedBuffer::Alignment)
26     report_fatal_error(
27         "AddressAlignment must be less or equal to AlignedBuffer::Alignment");
28   if (!Conf.AddressAlignment)
29     return std::uniform_int_distribution<uint32_t>(0, 0); // Always 0.
30   // If we test up to Size bytes, the returned offset must stay under
31   // BuffersSize - Size.
32   int64_t MaxOffset = Conf.BufferSize;
33   MaxOffset -= Conf.Size.To;
34   MaxOffset -= 1;
35   if (MaxOffset < 0)
36     report_fatal_error(
37         "BufferSize too small to exercise specified Size configuration");
38   MaxOffset /= Conf.AddressAlignment->value();
39   return std::uniform_int_distribution<uint32_t>(0, MaxOffset);
40 }
41 
OffsetDistribution(const StudyConfiguration & Conf)42 OffsetDistribution::OffsetDistribution(const StudyConfiguration &Conf)
43     : Distribution(GetOffsetDistribution(Conf)),
44       Factor(Conf.AddressAlignment.valueOrOne().value()) {}
45 
46 // Precomputes offset where to insert mismatches between the two buffers.
MismatchOffsetDistribution(const StudyConfiguration & Conf)47 MismatchOffsetDistribution::MismatchOffsetDistribution(
48     const StudyConfiguration &Conf)
49     : MismatchAt(Conf.MemcmpMismatchAt) {
50   if (MismatchAt <= 1)
51     return;
52   const auto ToSize = Conf.Size.To;
53   for (size_t I = ToSize + 1; I < Conf.BufferSize; I += ToSize)
54     MismatchIndices.push_back(I);
55   if (MismatchIndices.empty())
56     llvm::report_fatal_error("Unable to generate mismatch");
57   MismatchIndexSelector =
58       std::uniform_int_distribution<size_t>(0, MismatchIndices.size() - 1);
59 }
60 
61 } // namespace libc_benchmarks
62 } // namespace llvm
63