Index: MicroBenchmarks/Builtins/CMakeLists.txt =================================================================== --- /dev/null +++ MicroBenchmarks/Builtins/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(Int128) Index: MicroBenchmarks/Builtins/Int128/CMakeLists.txt =================================================================== --- /dev/null +++ MicroBenchmarks/Builtins/Int128/CMakeLists.txt @@ -0,0 +1,7 @@ +list(APPEND CPPFLAGS -std=c++11) + +llvm_test_run(WORKDIR ${CMAKE_CURRENT_BINARY_DIR}) + +llvm_test_executable(Builtins main.cpp) + +target_link_libraries(Builtins benchmark) Index: MicroBenchmarks/Builtins/Int128/main.cpp =================================================================== --- /dev/null +++ MicroBenchmarks/Builtins/Int128/main.cpp @@ -0,0 +1,137 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include "benchmark/benchmark.h" + +#if defined(__SIZEOF_INT128__) + +namespace { + +constexpr size_t kSampleSize = 1000000; + +std::mt19937 MakeRandomEngine() { + std::random_device r; + std::seed_seq seed({r(), r(), r(), r(), r(), r(), r(), r()}); + return std::mt19937(seed); +} + +// Some implementations of do not support __int128 when it is +// available, so we make our own uniform_int_distribution-like type. +template ::value, int64_t, uint64_t>::type> +class UniformIntDistribution128 { + public: + T operator()(std::mt19937& generator) { + return (static_cast(dist64_(generator)) << 64) | dist64_(generator); + } + + private: + std::uniform_int_distribution dist64_; +}; + +template ::value, int64_t, uint64_t>::type> +std::vector> GetRandomIntrinsic128SampleUniformDivisor() { + std::vector> values; + std::mt19937 random = MakeRandomEngine(); + UniformIntDistribution128 uniform_128; + values.reserve(kSampleSize); + for (size_t i = 0; i < kSampleSize; ++i) { + T a = uniform_128(random); + T b = uniform_128(random); + values.emplace_back(std::max(a, b), + std::max(static_cast(2), std::min(a, b))); + } + return values; +} + +template +void BM_DivideIntrinsic128UniformDivisor(benchmark::State& state) { + auto values = GetRandomIntrinsic128SampleUniformDivisor(); + size_t i = 0; + for (const auto _ : state) { + benchmark::DoNotOptimize(values[i].first / values[i].second); + ++i; + if (i == values.size()) { + i = 0; + } + } +} +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, unsigned __int128); +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __int128); + +template +void BM_RemainderIntrinsic128UniformDivisor(benchmark::State& state) { + auto values = GetRandomIntrinsic128SampleUniformDivisor(); + size_t i = 0; + for (const auto _ : state) { + benchmark::DoNotOptimize(values[i].first % values[i].second); + ++i; + if (i == values.size()) { + i = 0; + } + } +} +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, unsigned __int128); +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __int128); + +template ::value, int64_t, uint64_t>::type> +std::vector> GetRandomIntrinsic128SampleSmallDivisor() { + std::vector> values; + std::mt19937 random = MakeRandomEngine(); + UniformIntDistribution128 uniform_int128; + std::uniform_int_distribution uniform_int64; + values.reserve(kSampleSize); + for (size_t i = 0; i < kSampleSize; ++i) { + T a = uniform_int128(random); + H b = std::max(H{2}, uniform_int64(random)); + values.emplace_back(std::max(a, static_cast(b)), b); + } + return values; +} + +template +void BM_DivideIntrinsic128SmallDivisor(benchmark::State& state) { + auto values = GetRandomIntrinsic128SampleSmallDivisor(); + size_t i = 0; + for (const auto _ : state) { + benchmark::DoNotOptimize(values[i].first / values[i].second); + ++i; + if (i == values.size()) { + i = 0; + } + } +} +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, unsigned __int128); +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128); + +template +void BM_RemainderIntrinsic128SmallDivisor(benchmark::State& state) { + auto values = GetRandomIntrinsic128SampleSmallDivisor(); + size_t i = 0; + for (const auto _ : state) { + benchmark::DoNotOptimize(values[i].first % values[i].second); + ++i; + if (i == values.size()) { + i = 0; + } + } +} +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, unsigned __int128); +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128); + +} // namespace + +#endif + +BENCHMARK_MAIN(); Index: MicroBenchmarks/CMakeLists.txt =================================================================== --- MicroBenchmarks/CMakeLists.txt +++ MicroBenchmarks/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(ImageProcessing) add_subdirectory(LoopInterchange) add_subdirectory(MemFunctions) +add_subdirectory(Builtins)