[llvm] [Offload][Conformance] Add `RandomGenerator` for large input spaces (PR #154252)
Ross Brunton via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 19 02:31:04 PDT 2025
================
@@ -0,0 +1,112 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the definition of the RangeBasedGenerator class, a base
+/// class for input generators that operate on a sequence of ranges.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef MATHTEST_RANGEBASEDGENERATOR_HPP
+#define MATHTEST_RANGEBASEDGENERATOR_HPP
+
+#include "mathtest/IndexedRange.hpp"
+#include "mathtest/InputGenerator.hpp"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Parallel.h"
+
+#include <algorithm>
+#include <array>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <optional>
+#include <tuple>
+
+namespace mathtest {
+
+template <typename Derived, typename... InTypes>
+class [[nodiscard]] RangeBasedGenerator : public InputGenerator<InTypes...> {
+public:
+ void reset() noexcept override { NextFlatIndex = 0; }
+
+ [[nodiscard]] std::size_t
+ fill(llvm::MutableArrayRef<InTypes>... Buffers) noexcept override {
+ const std::array<std::size_t, NumInputs> BufferSizes = {Buffers.size()...};
+ const std::size_t BufferSize = BufferSizes[0];
+ assert((BufferSize != 0) && "Buffer size cannot be zero");
+ assert(std::all_of(BufferSizes.begin(), BufferSizes.end(),
+ [&](std::size_t Size) { return Size == BufferSize; }) &&
+ "All input buffers must have the same size");
+
+ if (NextFlatIndex >= SizeToGenerate)
+ return 0;
+
+ const auto BatchSize =
+ std::min<uint64_t>(BufferSize, SizeToGenerate - NextFlatIndex);
+ const auto CurrentFlatIndex = NextFlatIndex;
+ NextFlatIndex += BatchSize;
+
+ auto BufferPtrsTuple = std::make_tuple(Buffers.data()...);
+
+ llvm::parallelFor(0, BatchSize, [&](std::size_t Offset) {
+ static_cast<Derived *>(this)->writeInputs(CurrentFlatIndex, Offset,
+ BufferPtrsTuple);
+ });
+
+ return static_cast<std::size_t>(BatchSize);
+ }
+
+protected:
+ using RangesTupleType = std::tuple<IndexedRange<InTypes>...>;
+
+ static constexpr std::size_t NumInputs = sizeof...(InTypes);
+ static_assert(NumInputs > 0, "The number of inputs must be at least 1");
+
+ explicit constexpr RangeBasedGenerator(
+ const IndexedRange<InTypes> &...Ranges) noexcept
+ : RangesTuple(Ranges...) {
+ const auto MaybeInputSpaceSize = getInputSpaceSize(Ranges...);
+
+ assert(MaybeInputSpaceSize.has_value() &&
+ "The input space size is too large");
+ InputSpaceSize = *MaybeInputSpaceSize;
+
+ assert((InputSpaceSize > 0) && "The input space size must be at least 1");
+ }
+
+ uint64_t SizeToGenerate = 0;
+ uint64_t InputSpaceSize = 1;
+ RangesTupleType RangesTuple;
+
+private:
+ [[nodiscard]] static constexpr std::optional<uint64_t>
+ getInputSpaceSize(const IndexedRange<InTypes> &...Ranges) noexcept {
+ uint64_t InputSpaceSize = 1;
+ bool Overflowed = false;
+
+ auto Multiplier = [&](const uint64_t RangeSize) {
+ if (!Overflowed)
+ Overflowed =
+ __builtin_mul_overflow(InputSpaceSize, RangeSize, &InputSpaceSize);
----------------
RossBrunton wrote:
LLVM provides `MulOverflow` for this, rather than relying on a compiler-specific function.
Also, I think `Overflowed |= blah` might be more idiomatic.
https://github.com/llvm/llvm-project/pull/154252
More information about the llvm-commits
mailing list