From 3a320914a54ea0cdb37fa194d5a6fae4e14e4f94 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Mon, 9 Dec 2019 19:22:50 +0100 Subject: [PATCH] Added a divide SIMD helper --- src/sfizz/Config.h | 1 + src/sfizz/SIMDDummy.cpp | 8 ++++++- src/sfizz/SIMDHelpers.h | 50 +++++++++++++++++++++++++++++++++++++++++ src/sfizz/SIMDSSE.cpp | 27 +++++++++++++++++++++- 4 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/sfizz/Config.h b/src/sfizz/Config.h index 346154f8..332b6ea6 100644 --- a/src/sfizz/Config.h +++ b/src/sfizz/Config.h @@ -58,6 +58,7 @@ namespace SIMDConfig { constexpr bool readInterleaved { true }; constexpr bool fill { true }; constexpr bool gain { false }; + constexpr bool divide { false }; constexpr bool mathfuns { false }; constexpr bool loopingSFZIndex { true }; constexpr bool saturatingSFZIndex { true }; diff --git a/src/sfizz/SIMDDummy.cpp b/src/sfizz/SIMDDummy.cpp index f1409339..75cbb77f 100644 --- a/src/sfizz/SIMDDummy.cpp +++ b/src/sfizz/SIMDDummy.cpp @@ -77,6 +77,12 @@ void sfz::applyGain(absl::Span gain, absl::Span(gain, input, output); } +template <> +void sfz::divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept +{ + divide(input, divisor, output); +} + template <> void sfz::multiplyAdd(absl::Span gain, absl::Span input, absl::Span output) noexcept { @@ -173,4 +179,4 @@ template <> void sfz::diff(absl::Span input, absl::Span output) noexcept { diff(input, output); -} \ No newline at end of file +} diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 33b8c8ab..bd03ea93 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -457,6 +457,56 @@ void applyGain(float gain, absl::Span input, absl::Spa template <> void applyGain(absl::Span gain, absl::Span input, absl::Span output) noexcept; +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 + */ +template +void divide(absl::Span input, absl::Span divisor, absl::Span output) noexcept +{ + ASSERT(divisor.size() == input.size()); + ASSERT(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); +} + +/** + * @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 +void divide(absl::Span output, absl::Span divisor) noexcept +{ + divide(output, 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 253cde36..50b527bb 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -305,6 +305,31 @@ void sfz::applyGain(absl::Span gain, absl::Span(g, in, out); } + +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))); + div += TypeAlignment; + in += TypeAlignment; + out += TypeAlignment; + } + + while (out < output.end()) + _internals::snippetDivSpan(in, div, out); +} + + template <> void sfz::multiplyAdd(absl::Span gain, absl::Span input, absl::Span output) noexcept { @@ -809,4 +834,4 @@ void sfz::diff(absl::Span input, absl::Span out while (in < sentinel) _internals::snippetDiff(in, out); -} \ No newline at end of file +}