commit:     47709089ee12235f32005aa2295aec843164af16
Author:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
AuthorDate: Sat Sep  2 00:04:21 2023 +0000
Commit:     Ionen Wolkens <ionen <AT> gentoo <DOT> org>
CommitDate: Tue Sep  5 13:01:11 2023 +0000
URL:        https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=47709089

qt6-build.eclass: workaround mismatching cpu flags sets

qsimd_p.h tries determine if x86-64-v3 or v4 sets supported by the
compiler+flags seem complete, and errors out if not. This works out
rather badly on Gentoo, even -march=native can fail with some hard.

With qsimd_p.h being a private header this only affects dev-qt/*
packages, but fwics still need to fix all of dev-qt/* at once given
they are going to be using private bits from qtbase.

Debated a few options for this:

1. Patch headers (like old fix from bug #898644), but just not setting
   e.g. __haswell__ is not enough when __AVX2__ still confuses some
   code. Then unsetting these without going through the compiler leads
   to left over macros and more confusion. Besides... changing system
   headers behavior (why is __AVX2__ undef with -mavx2!?) only in
   distros tend to end in disaster.

2. Detect issues in qtbase ebuild, then disable x86intrin altogether
   if needed (carries over to other modules) + warn users (aka figure
   it out yourself). Not really great, users may also end up
   mismatching flags between dev-qt/ to fix this and then run into
   issues anyway.

3. Backport the next (wip/unmerged) upstream fix[1] but wait, looks
   like we are currently still playing whack-a-mole:
#  if defined(__AVX2__)
// List of features present with -march=x86-64-v3 and not architecturally
// implied by __AVX2__
#    define ARCH_HASWELL_MACROS     \
    (__AVX2__ && __BMI__ && __BMI2__ && __F16C__ \
     && __FMA__ && __LZCNT__ && __POPCNT__)
#    if ARCH_HASWELL_MACROS == 0
#      error "Please enable all x86-64-v3 extensions; <snip>
    ...so -mno-avx2 -mfma (bug #908420) is fine, older (bug #898644)
    is too, but if for any reason (VMs, buggy hardware, or the machine
    without F16C from bug #910419) anything else is disabled, then the
    issue is still there and may in fact trigger more than before.

4. Similarly to #2, detect issues but in the eclass. Then append
   -mno-* as needed to flags. Not too bad but passing -mno-*
   leads us to bug #913400.

5. Based on users flags, pick highest usable -march=x86-64-v* and
   strip everything else (or strip -march too...). Messy and think
   users wouldn't be happy about this. It would be what upstream
   likely wants us to do though, and causes no further problems.

Ultimately went with #4 for now, bug #913400 needs fixing either way.
- missing from set in #3 += -mno-avx2 (until #3, also -mno-fma)
- missing the AVX512* checked in qsimd_h += -mno-avx512*
(then let compiler disable features that depend on these)

Not great but better than doing nothing, no-op for non-affected users.

[1] https://codereview.qt-project.org/c/qt/qtbase/+/498799

Bug: https://bugs.gentoo.org/898644
Bug: https://bugs.gentoo.org/913400
Closes: https://bugs.gentoo.org/908420
Signed-off-by: Ionen Wolkens <ionen <AT> gentoo.org>

 eclass/qt6-build.eclass | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/eclass/qt6-build.eclass b/eclass/qt6-build.eclass
index f6ed180a6979..8db83524d5e3 100644
--- a/eclass/qt6-build.eclass
+++ b/eclass/qt6-build.eclass
@@ -21,7 +21,7 @@ _QT6_BUILD_ECLASS=1
 [[ ${CATEGORY} != dev-qt ]] &&
        die "${ECLASS} is only to be used for building Qt6"
 
-inherit cmake flag-o-matic
+inherit cmake flag-o-matic toolchain-funcs
 
 # @ECLASS_VARIABLE: QT6_MODULE
 # @PRE_INHERIT
@@ -108,6 +108,7 @@ qt6-build_src_prepare() {
        fi
 
        _qt6-build_prepare_env
+       _qt6-build_match_cpu_flags
 }
 
 # @FUNCTION: qt6-build_src_configure
@@ -235,6 +236,38 @@ _qt6-build_create_user_facing_links() {
        done < "${BUILD_DIR}"/user_facing_tool_links.txt || die
 }
 
+# @FUNCTION: _qt6-build_match_cpu_flags
+# @INTERNAL
+# @DESCRIPTION:
+# Try to adjust -m* cpu CXXFLAGS so that they match a configuration
+# accepted by Qt's headers, see bug #908420.
+_qt6-build_match_cpu_flags() {
+       use amd64 || use x86 || return 0
+
+       local flags=() intrin intrins
+       while IFS=' ' read -ra intrins; do
+               [[ ${intrins[*]} == *=[^_]* && ${intrins[*]} == *=_* ]] &&
+                       for intrin in "${intrins[@]}"; do
+                               [[ ${intrin} == *?=[^_]* ]] && 
flags+=(-mno-${intrin%=*})
+                       done
+       done < <(
+               # TODO: review if can drop fma= matching after QTBUG-116357
+               $(tc-getCXX) -E -P ${CXXFLAGS} ${CPPFLAGS} - <<-EOF | tail -n 2
+                       #if defined(__GNUC__) && (defined(__x86_64__) || 
defined(__i386__))
+                       #include <x86intrin.h>
+                       #endif
+                       avx2=__AVX2__ =__BMI__ =__BMI2__ =__F16C__ fma=__FMA__ 
=__LZCNT__ =__POPCNT__
+                       avx512f=__AVX512F__ avx512bw=__AVX512BW__ 
avx512cd=__AVX512CD__ avx512dq=__AVX512DQ__ avx512vl=__AVX512VL__
+               EOF
+               assert
+       )
+
+       if (( ${#flags[@]} )); then
+               einfo "Adjusting CXXFLAGS for https://bugs.gentoo.org/908420 
with: ${flags[*]}"
+               append-cxxflags "${flags[@]}"
+       fi
+}
+
 # @FUNCTION: _qt6-build_prepare_env
 # @INTERNAL
 # @DESCRIPTION:

Reply via email to