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,8 @@ +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) + +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,117 @@ +#include +#include +#include +#include +#include +#include + +#include "benchmark/benchmark.h" + +#if defined(__SIZEOF_INT128__) + +namespace { + +constexpr size_t kSampleSize = 1 << 20; + +// Some implementations of do not support __int128_t when it is +// available, so we make our own uniform_int_distribution-like type. +template +class UniformIntDistribution128 { + public: + T operator()(std::mt19937& generator) { + return (static_cast(dist64_(generator)) << 64) | dist64_(generator); + } + + private: + using H = typename std::conditional< + std::is_same::value, int64_t, uint64_t>::type; + std::uniform_int_distribution dist64_; +}; + +// Generates uniformly pairs (a, b) of 128-bit integers such as a >= b. +template +std::vector> GetRandomIntrinsic128SampleUniformDivisor() { + std::vector> values; + std::mt19937 random; + 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(static_cast(2), 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 = (i + 1) % kSampleSize; + } +} +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __uint128_t); +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128UniformDivisor, __int128_t); + +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 = (i + 1) % kSampleSize; + } +} +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __uint128_t); +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128UniformDivisor, __int128_t); + +// Generates random pairs of (a, b) where a >= b, a is 128-bit and +// b is 64-bit. +template ::value, int64_t, uint64_t>::type> +std::vector> GetRandomIntrinsic128SampleSmallDivisor() { + std::vector> values; + std::mt19937 random; + 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 = (i + 1) % kSampleSize; + } +} +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __uint128_t); +BENCHMARK_TEMPLATE(BM_DivideIntrinsic128SmallDivisor, __int128_t); + +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 = (i + 1) % kSampleSize; + } +} +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __uint128_t); +BENCHMARK_TEMPLATE(BM_RemainderIntrinsic128SmallDivisor, __int128_t); + +} // 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)