From 1b68331f385e4df3ffa91cab0ae87b5588ed6aea Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sat, 30 May 2020 22:26:35 +0200 Subject: [PATCH] Moved divide to the new format --- benchmarks/BM_divide.cpp | 8 +++---- src/sfizz/SIMDHelpers.cpp | 26 ++++++++++++++++++++++ src/sfizz/SIMDHelpers.h | 45 +++++++++++++++++---------------------- src/sfizz/SIMDSSE.cpp | 24 --------------------- 4 files changed, 49 insertions(+), 54 deletions(-) diff --git a/benchmarks/BM_divide.cpp b/benchmarks/BM_divide.cpp index b4fed561..770fac78 100644 --- a/benchmarks/BM_divide.cpp +++ b/benchmarks/BM_divide.cpp @@ -46,28 +46,28 @@ BENCHMARK_DEFINE_F(Divide, Straight)(benchmark::State& state) { BENCHMARK_DEFINE_F(Divide, Scalar)(benchmark::State& state) { for (auto _ : state) { - sfz::divide(input, divisor, absl::MakeSpan(output)); + sfz::divide(input, divisor, absl::MakeSpan(output)); } } BENCHMARK_DEFINE_F(Divide, SIMD)(benchmark::State& state) { for (auto _ : state) { - sfz::divide(input, divisor, absl::MakeSpan(output)); + sfz::divide(input, divisor, absl::MakeSpan(output)); } } BENCHMARK_DEFINE_F(Divide, Scalar_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::divide(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::divide(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); } } BENCHMARK_DEFINE_F(Divide, SIMD_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::divide(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::divide(absl::MakeSpan(input).subspan(1), absl::MakeSpan(divisor).subspan(1), absl::MakeSpan(output).subspan(1)); } } diff --git a/src/sfizz/SIMDHelpers.cpp b/src/sfizz/SIMDHelpers.cpp index a186280a..3aba1f84 100644 --- a/src/sfizz/SIMDHelpers.cpp +++ b/src/sfizz/SIMDHelpers.cpp @@ -188,4 +188,30 @@ void applyGain(const float* gain, const float* input, float* output, unsi *output++ = (*gain++) * (*input++); } +template <> +void sfz::divide(const float* input, const float* divisor, float* output, unsigned size) noexcept +{ + const auto sentinel = output + size; + + if (getSIMDOpStatus(SIMDOps::divide)) { +#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++) / (*divisor++); + + while (output < lastAligned) { + _mm_store_ps(output, _mm_div_ps(_mm_load_ps(input), _mm_load_ps(divisor))); + incrementAll<4>(divisor, input, output); + } + // fallthrough from lastAligned to sentinel + } +#endif + } + + while (output < sentinel) + *output++ = (*input++) / (*divisor++); +} + } diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index b93f3123..8a722109 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -242,56 +242,49 @@ inline void applyGain(absl::Span gain, absl::Span array) noexcept applyGain(gain.data(), array.data(), array.data(), minSpanSize(gain, array)); } -namespace _internals { - template - inline void snippetDivSpan(const T*& input, const T*& divisor,T*& output) - { - *output++ = (*input++) / (*divisor++); - } -} - /** * @brief Divide a vector by another vector * * The output size will be the minimum of the divisor, input span and output span size. * * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version * @param input * @param divisor * @param output + * @param size */ -template -void divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept +template +void divide(const T* input, const T* divisor, T* output, unsigned size) noexcept { - CHECK(divisor.size() == input.size()); - CHECK(input.size() <= output.size()); - auto* in = input.begin(); - auto* d = divisor.begin(); - auto* out = output.begin(); - auto* sentinel = out + std::min(divisor.size(), std::min(output.size(), input.size())); - while (out < sentinel) - _internals::snippetDivSpan(in, d, out); + const auto sentinel = output + size; + while (output < sentinel) + *output++ = (*input++) / (*divisor++); +} + +template <> +void divide(const float* input, const float* divisor, float* output, unsigned size) noexcept; + +template +inline void divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept +{ + CHECK_SPAN_SIZES(input, divisor, output); + divide(input.data(), divisor.data(), output.data(), minSpanSize(input, divisor, output)); } /** * @brief Divide a vector by another in place * * @tparam T the underlying type - * @tparam SIMD use the SIMD version or the scalar version * @param output * @param divisor */ -template +template void divide(absl::Span output, absl::Span divisor) noexcept { - divide(output, divisor, output); + CHECK_SPAN_SIZES(divisor, output); + divide(output.data(), divisor.data(), output.data(), minSpanSize(divisor, output)); } -template <> -void divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept; - - namespace _internals { template inline void snippetMultiplyAdd(const T*& gain, const T*& input, T*& output) diff --git a/src/sfizz/SIMDSSE.cpp b/src/sfizz/SIMDSSE.cpp index 5b893b80..0f4a807c 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -16,30 +16,6 @@ constexpr uintptr_t TypeAlignment = 4; - - -template <> -void sfz::divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept -{ - auto* in = input.begin(); - auto* out = output.begin(); - auto* div = divisor.begin(); - const auto size = std::min(output.size(), std::min(input.size(), divisor.size())); - const auto* lastAligned = prevAligned(output.begin() + size); - - while (unaligned(out, in, div) && out < lastAligned) - _internals::snippetDivSpan(in, div, out); - - while (out < lastAligned) { - _mm_store_ps(out, _mm_div_ps(_mm_load_ps(in), _mm_load_ps(div))); - incrementAll(in, div, out); - } - - while (out < output.end()) - _internals::snippetDivSpan(in, div, out); -} - - template <> void sfz::multiplyAdd(absl::Span gain, absl::Span input, absl::Span output) noexcept {