summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2017-05-08 10:47:04 +0200
committerTomaž Vajngerl <quikee@gmail.com>2019-07-09 02:46:43 +0200
commitf43f9b99603736a4d54f550052509eb5f4d04b45 (patch)
tree96f8e17bc271471d54571d6ffce7146b6bcdb626
parentf65905dd0ff464774f338db44d69925f98e1766c (diff)
CPU intrinsics detection (SSE, AVX)
Adds CPU intrinsics detection in configure pass for compile time detection and "cpuid" runtime detection of which CPU instruction sets are available on the user device. Change-Id: I0ee4d0b22a7c51f72796d43e7383a31d03b437ad Reviewed-on: https://gerrit.libreoffice.org/75175 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--config_host.mk.in1
-rw-r--r--configure.ac102
-rw-r--r--include/tools/cpuid.hxx71
-rw-r--r--include/tools/simd.hxx30
-rw-r--r--include/tools/simdsupport.hxx62
-rw-r--r--sc/source/core/data/formulacell.cxx2
-rw-r--r--sc/source/core/inc/arraysumfunctor.hxx15
-rw-r--r--tools/CppunitTest_tools_test.mk4
-rw-r--r--tools/qa/cppunit/test_cpuid.cxx74
-rw-r--r--tools/source/misc/cpuid.cxx119
10 files changed, 434 insertions, 46 deletions
diff --git a/config_host.mk.in b/config_host.mk.in
index 5c7038211a11..9bde2ff2a214 100644
--- a/config_host.mk.in
+++ b/config_host.mk.in
@@ -648,6 +648,7 @@ export ZLIB_LIBS=$(gb_SPACE)@ZLIB_LIBS@
export ZMF_CFLAGS=$(gb_SPACE)@ZMF_CFLAGS@
export ZMF_LIBS=$(gb_SPACE)@ZMF_LIBS@
export USE_AVMEDIA_DUMMY=@USE_AVMEDIA_DUMMY@
+export INTRINSICS_CXXFLAGS=@INTRINSICS_CXXFLAGS@
# lang-related stuff
include $(BUILDDIR)/config_$(gb_Side)_lang.mk
diff --git a/configure.ac b/configure.ac
index ba079753729f..b9785d895366 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6748,6 +6748,108 @@ fi
AC_SUBST([HAVE_BROKEN_GCC_WMAYBE_UNINITIALIZED])
dnl ===================================================================
+dnl CPU Intrinsincs support - SSE, AVX
+dnl ===================================================================
+
+INTRINSICS_CXXFLAGS=""
+
+if test "$GCC" = "yes"; then
+ AC_MSG_CHECKING([whether $CXX can compile SSE2 intrinsics])
+ AC_LANG_PUSH([C++])
+ save_CXXFLAGS=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -msse2"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ #include <x86intrin.h>
+ int main () {
+ volatile __m128i a = _mm_set1_epi32 (0), b = _mm_set1_epi32 (0), c;
+ c = _mm_xor_si128 (a, b);
+ return 0;
+ }
+ ])],
+ [can_compile_sse2=yes],
+ [can_compile_sse2=no])
+ AC_LANG_POP([C++])
+ CXXFLAGS=$save_CXXFLAGS
+ AC_MSG_RESULT([${can_compile_sse2}])
+ if test "${can_compile_sse2}" = "yes" ; then
+ INTRINSICS_CXXFLAGS="-msse2"
+ else
+ AC_MSG_WARN([cannot compile SSE2 intrinsics])
+ fi
+
+ AC_MSG_CHECKING([whether $CXX can compile SSSE3 intrinsics])
+ AC_LANG_PUSH([C++])
+ save_CXXFLAGS=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -mssse3"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ #include <x86intrin.h>
+ int main () {
+ volatile __m128i a = _mm_set1_epi32 (0), b = _mm_set1_epi32 (0), c;
+ c = _mm_maddubs_epi16 (a, b);
+ return 0;
+ }
+ ])],
+ [can_compile_ssse3=yes],
+ [can_compile_ssse3=no])
+ AC_LANG_POP([C++])
+ CXXFLAGS=$save_CXXFLAGS
+ AC_MSG_RESULT([${can_compile_ssse3}])
+ if test "${can_compile_ssse3}" = "yes" ; then
+ INTRINSICS_CXXFLAGS="-mssse3"
+ else
+ AC_MSG_WARN([cannot compile SSSE3 intrinsics])
+ fi
+
+ AC_MSG_CHECKING([whether $CXX can compile AVX intrinsics])
+ AC_LANG_PUSH([C++])
+ save_CXXFLAGS=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -mavx"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ #include <x86intrin.h>
+ int main () {
+ volatile __m256 a = _mm256_set1_ps (0.0f), b = _mm256_set1_ps (0.0f), c;
+ c = _mm256_xor_ps(a, b);
+ return 0;
+ }
+ ])],
+ [can_compile_avx=yes],
+ [can_compile_avx=no])
+ AC_LANG_POP([C++])
+ CXXFLAGS=$save_CXXFLAGS
+ AC_MSG_RESULT([${can_compile_avx}])
+ if test "${can_compile_avx}" = "yes" ; then
+ INTRINSICS_CXXFLAGS="-mavx"
+ else
+ AC_MSG_WARN([cannot compile AVX intrinsics])
+ fi
+
+ AC_MSG_CHECKING([whether $CXX can compile AVX2 intrinsics])
+ AC_LANG_PUSH([C++])
+ save_CXXFLAGS=$CXXFLAGS
+ CXXFLAGS="$CXXFLAGS -mavx2"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
+ #include <x86intrin.h>
+ int main () {
+ volatile __m256i a = _mm256_set1_epi32 (0), b = _mm256_set1_epi32 (0), c;
+ c = _mm256_maddubs_epi16(a, b);
+ return 0;
+ }
+ ])],
+ [can_compile_avx2=yes],
+ [can_compile_avx2=no])
+ AC_LANG_POP([C++])
+ CXXFLAGS=$save_CXXFLAGS
+ AC_MSG_RESULT([${can_compile_avx2}])
+ if test "${can_compile_avx2}" = "yes" ; then
+ INTRINSICS_CXXFLAGS="-mavx2"
+ else
+ AC_MSG_WARN([cannot compile AVX2 intrinsics])
+ fi
+fi
+
+AC_SUBST([INTRINSICS_CXXFLAGS])
+
+dnl ===================================================================
dnl system stl sanity tests
dnl ===================================================================
if test "$_os" != "WINNT"; then
diff --git a/include/tools/cpuid.hxx b/include/tools/cpuid.hxx
index 419d05714ae4..27e9987398e4 100644
--- a/include/tools/cpuid.hxx
+++ b/include/tools/cpuid.hxx
@@ -13,22 +13,73 @@
#include <sal/config.h>
#include <tools/toolsdllapi.h>
+#include <o3tl/typed_flags_set.hxx>
+#include <rtl/ustring.hxx>
-#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) && defined(__SSE2__)
-#define LO_SSE2_AVAILABLE 1
-#elif defined(_MSC_VER)
-#define LO_SSE2_AVAILABLE 1
-#endif
+namespace cpuid {
-namespace tools
+enum class InstructionSetFlags
{
-namespace cpuid
+ NONE = 0x00,
+ HYPER = 0x01,
+ SSE2 = 0x02,
+ SSSE3 = 0x04,
+ SSE41 = 0x08,
+ SSE42 = 0x10,
+ AVX = 0x20,
+ AVX2 = 0x40
+};
+
+} // end cpuid
+
+namespace o3tl {
+ template<> struct typed_flags<cpuid::InstructionSetFlags> : is_typed_flags<cpuid::InstructionSetFlags, 0x07f> {};
+}
+
+namespace cpuid {
+
+/** Get supported instruction set flags determined at runtime by probing the CPU.
+ */
+TOOLS_DLLPUBLIC InstructionSetFlags getCpuInstructionSetFlags();
+
+/** Check if a certain instruction set is supported by the CPU at runtime.
+ */
+TOOLS_DLLPUBLIC bool isCpuInstructionSetSupported(InstructionSetFlags eInstructions);
+
+/** Returns a string of supported instructions.
+ */
+TOOLS_DLLPUBLIC OUString instructionSetSupportedString();
+
+/** Check if SSE2 is supported by the CPU
+ */
+inline bool hasSSE2()
{
- TOOLS_DLLPUBLIC bool hasSSE2();
- TOOLS_DLLPUBLIC bool hasHyperThreading();
+ return isCpuInstructionSetSupported(InstructionSetFlags::SSE2);
}
+
+/** Check if SSSE3 is supported by the CPU
+ */
+inline bool hasSSSE3()
+{
+ return isCpuInstructionSetSupported(InstructionSetFlags::SSSE3);
+}
+
+/** Check if AVX2 is supported by the CPU
+ */
+inline bool hasAVX2()
+{
+ return isCpuInstructionSetSupported(InstructionSetFlags::AVX2);
+}
+
+/** Check if Hyper Threading is supported
+ */
+inline bool hasHyperThreading()
+{
+ return isCpuInstructionSetSupported(InstructionSetFlags::HYPER);
}
-#endif
+} // end cpuid
+
+#endif // INCLUDED_TOOLS_CPUID_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/tools/simd.hxx b/include/tools/simd.hxx
new file mode 100644
index 000000000000..bdfdb8928271
--- /dev/null
+++ b/include/tools/simd.hxx
@@ -0,0 +1,30 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_TOOLS_SIMD_HXX
+#define INCLUDED_TOOLS_SIMD_HXX
+
+namespace simd
+{
+template <typename T, unsigned int N> inline bool isAligned(const T* pointer)
+{
+ return 0 == (uintptr_t(pointer) % N);
+}
+
+template <typename T> inline T roundDown(T value, unsigned int multiple)
+{
+ return value & ~(multiple - 1);
+}
+
+} // end namespace simd
+
+#endif // INCLUDED_TOOLS_SIMD_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/tools/simdsupport.hxx b/include/tools/simdsupport.hxx
new file mode 100644
index 000000000000..74afc9300b1a
--- /dev/null
+++ b/include/tools/simdsupport.hxx
@@ -0,0 +1,62 @@
+/* -*- 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/.
+ *
+ */
+
+// Determine the compiler support for SIMD compiler intrinsics.
+// This changes from one compiled unit to the other, depending if
+// the support has been detected and if the compiled unit contains
+// code using intrinsics or not. So we have to (re)set them again
+// every time this file has been included.
+
+#undef LO_SSE2_AVAILABLE
+#undef LO_SSSE3_AVAILABLE
+#undef LO_AVX_AVAILABLE
+#undef LO_AVX2_AVAILABLE
+
+#if defined(_MSC_VER) // VISUAL STUDIO COMPILER
+
+// SSE2 is required for X64
+#if (defined(_M_X64) || defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+#define LO_SSE2_AVAILABLE
+#endif
+
+// compiled with /arch:AVX
+#if defined(__AVX__)
+#ifndef LO_SSE2_AVAILABLE
+#define LO_SSE2_AVAILABLE
+#endif
+#define LO_SSSE3_AVAILABLE
+#define LO_AVX_AVAILABLE
+#endif
+
+// compiled with /arch:AVX2
+#if defined(__AVX2__)
+#define LO_AVX2_AVAILABLE
+#endif
+
+#else // Clang and GCC
+
+#if defined(__SSE2__) || defined(__x86_64__) // SSE2 is required for X64
+#define LO_SSE2_AVAILABLE
+#endif
+
+#if defined(__SSSE3__)
+#define LO_SSSE3_AVAILABLE
+#endif
+#if defined(__AVX__)
+#define LO_AVX_AVAILABLE
+
+#endif
+#if defined(__AVX2__)
+#define LO_AVX2_AVAILABLE
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 48cb55fae27a..365f4151aca6 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4673,7 +4673,7 @@ bool ScFormulaCell::InterpretFormulaGroupThreading(sc::FormulaLogger::GroupScope
bDependencyComputed = true;
- const static bool bHyperThreadingActive = tools::cpuid::hasHyperThreading();
+ const static bool bHyperThreadingActive = cpuid::hasHyperThreading();
// Then do the threaded calculation
diff --git a/sc/source/core/inc/arraysumfunctor.hxx b/sc/source/core/inc/arraysumfunctor.hxx
index 226962cf1f0f..05977c026361 100644
--- a/sc/source/core/inc/arraysumfunctor.hxx
+++ b/sc/source/core/inc/arraysumfunctor.hxx
@@ -13,21 +13,18 @@
#include <cstdint>
#include <rtl/math.hxx>
+
+#include <tools/simdsupport.hxx>
+#include <tools/simd.hxx>
#include <tools/cpuid.hxx>
#if defined(LO_SSE2_AVAILABLE)
-#include <emmintrin.h>
+#include <x86intrin.h>
#endif
namespace sc
{
-template<typename T, unsigned int N>
-inline bool isAligned(const T* pointer)
-{
- return 0 == (uintptr_t(pointer) % N);
-}
-
struct ArraySumFunctor
{
private:
@@ -43,7 +40,7 @@ public:
double operator() ()
{
- const static bool hasSSE2 = tools::cpuid::hasSSE2();
+ const static bool hasSSE2 = cpuid::hasSSE2();
double fSum = 0.0;
size_t i = 0;
@@ -51,7 +48,7 @@ public:
if (hasSSE2)
{
- while ( i < mnSize && !isAligned<double, 16>(pCurrent))
+ while ( i < mnSize && !simd::isAligned<double, 16>(pCurrent))
{
fSum += *pCurrent++;
i++;
diff --git a/tools/CppunitTest_tools_test.mk b/tools/CppunitTest_tools_test.mk
index ad56d893ae80..a4cdf8626f3a 100644
--- a/tools/CppunitTest_tools_test.mk
+++ b/tools/CppunitTest_tools_test.mk
@@ -31,6 +31,10 @@ $(eval $(call gb_CppunitTest_add_exception_objects,tools_test, \
tools/qa/cppunit/test_xmlwalker \
))
+$(eval $(call gb_CppunitTest_add_cxxobjects,tools_test,\
+ tools/qa/cppunit/test_cpuid, $(gb_LinkTarget_EXCEPTIONFLAGS) $(INTRINSICS_CXXFLAGS) \
+))
+
$(eval $(call gb_CppunitTest_use_sdk_api,tools_test))
$(eval $(call gb_CppunitTest_use_libraries,tools_test, \
diff --git a/tools/qa/cppunit/test_cpuid.cxx b/tools/qa/cppunit/test_cpuid.cxx
new file mode 100644
index 000000000000..fdb19d0ec133
--- /dev/null
+++ b/tools/qa/cppunit/test_cpuid.cxx
@@ -0,0 +1,74 @@
+/* -*- 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 <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+#include <tools/cpuid.hxx>
+#include <tools/simd.hxx>
+#include <rtl/ustring.hxx>
+
+namespace
+{
+class CpuInstructionSetSupport : public CppUnit::TestFixture
+{
+public:
+ void testCpuInstructionSetSupport();
+
+ CPPUNIT_TEST_SUITE(CpuInstructionSetSupport);
+ CPPUNIT_TEST(testCpuInstructionSetSupport);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void CpuInstructionSetSupport::testCpuInstructionSetSupport()
+{
+ OUString aString = cpuid::instructionSetSupportedString();
+
+ if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSE2))
+ {
+ CPPUNIT_ASSERT(aString.indexOf("SSE2") >= 0);
+ }
+
+ if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSSE3))
+ {
+ CPPUNIT_ASSERT(aString.indexOf("SSSE3") >= 0);
+ }
+
+ if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::AVX))
+ {
+ CPPUNIT_ASSERT(aString.indexOf("AVX") > 0);
+ }
+
+ if (cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::AVX2))
+ {
+ CPPUNIT_ASSERT(aString.indexOf("AVX2") > 0);
+ }
+
+#ifdef LO_SSE2_AVAILABLE
+ CPPUNIT_ASSERT_EQUAL(cpuid::hasSSE2(),
+ cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSE2));
+#endif
+
+#ifdef LO_SSSE3_AVAILABLE
+ CPPUNIT_ASSERT_EQUAL(cpuid::hasSSSE3(),
+ cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::SSE2));
+#endif
+
+#ifdef LO_AVX2_AVAILABLE
+ CPPUNIT_ASSERT_EQUAL(cpuid::hasAVX2(),
+ cpuid::isCpuInstructionSetSupported(cpuid::InstructionSetFlags::AVX2));
+#endif
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(CpuInstructionSetSupport);
+
+} // end anonymous namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/tools/source/misc/cpuid.cxx b/tools/source/misc/cpuid.cxx
index ee5093ce1892..e8699cbdf51c 100644
--- a/tools/source/misc/cpuid.cxx
+++ b/tools/source/misc/cpuid.cxx
@@ -11,25 +11,21 @@
#include <tools/cpuid.hxx>
#include <cstdint>
-namespace tools
-{
-namespace cpuid
-{
+namespace cpuid {
+
+namespace {
-namespace
-{
#if defined(_MSC_VER)
#include <intrin.h>
-void getCpuId(uint32_t array[4])
+void getCpuId(uint32_t array[4], uint32_t nInfoType)
{
- __cpuid(reinterpret_cast<int*>(array), 1);
+ __cpuid(reinterpret_cast<int*>(array), nInfoType);
}
-#else
-#if (defined(__i386__) || defined(__x86_64__))
+#elif (defined(__i386__) || defined(__x86_64__))
#include <cpuid.h>
-void getCpuId(uint32_t array[4])
+void getCpuId(uint32_t array[4], uint32_t nInfoType)
{
- __get_cpuid(1, array + 0, array + 1, array + 2, array + 3);
+ __cpuid_count(nInfoType, 0, *(array + 0), *(array + 1), *(array + 2), *(array + 3));
}
#else
void getCpuId(uint32_t array[4])
@@ -37,33 +33,104 @@ void getCpuId(uint32_t array[4])
array[0] = array[1] = array[2] = array[3] = 0;
}
#endif
+
+// For AVX we need to check if OS has support for ymm registers
+bool checkAVXSupportInOS()
+{
+ uint32_t xcr0 = 0;
+#if defined(_MSC_VER)
+ xcr0 = uint32_t(_xgetbv(0));
+#elif (defined(__i386__) || defined(__x86_64__))
+ __asm__("xgetbv" : "=a" (xcr0) : "c" (0) : "%edx");
#endif
+ return ((xcr0 & 6) == 6); /* checking if xmm and ymm state are enabled in XCR0 */
}
-#if defined(LO_SSE2_AVAILABLE)
+} // end anonymous namespace
-bool hasSSE2()
+#define HYPER_bit (1 << 28)
+#define SSE2_bit (1 << 26)
+#define SSSE3_bit (1 << 9)
+#define SSE41_bit (1 << 19)
+#define SSE42_bit (1 << 20)
+#define XSAVE_bit (1 << 27)
+#define AVX_bit (1 << 28)
+#define AVX2_bit (1 << 5)
+
+InstructionSetFlags getCpuInstructionSetFlags()
{
- uint32_t cpuInfoArray[] = {0, 0, 0, 0};
- getCpuId(cpuInfoArray);
- return (cpuInfoArray[3] & (1 << 26)) != 0;
-}
+ InstructionSetFlags eInstructions = InstructionSetFlags::NONE;
-#else
+ uint32_t info[] = {0, 0, 0, 0};
+ getCpuId(info, 0);
+ int nLevel = info[0];
-bool hasSSE2() { return false; }
+ if (nLevel >= 1)
+ {
+ uint32_t aCpuInfoArray[] = {0, 0, 0, 0};
+ getCpuId(aCpuInfoArray, 1);
-#endif
+ if ((aCpuInfoArray[3] & HYPER_bit) != 0)
+ eInstructions |= InstructionSetFlags::HYPER;
-bool hasHyperThreading()
-{
- uint32_t cpuInfoArray[] = {0, 0, 0, 0};
- getCpuId(cpuInfoArray);
- return (cpuInfoArray[3] & (1 << 28)) != 0;
+ if ((aCpuInfoArray[3] & SSE2_bit) != 0)
+ eInstructions |= InstructionSetFlags::SSE2;
+
+ if ((aCpuInfoArray[2] & SSSE3_bit) != 0)
+ eInstructions |= InstructionSetFlags::SSSE3;
+
+ if ((aCpuInfoArray[2] & SSE41_bit ) != 0)
+ eInstructions |= InstructionSetFlags::SSE41;
+
+ if ((aCpuInfoArray[2] & SSE42_bit) != 0)
+ eInstructions |= InstructionSetFlags::SSE42;
+
+ if (((aCpuInfoArray[2] & AVX_bit) != 0) &&
+ ((aCpuInfoArray[2] & XSAVE_bit) != 0))
+ {
+ if (checkAVXSupportInOS())
+ {
+ eInstructions |= InstructionSetFlags::AVX;
+
+ if (nLevel >= 7)
+ {
+ uint32_t aExtendedInfo[] = {0, 0, 0, 0};
+ getCpuId(aExtendedInfo, 7);
+
+ if ((aExtendedInfo[1] & AVX2_bit) != 0)
+ eInstructions |= InstructionSetFlags::AVX2;
+ }
+ }
+ }
+ }
+
+ return eInstructions;
}
+bool isCpuInstructionSetSupported(InstructionSetFlags eInstructions)
+{
+ static InstructionSetFlags eCPUFlags = getCpuInstructionSetFlags();
+ return (eCPUFlags & eInstructions) == eInstructions;
}
+
+OUString instructionSetSupportedString()
+{
+ OUString aString;
+ if (isCpuInstructionSetSupported(InstructionSetFlags::SSE2))
+ aString += "SSE2 ";
+ if (isCpuInstructionSetSupported(InstructionSetFlags::SSSE3))
+ aString += "SSSE3 ";
+ if (isCpuInstructionSetSupported(InstructionSetFlags::SSE41))
+ aString += "SSE4.1 ";
+ if (isCpuInstructionSetSupported(InstructionSetFlags::SSE42))
+ aString += "SSE4.2 ";
+ if (isCpuInstructionSetSupported(InstructionSetFlags::AVX))
+ aString += "AVX ";
+ if (isCpuInstructionSetSupported(InstructionSetFlags::AVX2))
+ aString += "AVX2 ";
+ return aString;
}
+} // end cpuid
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */