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