//===----------------------------------------------------------------------===// // 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 // //===----------------------------------------------------------------------===// #include #include #include #include "benchmark/benchmark.h" #include "CartesianBenchmarks.h" // Tests the full range of the value. template static std::array generate(std::uniform_int_distribution distribution = std::uniform_int_distribution{ std::numeric_limits::min(), std::numeric_limits::max()}) { std::mt19937 generator; std::array result; std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); }); return result; } template static void BM_Basic(benchmark::State& state) { std::array data{generate()}; std::array output; while (state.KeepRunningBatch(data.size())) for (auto value : data) benchmark::DoNotOptimize(std::format_to(output.begin(), "{}", value)); } BENCHMARK_TEMPLATE(BM_Basic, uint32_t); BENCHMARK_TEMPLATE(BM_Basic, int32_t); BENCHMARK_TEMPLATE(BM_Basic, uint64_t); BENCHMARK_TEMPLATE(BM_Basic, int64_t); // Ideally the low values of a 128-bit value are all dispatched to a 64-bit routine. template static void BM_BasicLow(benchmark::State& state) { using U = std::conditional_t, int64_t, uint64_t>; std::array data{ generate(std::uniform_int_distribution{std::numeric_limits::min(), std::numeric_limits::max()})}; std::array output; while (state.KeepRunningBatch(data.size())) for (auto value : data) benchmark::DoNotOptimize(std::format_to(output.begin(), "{}", value)); } BENCHMARK_TEMPLATE(BM_BasicLow, __uint128_t); BENCHMARK_TEMPLATE(BM_BasicLow, __int128_t); BENCHMARK_TEMPLATE(BM_Basic, __uint128_t); BENCHMARK_TEMPLATE(BM_Basic, __int128_t); // *** Localization *** enum class LocalizationE { False, True }; struct AllLocalizations : EnumValuesAsTuple { static constexpr const char* Names[] = {"LocFalse", "LocTrue"}; }; template struct Localization {}; template <> struct Localization { static constexpr const char* fmt = ""; }; template <> struct Localization { static constexpr const char* fmt = "L"; }; // *** Base *** enum class BaseE { Binary, Octal, Decimal, Hex, HexUpper, }; struct AllBases : EnumValuesAsTuple { static constexpr const char* Names[] = {"BaseBin", "BaseOct", "BaseDec", "BaseHex", "BaseHexUpper"}; }; template struct Base {}; template <> struct Base { static constexpr const char* fmt = "b"; }; template <> struct Base { static constexpr const char* fmt = "o"; }; template <> struct Base { static constexpr const char* fmt = "d"; }; template <> struct Base { static constexpr const char* fmt = "x"; }; template <> struct Base { static constexpr const char* fmt = "X"; }; // *** Types *** enum class TypeE { Int64, Uint64 }; struct AllTypes : EnumValuesAsTuple { static constexpr const char* Names[] = {"Int64", "Uint64"}; }; template struct Type {}; template <> struct Type { using type = int64_t; static std::array make_data() { return generate(); } }; template <> struct Type { using type = uint64_t; static std::array make_data() { return generate(); } }; // *** Alignment *** enum class AlignmentE { None, Left, Center, Right, ZeroPadding }; struct AllAlignments : EnumValuesAsTuple { static constexpr const char* Names[] = { "AlignNone", "AlignmentLeft", "AlignmentCenter", "AlignmentRight", "ZeroPadding"}; }; template struct Alignment {}; template <> struct Alignment { static constexpr const char* fmt = ""; }; template <> struct Alignment { static constexpr const char* fmt = "0<512"; }; template <> struct Alignment { static constexpr const char* fmt = "0^512"; }; template <> struct Alignment { static constexpr const char* fmt = "0>512"; }; template <> struct Alignment { static constexpr const char* fmt = "0512"; }; template struct Integral { void run(benchmark::State& state) const { std::array data{Type::make_data()}; std::array output; while (state.KeepRunningBatch(data.size())) for (auto value : data) benchmark::DoNotOptimize(std::format_to(output.begin(), std::string_view{fmt.data(), fmt.size()}, value)); } std::string name() const { return "Integral" + L::name() + B::name() + A::name() + T::name(); } static constexpr std::string make_fmt() { return std::string("{:") + Alignment::fmt + Localization::fmt + Base::fmt + "}"; } static constexpr auto fmt = []() { constexpr size_t s = make_fmt().size(); std::array r; std::ranges::copy(make_fmt(), r.begin()); return r; }(); }; int main(int argc, char** argv) { benchmark::Initialize(&argc, argv); if (benchmark::ReportUnrecognizedArguments(argc, argv)) return 1; makeCartesianProductBenchmark(); benchmark::RunSpecifiedBenchmarks(); }