From af855d39937c8432dcb0d9c00acc31732736932c Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sun, 31 May 2020 09:31:23 +0200 Subject: [PATCH] Move subtract to the new format --- benchmarks/BM_subtract.cpp | 12 ++++-- src/sfizz/SIMDHelpers.cpp | 53 ++++++++++++++++++++++++ src/sfizz/SIMDHelpers.h | 83 +++++++++++++++++--------------------- src/sfizz/SIMDSSE.cpp | 41 ------------------- tests/SIMDHelpersT.cpp | 20 +++++---- 5 files changed, 112 insertions(+), 97 deletions(-) diff --git a/benchmarks/BM_subtract.cpp b/benchmarks/BM_subtract.cpp index afc8fc95..0bc60f15 100644 --- a/benchmarks/BM_subtract.cpp +++ b/benchmarks/BM_subtract.cpp @@ -36,28 +36,32 @@ public: BENCHMARK_DEFINE_F(SubArray, Scalar)(benchmark::State& state) { for (auto _ : state) { - sfz::subtract(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false); + sfz::subtract(input, absl::MakeSpan(output)); } } BENCHMARK_DEFINE_F(SubArray, SIMD)(benchmark::State& state) { for (auto _ : state) { - sfz::subtract(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true); + sfz::subtract(input, absl::MakeSpan(output)); } } BENCHMARK_DEFINE_F(SubArray, Scalar_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::subtract(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false); + sfz::subtract(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); } } BENCHMARK_DEFINE_F(SubArray, SIMD_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::subtract(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true); + sfz::subtract(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); } } diff --git a/src/sfizz/SIMDHelpers.cpp b/src/sfizz/SIMDHelpers.cpp index 245246be..ada8cb78 100644 --- a/src/sfizz/SIMDHelpers.cpp +++ b/src/sfizz/SIMDHelpers.cpp @@ -392,4 +392,57 @@ void add(float value, float* output, unsigned size) noexcept *output++ += value; } +template <> +void subtract(const float* input, float* output, unsigned size) noexcept +{ + const auto sentinel = output + size; + + if (getSIMDOpStatus(SIMDOps::subtract)) { +#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386 + if (cpuInfo.has_sse()) { + const auto* lastAligned = prevAligned(sentinel); + + while (unaligned(input, output) && output < lastAligned) + *output++ -= *input++; + + while (output < lastAligned) { + _mm_store_ps(output, _mm_sub_ps(_mm_load_ps(output), _mm_load_ps(input))); + incrementAll<4>(input, output); + } + // fallthrough from lastAligned to sentinel + } +#endif + } + + while (output < sentinel) + *output++ -= *input++; +} + +template <> +void subtract(float value, float* output, unsigned size) noexcept +{ + const auto sentinel = output + size; + + if (getSIMDOpStatus(SIMDOps::subtract)) { +#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386 + if (cpuInfo.has_sse()) { + const auto* lastAligned = prevAligned(sentinel); + + while (unaligned(output) && output < lastAligned) + *output++ -= value; + + const auto mmValue = _mm_set1_ps(value); + while (output < lastAligned) { + _mm_store_ps(output, _mm_sub_ps(_mm_load_ps(output), mmValue)); + incrementAll<4>(output); + } + // fallthrough from lastAligned to sentinel + } +#endif + } + + while (output < sentinel) + *output++ -= value; +} + } diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 24370bb0..29e36f33 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -450,63 +450,56 @@ void add(T value, absl::Span output) noexcept add(value, output.data(), output.size()); } -namespace _internals { - template - inline void snippetSubtract(const T*& input, T*& output) - { - *output++ -= *input++; - } - - template - inline void snippetSubtract(const T value, T*& output) - { - *output++ -= value; - } -} - /** - * @brief Subtract a value from a span + * @brief Subtract an input span from the output span * * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version - * @param value - * @param output - */ -template -void subtract(const T value, absl::Span output) noexcept -{ - auto* out = output.begin(); - auto* sentinel = output.end(); - while (out < sentinel) - _internals::snippetSubtract(value, out); -} - -/** - * @brief Subtract a span from another span - * - * The output size will be the minimum of the input span and output span sizes. - * - * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version * @param input * @param output + * @param size */ -template -void subtract(absl::Span input, absl::Span output) noexcept +template +void subtract(const T* input, T* output, unsigned size) noexcept { - CHECK(output.size() >= input.size()); - auto* in = input.begin(); - auto* out = output.begin(); - auto* sentinel = out + min(input.size(), output.size()); - while (out < sentinel) - _internals::snippetSubtract(in, out); + const auto sentinel = output + size; + while (output < sentinel) + *output++ -= *input++; } template <> -void subtract(absl::Span input, absl::Span output) noexcept; +void subtract(const float* input, float* output, unsigned size) noexcept; + +template +void subtract(absl::Span input, absl::Span output) noexcept +{ + CHECK_SPAN_SIZES(input, output); + subtract(input.data(), output.data(), minSpanSize(input, output)); +} + +/** + * @brief Subtract a value inplace + * + * @tparam T the underlying type + * @param value + * @param output + * @param size + */ +template +void subtract(T value, T* output, unsigned size) noexcept +{ + const auto sentinel = output + size; + while (output < sentinel) + *output++ -= value; +} template <> -void subtract(const float value, absl::Span output) noexcept; +void subtract(float value, float* output, unsigned size) noexcept; + +template +void subtract(T value, absl::Span output) noexcept +{ + subtract(value, output.data(), output.size()); +} namespace _internals { template diff --git a/src/sfizz/SIMDSSE.cpp b/src/sfizz/SIMDSSE.cpp index aca877a6..0a4422e4 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -16,47 +16,6 @@ constexpr uintptr_t TypeAlignment = 4; -template <> -void sfz::subtract(absl::Span input, absl::Span output) noexcept -{ - CHECK(output.size() >= input.size()); - auto* in = input.begin(); - auto* out = output.begin(); - auto* sentinel = out + min(input.size(), output.size()); - const auto* lastAligned = prevAligned(sentinel); - - while (unaligned(in, out) && out < lastAligned) - _internals::snippetSubtract(in, out); - - while (out < lastAligned) { - _mm_store_ps(out, _mm_sub_ps(_mm_load_ps(out), _mm_load_ps(in))); - incrementAll(in, out); - } - - while (out < sentinel) - _internals::snippetSubtract(in, out); -} - -template <> -void sfz::subtract(const float value, absl::Span output) noexcept -{ - auto* out = output.begin(); - auto* sentinel = output.end(); - const auto* lastAligned = prevAligned(sentinel); - - while (unaligned(out) && out < lastAligned) - _internals::snippetSubtract(value, out); - - auto mmValue = _mm_set_ps1(value); - while (out < lastAligned) { - _mm_store_ps(out, _mm_sub_ps(_mm_load_ps(out), mmValue)); - out += TypeAlignment; - } - - while (out < sentinel) - _internals::snippetSubtract(value, out); -} - template <> void sfz::copy(absl::Span input, absl::Span output) noexcept { diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index b38774f3..5d35ce89 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -562,7 +562,7 @@ TEST_CASE("[Helpers] Subtract") std::array input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; std::array output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; std::array expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f }; - sfz::subtract(input, absl::MakeSpan(output)); + sfz::subtract(input, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -570,7 +570,8 @@ TEST_CASE("[Helpers] Subtract 2") { std::array output { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; std::array expected { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f }; - sfz::subtract(1.0f, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false); + sfz::subtract(1.0f, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -580,7 +581,8 @@ TEST_CASE("[Helpers] Subtract (SIMD)") std::array input { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f }; std::array output { 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; std::array expected { 0.0f, -1.0f, -2.0f, -3.0f, -4.0f }; - sfz::subtract(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true); + sfz::subtract(input, absl::MakeSpan(output)); REQUIRE(output == expected); } @@ -593,8 +595,10 @@ TEST_CASE("[Helpers] Subtract (SIMD vs scalar)") absl::c_fill(outputScalar, 0.0f); absl::c_fill(outputSIMD, 0.0f); - sfz::subtract(input, absl::MakeSpan(outputScalar)); - sfz::subtract(input, absl::MakeSpan(outputSIMD)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false); + sfz::subtract(input, absl::MakeSpan(outputScalar)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true); + sfz::subtract(input, absl::MakeSpan(outputSIMD)); REQUIRE(approxEqual(outputScalar, outputSIMD)); } @@ -605,8 +609,10 @@ TEST_CASE("[Helpers] Subtract 2 (SIMD vs scalar)") absl::c_iota(outputScalar, 0.0f); absl::c_iota(outputSIMD, 0.0f); - sfz::subtract(1.2f, absl::MakeSpan(outputScalar)); - sfz::subtract(1.2f, absl::MakeSpan(outputSIMD)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, false); + sfz::subtract(1.2f, absl::MakeSpan(outputScalar)); + sfz::setSIMDOpStatus(sfz::SIMDOps::subtract, true); + sfz::subtract(1.2f, absl::MakeSpan(outputSIMD)); REQUIRE(approxEqual(outputScalar, outputSIMD)); }