From 190e7085de4eea97d8bb2c1848ccc860251f53e5 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Sun, 31 May 2020 09:49:28 +0200 Subject: [PATCH] Move copy to the new format --- benchmarks/BM_copy.cpp | 12 ++++++++---- src/sfizz/SIMDHelpers.cpp | 26 ++++++++++++++++++++++++++ src/sfizz/SIMDHelpers.h | 34 ++++++++++++---------------------- src/sfizz/SIMDSSE.cpp | 21 --------------------- tests/SIMDHelpersT.cpp | 12 ++++++++---- 5 files changed, 54 insertions(+), 51 deletions(-) diff --git a/benchmarks/BM_copy.cpp b/benchmarks/BM_copy.cpp index 20d4f088..1196730b 100644 --- a/benchmarks/BM_copy.cpp +++ b/benchmarks/BM_copy.cpp @@ -43,14 +43,16 @@ BENCHMARK_DEFINE_F(CopyArray, StdCopy)(benchmark::State& state) { BENCHMARK_DEFINE_F(CopyArray, Scalar)(benchmark::State& state) { for (auto _ : state) { - sfz::copy(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, false); + sfz::copy(input, absl::MakeSpan(output)); } } BENCHMARK_DEFINE_F(CopyArray, SIMD)(benchmark::State& state) { for (auto _ : state) { - sfz::copy(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, true); + sfz::copy(input, absl::MakeSpan(output)); } } @@ -64,14 +66,16 @@ BENCHMARK_DEFINE_F(CopyArray, StdCopy_Unaligned)(benchmark::State& state) { BENCHMARK_DEFINE_F(CopyArray, Scalar_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::copy(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, false); + sfz::copy(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); } } BENCHMARK_DEFINE_F(CopyArray, SIMD_Unaligned)(benchmark::State& state) { for (auto _ : state) { - sfz::copy(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, true); + sfz::copy(absl::MakeSpan(input).subspan(1), absl::MakeSpan(output).subspan(1)); } } diff --git a/src/sfizz/SIMDHelpers.cpp b/src/sfizz/SIMDHelpers.cpp index ada8cb78..d1c61bdc 100644 --- a/src/sfizz/SIMDHelpers.cpp +++ b/src/sfizz/SIMDHelpers.cpp @@ -445,4 +445,30 @@ void subtract(float value, float* output, unsigned size) noexcept *output++ -= value; } +template <> +void copy(const float* input, float* output, unsigned size) noexcept +{ + // The sentinel is the input here + const auto sentinel = input + size; + + if (getSIMDOpStatus(SIMDOps::copy)) { +#if SFIZZ_CPU_FAMILY_X86_64 || SFIZZ_CPU_FAMILY_I386 + if (cpuInfo.has_sse()) { + const auto* lastAligned = prevAligned(sentinel); + + while (unaligned(input, output) && input < lastAligned) + *output++ = *input++; + + while (input < lastAligned) { + _mm_store_ps(output, _mm_load_ps(input)); + incrementAll<4>(input, output); + } + // fallthrough from lastAligned to sentinel + } +#endif + } + + std::copy(input, sentinel, output); +} + } diff --git a/src/sfizz/SIMDHelpers.h b/src/sfizz/SIMDHelpers.h index 29e36f33..aef54af6 100644 --- a/src/sfizz/SIMDHelpers.h +++ b/src/sfizz/SIMDHelpers.h @@ -501,39 +501,29 @@ void subtract(T value, absl::Span output) noexcept subtract(value, output.data(), output.size()); } -namespace _internals { - template - void snippetCopy(const T*& input, T*& output) - { - *output++ = *input++; - } -} - /** * @brief Copy a span in another * - * 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 copy(absl::Span input, absl::Span output) noexcept +template +void copy(const T* input, T* output, unsigned size) noexcept { - CHECK(output.size() >= input.size()); - if (output.data() == input.data() && output.size() == input.size()) - return; - auto* in = input.begin(); - auto* out = output.begin(); - auto* sentinel = out + min(input.size(), output.size()); - while (out < sentinel) - _internals::snippetCopy(in, out); + std::copy(input, input + size, output); } template <> -void copy(absl::Span input, absl::Span output) noexcept; +void copy(const float* input, float* output, unsigned size) noexcept; + +template +void copy(absl::Span input, absl::Span output) noexcept +{ + CHECK_SPAN_SIZES(input, output); + copy(input.data(), output.data(), minSpanSize(input, output)); +} namespace _internals { // Number of elements in the table, odd for equal volume at center diff --git a/src/sfizz/SIMDSSE.cpp b/src/sfizz/SIMDSSE.cpp index 0a4422e4..da6a734b 100644 --- a/src/sfizz/SIMDSSE.cpp +++ b/src/sfizz/SIMDSSE.cpp @@ -16,27 +16,6 @@ constexpr uintptr_t TypeAlignment = 4; -template <> -void sfz::copy(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::snippetCopy(in, out); - - while (out < lastAligned) { - _mm_store_ps(out, _mm_load_ps(in)); - incrementAll(in, out); - } - - while (out < sentinel) - _internals::snippetCopy(in, out); -} - template <> void sfz::pan(absl::Span panEnvelope, absl::Span leftBuffer, absl::Span rightBuffer) noexcept { diff --git a/tests/SIMDHelpersT.cpp b/tests/SIMDHelpersT.cpp index 5d35ce89..d4d3c437 100644 --- a/tests/SIMDHelpersT.cpp +++ b/tests/SIMDHelpersT.cpp @@ -620,7 +620,8 @@ TEST_CASE("[Helpers] copy") { 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 }; - sfz::copy(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, false); + sfz::copy(input, absl::MakeSpan(output)); REQUIRE(output == input); } @@ -628,7 +629,8 @@ TEST_CASE("[Helpers] copy (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 }; - sfz::copy(input, absl::MakeSpan(output)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, true); + sfz::copy(input, absl::MakeSpan(output)); REQUIRE(output == input); } @@ -641,8 +643,10 @@ TEST_CASE("[Helpers] copy (SIMD vs scalar)") absl::c_fill(outputScalar, 0.0f); absl::c_fill(outputSIMD, 0.0f); - sfz::copy(input, absl::MakeSpan(outputScalar)); - sfz::copy(input, absl::MakeSpan(outputSIMD)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, false); + sfz::copy(input, absl::MakeSpan(outputScalar)); + sfz::setSIMDOpStatus(sfz::SIMDOps::copy, true); + sfz::copy(input, absl::MakeSpan(outputSIMD)); REQUIRE(approxEqual(outputScalar, outputSIMD)); }