summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2021-12-20 21:11:17 -0300
committerThiago Macieira <thiago.macieira@intel.com>2022-01-20 20:48:23 -0300
commitc062fed4275c07e5c7a1a18d0779144519bec799 (patch)
tree5aae1e01ba2750e5cc20e764e7afb4934b6e14ae
parent970b249140da895abc23c3499ec11ccbf060fe00 (diff)
qsimd_p.h: add a hack to allow AVX to work with MinGW
GCC is unable to emit the SEH metadata about the stack aligning that is required to execute AVX aligned instructions (VMOVDQA, VMOVAPS, etc.), so it just doesn't align the stack. That causes crashes on a 50/50 chance every time the compiler attempts to address a stack-aligned variable. In a debug-mode build, because it always loads & saves everything on the stack, the chance of a crash happening is a near certainty. So we hack around it by going behind the compiler's back and instructing the assembler to emit the unaligned counterparts of the instructions every time the compiler wished to emit the aligned one. There's no performance penalty: if the variable is actually aligned, the unaligned instruction executes in the exact same time. Change-Id: Ib42b3adc93bf4d43bd55fffd16c29cac0da18972 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--config.tests/x86_simd/main.cpp3
-rw-r--r--src/corelib/global/qsimd_p.h23
2 files changed, 23 insertions, 3 deletions
diff --git a/config.tests/x86_simd/main.cpp b/config.tests/x86_simd/main.cpp
index 0e7ebed8d9..29c8b97c12 100644
--- a/config.tests/x86_simd/main.cpp
+++ b/config.tests/x86_simd/main.cpp
@@ -161,9 +161,6 @@ attribute_target("sha") void test_shani()
#endif
#if T(AVX)
-# if defined(__WIN64__) && defined(__GNUC__) && !defined(__clang__)
-# error "AVX support is broken in 64-bit MinGW - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49001"
-# endif
attribute_target("avx") void test_avx()
{
__m256d a = _mm256_setzero_pd();
diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h
index fdf5529135..57ef30d567 100644
--- a/src/corelib/global/qsimd_p.h
+++ b/src/corelib/global/qsimd_p.h
@@ -190,6 +190,29 @@
# define __SSE__ 1
# endif
+# if defined(Q_OS_WIN) && defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
+// 64-bit GCC on Windows does not support AVX, so we hack around it by forcing
+// it to emit unaligned loads & stores
+// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49001
+asm(
+ ".macro vmovapd args:vararg\n"
+ " vmovupd \\args\n"
+ ".endm\n"
+ ".macro vmovaps args:vararg\n"
+ " vmovups \\args\n"
+ ".endm\n"
+ ".macro vmovdqa args:vararg\n"
+ " vmovdqu \\args\n"
+ ".endm\n"
+ ".macro vmovdqa32 args:vararg\n"
+ " vmovdqu32 \\args\n"
+ ".endm\n"
+ ".macro vmovdqa64 args:vararg\n"
+ " vmovdqu64 \\args\n"
+ ".endm\n"
+);
+# endif
+
# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_OS_WASM)
// GCC 4.4 and Clang 2.8 added a few more intrinsics there
# include <x86intrin.h>