Skip to content

Commit

Permalink
New Simd namespace for compile-time and runtime CPU feature dispatch.
Browse files Browse the repository at this point in the history
ONCE AGAIN the CPU feature detection code has comment:code ratio 1000:1.
What a mess.
  • Loading branch information
mosra committed Mar 17, 2021
1 parent 9c8e07f commit 4ac3be9
Show file tree
Hide file tree
Showing 9 changed files with 1,352 additions and 4 deletions.
3 changes: 3 additions & 0 deletions doc/corrade-changelog.dox
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ namespace Corrade {
and @ref CORRADE_TARGET_SIMD128 preprocessor variables added to the already
existing @ref CORRADE_TARGET_SSE2 for detecting enabled instruction sets on
x86, ARM and WebAssembly
- New @ref Simd namespace that provides basic building blocks for
compile-time and runtime CPU feature detection and dispatch on x86, ARM and
WebAssembly

@subsubsection corrade-changelog-latest-new-containers Containers library

Expand Down
1 change: 1 addition & 0 deletions doc/snippets/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ set_directory_properties(PROPERTIES
add_library(snippets STATIC
Containers.cpp
Containers-stl.cpp
Corrade.cpp
Utility.cpp)
target_link_libraries(snippets PRIVATE CorradeUtility)
set_target_properties(snippets PROPERTIES FOLDER "Corrade/doc/snippets")
Expand Down
90 changes: 90 additions & 0 deletions doc/snippets/Corrade.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
This file is part of Corrade.
Copyright © 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016,
2017, 2018, 2019, 2020, 2021
Vladimír Vondruš <[email protected]>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

#include "Corrade/Simd.h"
#include "Corrade/Containers/ArrayView.h"

using namespace Corrade;

#define DOXYGEN_IGNORE(...) __VA_ARGS__

#ifdef CORRADE_TARGET_X86
/* [Simd-compile-time-declare] */
void transformData(Simd::ScalarT, Containers::ArrayView<float> data);
void transformData(Simd::Sse41T, Containers::ArrayView<float> data);
void transformData(Simd::Avx2T, Containers::ArrayView<float> data);
/* [Simd-compile-time-declare] */

void transformData(Simd::Features features, Containers::ArrayView<float> data);
/* [Simd-runtime-dispatch] */
void transformData(Simd::Features features, Containers::ArrayView<float> data) {
if(features & Simd::Avx2) transformData(Simd::Avx2, data);
else if(features & Simd::Sse41) transformData(Simd::Sse41, data);
else transformData(Simd::Scalar, data);
}
/* [Simd-runtime-dispatch] */
#endif

void foo();
void foo() {

#ifdef CORRADE_TARGET_X86
{
Containers::ArrayView<float> data, another;
/* [Simd-compile-time-use] */
/* Calls the Scalar implementation because there's nothing better for SSE3 */
transformData(Simd::Sse3, data);

/* Calls the AVX2 implementation if CORRADE_TARGET_AVX2 is defined, or the
SSE4.1 one if either CORRADE_TARGET_SSE41 or CORRADE_TARGET_SSE42 is
defined, falls back to scalar otherwise */
transformData(Simd::Default, another);
/* [Simd-compile-time-use] */
}

{
Containers::ArrayView<float> data;
/* [Simd-runtime-use] */
transformData(Simd::Features{}, data);
/* [Simd-runtime-use] */
}

{
Containers::ArrayView<float> data;
/* [Simd-runtime-cache] */
/* Don't want the AVX2 implementation as it's weirdly slow, OTOH this processor
supports SSE4a so we can use the SSE4.1 implementation even though it isn't
autodetected */
Simd::Features features;
features &= ~Simd::Avx2;
features |= Simd::Sse41;

transformData(features, data);
/* [Simd-runtime-cache] */
}
#endif

}
15 changes: 12 additions & 3 deletions src/Corrade/Corrade.h
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ doesn't know about yet.
@see @ref CORRADE_TARGET_SSE2, @ref CORRADE_TARGET_SSE3,
@ref CORRADE_TARGET_SSSE3, @ref CORRADE_TARGET_SSE41,
@ref CORRADE_TARGET_SSE42, @ref CORRADE_TARGET_AVX,
@ref CORRADE_TARGET_AVX2
@ref CORRADE_TARGET_AVX2, @relativeref{Corrade,Simd}
*/
#define CORRADE_TARGET_X86
#undef CORRADE_TARGET_X86
Expand All @@ -265,7 +265,7 @@ multi-architecture binaries. If neither @ref CORRADE_TARGET_X86,
@ref CORRADE_TARGET_WASM is defined, the platform might be either a very old
pre-WebAssembly @ref CORRADE_TARGET_EMSCRIPTEN or any other that the library
doesn't know about yet.
@see @ref CORRADE_TARGET_NEON
@see @ref CORRADE_TARGET_NEON, @relativeref{Corrade,Simd}
*/
#define CORRADE_TARGET_ARM
#undef CORRADE_TARGET_ARM
Expand Down Expand Up @@ -303,7 +303,7 @@ multi-architecture binaries. If neither @ref CORRADE_TARGET_X86,
@ref CORRADE_TARGET_WASM is defined, the platform might be either a very old
pre-WebAssembly @ref CORRADE_TARGET_EMSCRIPTEN or any other that the library
doesn't know about yet.
@see @ref CORRADE_TARGET_SIMD128
@see @ref CORRADE_TARGET_SIMD128, @relativeref{Corrade,Simd}
*/
#define CORRADE_TARGET_WASM
#undef CORRADE_TARGET_WASM
Expand Down Expand Up @@ -488,6 +488,7 @@ Defined on @ref CORRADE_TARGET_X86 "x86" if
[Streaming SIMD Extensions 2](https://en.wikipedia.org/wiki/SSE2) are enabled
at compile time (`-msse2` or higher on GCC/Clang, `/arch:SSE2` or higher on
MSVC). All x86-64 targets support SSE2. Implied by @ref CORRADE_TARGET_SSE3.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Sse2}
*/
#define CORRADE_TARGET_SSE2
#undef CORRADE_TARGET_SSE2
Expand All @@ -501,6 +502,7 @@ Defined on @ref CORRADE_TARGET_X86 "x86" if
at compile time (on GCC/Clang it's `-msse3` and higher, MSVC doesn't have a
direct option and it's only implied by `/arch:AVX`). Superset of
@ref CORRADE_TARGET_SSE2, implied by @ref CORRADE_TARGET_SSSE3.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Sse3}
*/
#define CORRADE_TARGET_SSE3
#undef CORRADE_TARGET_SSE3
Expand All @@ -519,6 +521,7 @@ Note that certain older AMD processors have [SSE4a](https://en.wikipedia.org/wik
but neither SSSE3 nor SSE4.1. Both can be however treated as a subset of SSE4.1
to a large extent, and it's recommended to use @ref CORRADE_TARGET_SSE41 to
detect those.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Ssse3}
*/
#define CORRADE_TARGET_SSSE3
#undef CORRADE_TARGET_SSSE3
Expand All @@ -537,6 +540,7 @@ Note that certain older AMD processors have [SSE4a](https://en.wikipedia.org/wik
but neither SSSE3 nor SSE4.1. Both can be however treated as a subset of SSE4.1
to a large extent, and it's recommended to use @ref CORRADE_TARGET_SSE41 to
detect those.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Sse41}
*/
#define CORRADE_TARGET_SSE41
#undef CORRADE_TARGET_SSE41
Expand All @@ -550,6 +554,7 @@ Defined on @ref CORRADE_TARGET_X86 "x86" if
are enabled at compile time (on GCC/Clang it's `-msse4.2` and higher, MSVC
doesn't have a direct option and it's only implied by `/arch:AVX`). Superset of
@ref CORRADE_TARGET_SSE41, implied by @ref CORRADE_TARGET_AVX.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Sse42}
*/
#define CORRADE_TARGET_SSE42
#undef CORRADE_TARGET_SSE42
Expand All @@ -563,6 +568,7 @@ Defined on @ref CORRADE_TARGET_X86 "x86" if
are enabled at compile time (`-mavx` and higher on GCC/Clang, `/arch:AVX` on
MSVC). Superset of @ref CORRADE_TARGET_SSE42, implied by
@ref CORRADE_TARGET_AVX2.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Avx}
*/
#define CORRADE_TARGET_AVX
#undef CORRADE_TARGET_AVX
Expand All @@ -575,6 +581,7 @@ Defined on @ref CORRADE_TARGET_X86 "x86" if
[Advanced Vector Extensions 2](https://en.wikipedia.org/wiki/Advanced_Vector_Extensions#Advanced_Vector_Extensions_2)
are enabled at compile time (`-mavx2` and higher on GCC/Clang, `/arch:AVX2` on
MSVC). Superset of @ref CORRADE_TARGET_AVX.
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Avx2}
*/
#define CORRADE_TARGET_AVX2
#undef CORRADE_TARGET_AVX2
Expand All @@ -587,6 +594,7 @@ Defined on @ref CORRADE_TARGET_ARM "ARM" if
[ARM NEON](https://en.wikipedia.org/wiki/ARM_architecture#Advanced_SIMD_(Neon))
instructions are enabled at compile time (`-mfpu=neon` on GCC/Clang, implicitly
supported on AArch64).
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Neon}
*/
#define CORRADE_TARGET_NEON
#undef CORRADE_TARGET_NEON
Expand All @@ -598,6 +606,7 @@ supported on AArch64).
Defined on @ref CORRADE_TARGET_WASM "WebAssembly" if
[128-bit SIMD](https://github.com/webassembly/simd) instructions are enabled at
compile time (`-msimd128` passed to Clang).
@see @relativeref{Corrade,Simd}, @relativeref{Corrade,Simd::Simd128}
*/
#define CORRADE_TARGET_SIMD128
#undef CORRADE_TARGET_SIMD128
Expand Down
Loading

0 comments on commit 4ac3be9

Please sign in to comment.