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>
23 getOffsetDistribution(size_t BufferSize, size_t MaxSizeValue,
24                       MaybeAlign AccessAlignment) {
25   if (AccessAlignment && *AccessAlignment > AlignedBuffer::Alignment)
26     report_fatal_error(
27         "AccessAlignment must be less or equal to AlignedBuffer::Alignment");
28   if (!AccessAlignment)
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 = BufferSize;
33   MaxOffset -= MaxSizeValue;
34   MaxOffset -= 1;
35   if (MaxOffset < 0)
36     report_fatal_error(
37         "BufferSize too small to exercise specified Size configuration");
38   MaxOffset /= AccessAlignment->value();
39   return std::uniform_int_distribution<uint32_t>(0, MaxOffset);
40 }
41 
42 OffsetDistribution::OffsetDistribution(size_t BufferSize, size_t MaxSizeValue,
43                                        MaybeAlign AccessAlignment)
44     : Distribution(
45           getOffsetDistribution(BufferSize, MaxSizeValue, AccessAlignment)),
46       Factor(AccessAlignment.valueOrOne().value()) {}
47 
48 // Precomputes offset where to insert mismatches between the two buffers.
49 MismatchOffsetDistribution::MismatchOffsetDistribution(size_t BufferSize,
50                                                        size_t MaxSizeValue,
51                                                        size_t MismatchAt)
52     : MismatchAt(MismatchAt) {
53   if (MismatchAt <= 1)
54     return;
55   for (size_t I = MaxSizeValue + 1; I < BufferSize; I += MaxSizeValue)
56     MismatchIndices.push_back(I);
57   if (MismatchIndices.empty())
58     report_fatal_error("Unable to generate mismatch");
59   MismatchIndexSelector =
60       std::uniform_int_distribution<size_t>(0, MismatchIndices.size() - 1);
61 }
62 
63 } // namespace libc_benchmarks
64 } // namespace llvm
65