diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2020-06-20 16:59:59 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2020-06-24 08:47:30 +0200 |
commit | 7ee6fa6487f01271c4374e4c260466b5041afe72 (patch) | |
tree | ade1cbf020229c04d8d859cb9ee9ebf583e31ed8 | |
parent | 240758a972eb99dd4d26fa6040ff0b6614036621 (diff) |
Add test as an example how to add CPU intrinsics support
Also makes sure that if the CPU dataction or compiler detection
doesn't work correctly, the test could potentially crash.
Change-Id: If0862c0a736c8e1f5ba1117b248918e4c1fb2f4d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/96779
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r-- | include/tools/simdsupport.hxx | 21 | ||||
-rw-r--r-- | tools/CppunitTest_tools_test.mk | 12 | ||||
-rw-r--r-- | tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx | 75 | ||||
-rw-r--r-- | tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx | 58 | ||||
-rw-r--r-- | tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx | 58 |
5 files changed, 214 insertions, 10 deletions
diff --git a/include/tools/simdsupport.hxx b/include/tools/simdsupport.hxx index 4ef7a698089e..5d10d53d48ad 100644 --- a/include/tools/simdsupport.hxx +++ b/include/tools/simdsupport.hxx @@ -14,6 +14,8 @@ // code using intrinsics or not. So we have to (re)set them again // every time this file has been included. +// In other words... DO NOT ADD "#pragma once" here + #undef LO_SSE2_AVAILABLE #undef LO_SSSE3_AVAILABLE #undef LO_AVX_AVAILABLE @@ -24,49 +26,48 @@ // SSE2 is required for X64 #if (defined(_M_X64) || defined(_M_IX86_FP) && _M_IX86_FP >= 2) #define LO_SSE2_AVAILABLE +#include <intrin.h> #endif // end SSE2 // compiled with /arch:AVX #if defined(__AVX__) #ifndef LO_SSE2_AVAILABLE #define LO_SSE2_AVAILABLE +#include <intrin.h> #endif #define LO_SSSE3_AVAILABLE #define LO_AVX_AVAILABLE -#endif // defined(__AVX__) +#include <immintrin.h> +#endif // end defined(__AVX__) // compiled with /arch:AVX2 #if defined(__AVX2__) #define LO_AVX2_AVAILABLE +#include <immintrin.h> #endif // defined(__AVX2__) #else // compiler Clang and GCC #if defined(__SSE2__) || defined(__x86_64__) // SSE2 is required for X64 #define LO_SSE2_AVAILABLE +#include <emmintrin.h> #endif // defined(__SSE2__) #if defined(__SSSE3__) #define LO_SSSE3_AVAILABLE +#include <tmmintrin.h> #endif // defined(__SSSE3__) #if defined(__AVX__) #define LO_AVX_AVAILABLE +#include <immintrin.h> #endif // defined(__AVX__) #if defined(__AVX2__) #define LO_AVX2_AVAILABLE +#include <immintrin.h> #endif // defined(__AVX2__) #endif // end compiler Clang and GCC -// If we detect any SIMD intrinsics, include the headers automatically -#if defined(LO_SSE2_AVAILABLE) -#include <emmintrin.h> -#elif defined(LO_SSSE3_AVAILABLE) -#include <tmmintrin.h> -#elif defined(LO_AVX_AVAILABLE) || defined(LO_AVX2_AVAILABLE) -#include <immintrin.h> -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk index 46a6cf5242cd..aa5ac4606d02 100644 --- a/tools/CppunitTest_tools_test.mk +++ b/tools/CppunitTest_tools_test.mk @@ -34,6 +34,18 @@ $(eval $(call gb_CppunitTest_add_exception_objects,tools_test, \ tools/qa/cppunit/test_cpuid \ )) +$(eval $(call gb_CppunitTest_add_exception_objects,tools_test,\ + tools/qa/cppunit/test_cpu_runtime_detection_AVX2, $(CXXFLAGS_INTRINSICS_AVX2) \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,tools_test,\ + tools/qa/cppunit/test_cpu_runtime_detection_SSE2, $(CXXFLAGS_INTRINSICS_SSE2) \ +)) + +$(eval $(call gb_CppunitTest_add_exception_objects,tools_test,\ + tools/qa/cppunit/test_cpu_runtime_detection_SSSE3, $(CXXFLAGS_INTRINSICS_SSSE3) \ +)) + $(eval $(call gb_CppunitTest_use_sdk_api,tools_test)) $(eval $(call gb_CppunitTest_use_libraries,tools_test, \ diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx new file mode 100644 index 000000000000..0c98f2fc8c98 --- /dev/null +++ b/tools/qa/cppunit/test_cpu_runtime_detection_AVX2.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <tools/simdsupport.hxx> + +#ifdef LO_AVX2_AVAILABLE + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <tools/cpuid.hxx> + +namespace +{ +class CpuRuntimeDetection_AVX2 : public CppUnit::TestFixture +{ +public: + void checkAVX2(); + void testCpuRuntimeDetection(); + + CPPUNIT_TEST_SUITE(CpuRuntimeDetection_AVX2); + CPPUNIT_TEST(testCpuRuntimeDetection); + CPPUNIT_TEST_SUITE_END(); +}; + +void CpuRuntimeDetection_AVX2::testCpuRuntimeDetection() +{ + // can only run if this function if CPU supports AVX2 + if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::AVX2)) + checkAVX2(); +} + +void CpuRuntimeDetection_AVX2::checkAVX2() +{ + __m256i a = _mm256_set_epi64x(1, 4, 8, 3); + __m256i b = _mm256_set_epi64x(2, 1, 1, 5); + __m256i c = _mm256_xor_si256(a, b); + + sal_Int64 values[4]; + _mm256_storeu_si256(reinterpret_cast<__m256i*>(&values), c); + + CPPUNIT_ASSERT_EQUAL(sal_Int64(6), values[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(9), values[1]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(5), values[2]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(3), values[3]); + + __m256i d = _mm256_set_epi64x(3, 5, 1, 0); + + __m256i result = _mm256_cmpeq_epi64(d, c); + + // Compare equals + sal_Int64 compare[4]; + _mm256_storeu_si256(reinterpret_cast<__m256i*>(&compare), result); + + CPPUNIT_ASSERT_EQUAL(sal_Int64(0), compare[0]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(0), compare[1]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(-1), compare[2]); + CPPUNIT_ASSERT_EQUAL(sal_Int64(-1), compare[3]); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CpuRuntimeDetection_AVX2); + +} // end anonymous namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx new file mode 100644 index 000000000000..13dd48d2176e --- /dev/null +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSE2.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <tools/simdsupport.hxx> + +#ifdef LO_SSE2_AVAILABLE + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <tools/cpuid.hxx> + +namespace +{ +class CpuRuntimeDetection_SSE2 : public CppUnit::TestFixture +{ +public: + void checkSSE2(); + void testCpuRuntimeDetection(); + + CPPUNIT_TEST_SUITE(CpuRuntimeDetection_SSE2); + CPPUNIT_TEST(testCpuRuntimeDetection); + CPPUNIT_TEST_SUITE_END(); +}; + +void CpuRuntimeDetection_SSE2::testCpuRuntimeDetection() +{ + // can only run if this function if CPU supports SSE2 + if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSE2)) + checkSSE2(); +} + +void CpuRuntimeDetection_SSE2::checkSSE2() +{ + // Try some SSE2 intrinsics calcualtion + __m128i a = _mm_set1_epi32(15); + __m128i b = _mm_set1_epi32(15); + __m128i c = _mm_xor_si128(a, b); + + // Check zero + CPPUNIT_ASSERT_EQUAL(0xFFFF, _mm_movemask_epi8(_mm_cmpeq_epi32(c, _mm_setzero_si128()))); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CpuRuntimeDetection_SSE2); + +} // end anonymous namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx new file mode 100644 index 000000000000..1d730d99e985 --- /dev/null +++ b/tools/qa/cppunit/test_cpu_runtime_detection_SSSE3.cxx @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <tools/simdsupport.hxx> + +#ifdef LO_SSSE3_AVAILABLE + +#include <cppunit/TestAssert.h> +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <tools/cpuid.hxx> + +namespace +{ +class CpuRuntimeDetection_SSSE3 : public CppUnit::TestFixture +{ +public: + void checkSSSE3(); + void testCpuRuntimeDetection(); + + CPPUNIT_TEST_SUITE(CpuRuntimeDetection_SSSE3); + CPPUNIT_TEST(testCpuRuntimeDetection); + CPPUNIT_TEST_SUITE_END(); +}; + +void CpuRuntimeDetection_SSSE3::testCpuRuntimeDetection() +{ + // can only run if this function if CPU supports SSSE3 + if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSSE3)) + checkSSSE3(); +} + +void CpuRuntimeDetection_SSSE3::checkSSSE3() +{ + // Try some SSSE3 intrinsics calcualtion + __m128i a = _mm_set1_epi32(3); + __m128i b = _mm_set1_epi32(3); + __m128i c = _mm_maddubs_epi16(a, b); + + // Check result is 9 + CPPUNIT_ASSERT_EQUAL(0xFFFF, _mm_movemask_epi8(_mm_cmpeq_epi32(c, _mm_set1_epi32(9)))); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(CpuRuntimeDetection_SSSE3); + +} // end anonymous namespace + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |