diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index c1c5ca5a0..1ac9c1902 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -6,13 +6,14 @@ concurrency: jobs: test: runs-on: ubuntu-latest + name: 'android-${{ matrix.api }} - ${{ matrix.target.abi }} ${{ matrix.target.arch }}' strategy: matrix: target: - - armeabi-v7a - - arm64-v8a - - x86 - - x86_64 + - { abi: 'armeabi-v7a', arch: 'neon' } + - { abi: 'arm64-v8a', arch: 'neon64' } + - { abi: 'x86', arch: 'ssse3' } + - { abi: 'x86_64', arch: 'sse4.2' } api: - 16 - 18 @@ -21,14 +22,14 @@ jobs: uses: actions/checkout@v6 - name: Build script - env: - TARGET: ${{ matrix.target }} - API: ${{ matrix.api }} run: | NDK="$($ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --list_installed | sed -E 's/( +[|] +)/|/g;s/ +$//' | grep '^ ndk' | cut -d '|' -f 4 | sort | head -n1)" cmake -B _build \ - -DCMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/$NDK/build/cmake/android.toolchain.cmake \ - -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON \ - -DANDROID_ABI=$ABI -DANDROID_PLATFORM=android-$API \ - -DCMAKE_BUILD_TYPE=Release + -D CMAKE_TOOLCHAIN_FILE=$ANDROID_HOME/$NDK/build/cmake/android.toolchain.cmake \ + -D CMAKE_BUILD_TYPE=Release \ + -D BUILD_TESTS=ON \ + -D DOWNLOAD_DOCTEST=ON \ + -D ANDROID_ABI="${{ matrix.target.abi }}" \ + -D ANDROID_PLATFORM=android-${{ matrix.api }} \ + -D TARGET_ARCH="${{ matrix.target.arch }}" cmake --build _build --verbose diff --git a/.github/workflows/cross-arm.yml b/.github/workflows/cross-arm.yml index 79a83492a..f0966f286 100644 --- a/.github/workflows/cross-arm.yml +++ b/.github/workflows/cross-arm.yml @@ -10,9 +10,9 @@ jobs: strategy: matrix: target: - - { platform: 'arm', arch: 'armv7-a', dir: 'arm-linux-gnueabihf', flags: '-mfpu=neon', full: 'ON'} - - { platform: 'arm', arch: 'armv7-a', dir: 'arm-linux-gnueabihf', flags: '-mfpu=vfpv3-d16', full: 'OFF' } # no neon - - { platform: 'aarch64', arch: 'armv8-a', dir: 'aarch64-linux-gnu', flags: '', full: 'ON' } + - { arch: 'armv7-a', xsimd_arch: 'neon', dir: 'arm-linux-gnueabihf', flags: '-mfpu=neon', full: 'ON' } + - { arch: 'armv7-a', xsimd_arch: 'generic', dir: 'arm-linux-gnueabihf', flags: '-mfpu=vfpv3-d16', full: 'OFF' } # no neon + - { arch: 'armv8-a', xsimd_arch: 'neon64', dir: 'aarch64-linux-gnu', flags: '', full: 'ON' } sys: - { compiler: 'gcc', version: '10' } - { compiler: 'gcc', version: '14' } @@ -39,12 +39,12 @@ jobs: cmake -B _build \ -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DBUILD_BENCHMARK=${{ matrix.target.full }} \ -DBUILD_EXAMPLES=${{ matrix.target.full }} -DCMAKE_BUILD_TYPE=Release \ - -DTARGET_ARCH=generic \ + -DTARGET_ARCH=${{ matrix.target.xsimd_arch }} \ -DCMAKE_C_FLAGS="-march=${{ matrix.target.arch }} ${{ matrix.target.flags }}" \ -DCMAKE_CXX_FLAGS="-march=${{ matrix.target.arch }} ${{ matrix.target.flags }}" \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/${{ matrix.sys.compiler }}-${{ matrix.target.dir }}.cmake - name: Build run: cmake --build _build - name: Testing xsimd - run: qemu-${{ matrix.target.platform }} -L /usr/${{ matrix.target.dir}}/ ./test/test_xsimd + run: qemu-${{ matrix.target.arch == 'armv8-a' && 'aarch64' || 'arm' }} -L /usr/${{ matrix.target.dir}}/ ./test/test_xsimd working-directory: ${{ github.workspace }}/_build diff --git a/.github/workflows/cross-loongarch.yml b/.github/workflows/cross-loongarch.yml index 8840fdd86..b5598c90f 100644 --- a/.github/workflows/cross-loongarch.yml +++ b/.github/workflows/cross-loongarch.yml @@ -6,13 +6,13 @@ concurrency: jobs: build: runs-on: ubuntu-latest - name: 'LoongArch64 ${{ matrix.simd.name }}' + name: 'LoongArch64 ${{ matrix.simd.arch }}' strategy: fail-fast: false matrix: simd: - - { name: 'LSX', flags: '-mlsx -mno-lasx', lasx: 0, cpu: 'la464,lsx=on,lasx=off' } - - { name: 'LASX', flags: '-mlasx', lasx: 1, cpu: 'la464,lsx=on,lasx=on' } + - { arch: 'lsx', lasx: 0, cpu: 'la464,lsx=on,lasx=off' } + - { arch: 'lasx', lasx: 1, cpu: 'la464,lsx=on,lasx=on' } steps: - name: Setup compiler run: | @@ -42,9 +42,7 @@ jobs: -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DCMAKE_BUILD_TYPE=Release - -DTARGET_ARCH=generic - -DCMAKE_C_FLAGS="${{ matrix.simd.flags }}" - -DCMAKE_CXX_FLAGS="${{ matrix.simd.flags }}" + -DTARGET_ARCH=${{ matrix.simd.arch }} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/gcc-loongarch64-linux-gnu.cmake - name: Build run: cmake --build _build diff --git a/.github/workflows/cross-ppc.yml b/.github/workflows/cross-ppc.yml index 6f07a763c..f5cfef1c1 100644 --- a/.github/workflows/cross-ppc.yml +++ b/.github/workflows/cross-ppc.yml @@ -11,8 +11,8 @@ jobs: strategy: matrix: target: - - { platform: 'ppc64le', dir: 'powerpc64le-linux-gnu', flags: '-maltivec -mvsx -mcpu=power10', full: 'OFF' } - - { platform: 'ppc64', dir: 'powerpc64-linux-gnu', flags: '-maltivec -mvsx -mcpu=power10', full: 'OFF' } + - { platform: 'ppc64le', dir: 'powerpc64le-linux-gnu', full: 'OFF' } + - { platform: 'ppc64', dir: 'powerpc64-linux-gnu', full: 'OFF' } sys: - { compiler: 'gcc', version: '12' } - { compiler: 'clang', version: '20', gcc_runtime: '12' } @@ -50,8 +50,7 @@ jobs: -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON \ -DBUILD_BENCHMARK=${{ matrix.target.full }} -DBUILD_EXAMPLES=${{ matrix.target.full }} \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_FLAGS="${{ matrix.target.flags }}" \ - -DCMAKE_CXX_FLAGS="${{ matrix.target.flags }}" \ + -DTARGET_ARCH=vsx \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/${{ matrix.sys.compiler }}-${{ matrix.target.dir }}.cmake - name: Build run: cmake --build build/ --verbose -j1 diff --git a/.github/workflows/cross-rvv.yml b/.github/workflows/cross-rvv.yml index a596de634..29a9a3c1d 100644 --- a/.github/workflows/cross-rvv.yml +++ b/.github/workflows/cross-rvv.yml @@ -68,9 +68,7 @@ jobs: -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DCMAKE_BUILD_TYPE=Release - -DTARGET_ARCH=generic - -DCMAKE_C_FLAGS="-march=rv64gcv_zvl${{ matrix.vector_bits }}b_zba_zbb_zbs -mrvv-vector-bits=zvl" - -DCMAKE_CXX_FLAGS="-march=rv64gcv_zvl${{ matrix.vector_bits }}b_zba_zbb_zbs -mrvv-vector-bits=zvl" + -DTARGET_ARCH=rvv_${{ matrix.vector_bits }} -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/${{ matrix.sys.compiler }}-riscv64-linux-gnu.cmake - name: Build run: cmake --build _build diff --git a/.github/workflows/cross-s390x.yml b/.github/workflows/cross-s390x.yml index b748d328e..10361b5e2 100644 --- a/.github/workflows/cross-s390x.yml +++ b/.github/workflows/cross-s390x.yml @@ -38,8 +38,7 @@ jobs: -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON \ -DBUILD_BENCHMARK=${{ matrix.target.full }} -DBUILD_EXAMPLES=${{ matrix.target.full }} \ -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_FLAGS="${{ matrix.target.flags }}" \ - -DCMAKE_CXX_FLAGS="${{ matrix.target.flags }}" \ + -DTARGET_ARCH=vxe \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/${{ matrix.sys.compiler }}-${{ matrix.target.dir }}.cmake - name: Build run: cmake --build build/ --verbose -j1 diff --git a/.github/workflows/cross-sve.yml b/.github/workflows/cross-sve.yml index 8a2ffe102..b58d7272d 100644 --- a/.github/workflows/cross-sve.yml +++ b/.github/workflows/cross-sve.yml @@ -34,9 +34,7 @@ jobs: -GNinja \ -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON \ -DCMAKE_BUILD_TYPE=Release \ - -DTARGET_ARCH=generic \ - -DCMAKE_C_FLAGS="-march=armv8-a+sve -msve-vector-bits=${{ matrix.vector_bits }}" \ - -DCMAKE_CXX_FLAGS="-march=armv8-a+sve -msve-vector-bits=${{ matrix.vector_bits }}" \ + -DTARGET_ARCH=sve_${{ matrix.vector_bits }} \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/.github/toolchains/gcc-aarch64-linux-gnu.cmake - name: Build run: cmake --build _build diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 0940742df..2a72953ed 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -10,30 +10,28 @@ defaults: jobs: build: runs-on: ubuntu-latest - name: '${{ matrix.sys.compiler }} ${{ matrix.sys.version }} - ${{ matrix.sys.flags }}' + name: '${{ matrix.sys.compiler }} ${{ matrix.sys.version }} - ${{ matrix.sys.arch }} ${{ join(matrix.sys.flags, '' '') }}' strategy: matrix: sys: - - { compiler: 'gcc', version: '12', flags: 'force_no_instr_set' } - - { compiler: 'gcc', version: '13', flags: 'enable_xtl_complex' } - - { compiler: 'gcc', version: '14', flags: 'avx' } - - { compiler: 'gcc', version: '14', flags: 'avx2' } - - { compiler: 'gcc', version: '13', flags: 'avx512' } - - { compiler: 'gcc', version: '10', flags: 'avx512' } - - { compiler: 'gcc', version: '12', flags: 'i386' } - - { compiler: 'gcc', version: '13', flags: 'avx512pf' } - - { compiler: 'gcc', version: '13', flags: 'avx512vbmi' } - - { compiler: 'gcc', version: '14', flags: 'avx512vbmi2' } - - { compiler: 'gcc', version: '13', flags: 'avx512vnni' } - - { compiler: 'clang', version: '16', flags: 'force_no_instr_set' } - - { compiler: 'clang', version: '16', flags: 'enable_xtl_complex' } - - { compiler: 'clang', version: '17', flags: 'avx' } - - { compiler: 'clang', version: '17', flags: 'sse3' } - - { compiler: 'clang', version: '18', flags: 'avx512' } - - { compiler: 'clang', version: '18', flags: 'avx_128' } - - { compiler: 'clang', version: '18', flags: 'avx2_128' } - - { compiler: 'clang', version: '18', flags: 'avx512vl_128' } - - { compiler: 'clang', version: '18', flags: 'avx512vl_256' } + - { compiler: 'gcc', version: '13', arch: 'native', flags: ['xtl-complex'] } + - { compiler: 'gcc', version: '14', arch: 'avx', flags: [] } + - { compiler: 'gcc', version: '14', arch: 'avx2', flags: [] } + - { compiler: 'gcc', version: '13', arch: 'avx512bw', flags: [] } + - { compiler: 'gcc', version: '10', arch: 'avx512bw', flags: [] } + - { compiler: 'gcc', version: '12', arch: 'native', flags: ['32bits'] } + - { compiler: 'gcc', version: '13', arch: 'avx512pf', flags: [] } + - { compiler: 'gcc', version: '13', arch: 'avx512vbmi', flags: [] } + - { compiler: 'gcc', version: '14', arch: 'avx512vbmi2', flags: [] } + - { compiler: 'gcc', version: '13', arch: 'avx512vnni_avx512bw', flags: [] } + - { compiler: 'clang', version: '16', arch: 'native', flags: ['xtl-complex'] } + - { compiler: 'clang', version: '17', arch: 'avx', flags: [] } + - { compiler: 'clang', version: '17', arch: 'sse3', flags: [] } + - { compiler: 'clang', version: '18', arch: 'avx512bw', flags: [] } + - { compiler: 'clang', version: '18', arch: 'avx_128', flags: [] } + - { compiler: 'clang', version: '18', arch: 'avx2_128', flags: [] } + - { compiler: 'clang', version: '18', arch: 'avx512vl_128', flags: [] } + - { compiler: 'clang', version: '18', arch: 'avx512vl_256', flags: [] } steps: - name: Setup compiler if: ${{ matrix.sys.compiler == 'gcc' }} @@ -68,82 +66,34 @@ jobs: with: environment-file: environment.yml - name: Setup SDE - if: startswith(matrix.sys.flags, 'avx512') + if: startswith(matrix.sys.arch, 'avx512') run: sh install_sde.sh - name: Configure build env: CC: ${{ env.CC }} CXX: ${{ env.CXX }} run: | - if [[ '${{ matrix.sys.flags }}' == 'enable_xtl_complex' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DENABLE_XTL_COMPLEX=ON" + CMAKE_ARGS=() + if [[ '${{ contains(matrix.sys.flags, 'xtl-complex') }}' == 'true' ]]; then + CMAKE_ARGS+=(-D ENABLE_XTL_COMPLEX=ON) fi - if [[ '${{ matrix.sys.flags }}' == 'avx' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=sandybridge" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx_128' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=sandybridge" - CXXFLAGS="$CXXFLAGS -DXSIMD_DEFAULT_ARCH=avx_128" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx2' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=haswell" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx2_128' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=haswell" - CXXFLAGS="$CXXFLAGS -DXSIMD_DEFAULT_ARCH=avx2_128" - fi - if [[ '${{ matrix.sys.flags }}' == 'sse3' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=nocona" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=skylake-avx512" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512vl_128' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=skylake-avx512" - CXXFLAGS="$CXXFLAGS -DXSIMD_DEFAULT_ARCH=avx512vl_128" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512vl_256' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=skylake-avx512" - CXXFLAGS="$CXXFLAGS -DXSIMD_DEFAULT_ARCH=avx512vl_256" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512pf' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=knl" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512vbmi' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=cannonlake" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512vbmi2' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=icelake-server" - fi - if [[ '${{ matrix.sys.flags }}' == 'avx512vnni' ]]; then - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DTARGET_ARCH=knm" - fi - if [[ '${{ matrix.sys.flags }}' == 'i386' ]]; then - CXXFLAGS="$CXXFLAGS -m32" - fi - if [[ '${{ matrix.sys.flags }}' == 'force_no_instr_set' ]]; then - : - else - CMAKE_EXTRA_ARGS="$CMAKE_EXTRA_ARGS -DXSIMD_ENABLE_WERROR=ON" - fi - - # Cheap way of spotting uninitialized read - if echo 'int main(){}' | $CXX -x c++ -ftrivial-auto-var-init=pattern -fsyntax-only - 2>/dev/null; then - CXXFLAGS="$CXXFLAGS -ftrivial-auto-var-init=pattern" + if [[ '${{ contains(matrix.sys.flags, '32bits') }}' == 'true' ]]; then + CMAKE_ARGS+=(-D CMAKE_CXX_FLAGS=-m32) fi - cmake -B _build \ - -DBUILD_TESTS=ON \ - -DBUILD_EXAMPLES=ON \ - -DBUILD_ARCHITECTURE_TESTS=OFF \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - $CMAKE_EXTRA_ARGS \ - -DCMAKE_CXX_FLAGS="$CXXFLAGS" \ - -G Ninja + cmake -B build/ -G Ninja \ + -D CMAKE_C_COMPILER=$CC \ + -D CMAKE_CXX_COMPILER=$CXX \ + -D CMAKE_BUILD_TYPE=Release \ + -D BUILD_TESTS=ON \ + -D BUILD_EXAMPLES=ON \ + -D BUILD_ARCHITECTURE_TESTS=OFF \ + -D XSIMD_ENABLE_WERROR=ON \ + -D XSIMD_HARDEN_TRIVIAL_AUTO_VAR_INIT=ON \ + -D TARGET_ARCH="${{ matrix.sys.arch }}" \ + "${CMAKE_ARGS[@]}" - name: Build - run: cmake --build _build + run: cmake --build build/ - name: Test run: | # Set CPU feature test expectations, 0 is explicit absence of the feature @@ -151,8 +101,8 @@ jobs: export XSIMD_TEST_CPU_ASSUME_RVV="0" export XSIMD_TEST_CPU_ASSUME_VSX="0" export XSIMD_TEST_CPU_ASSUME_VXE="0" - cd _build/test - if echo '${{ matrix.sys.flags }}' | grep -q 'avx512' ; then + cd build/test + if echo '${{ matrix.sys.arch }}' | grep -q 'avx512' ; then # Running with emulation, must have AVX512, lower tier are checked by implications in tests export XSIMD_TEST_CPU_ASSUME_AVX512F="1" ../../sde-external-9.48.0-2024-11-25-lin/sde64 -tgl -- ./test_xsimd @@ -182,14 +132,14 @@ jobs: environment-file: environment.yml - name: Configure build run: | - cmake -B _build \ - -DBUILD_TESTS=ON \ - -DBUILD_ARCHITECTURE_TESTS=ON \ - -DBUILD_BENCHMARK=ON \ - -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_COMPILER=$CC \ - -DCMAKE_CXX_COMPILER=$CXX \ - -DXSIMD_ENABLE_WERROR=ON \ - -G Ninja + cmake -B build/ -G Ninja \ + -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_C_COMPILER=$CC \ + -D CMAKE_CXX_COMPILER=$CXX \ + -D BUILD_TESTS=ON \ + -D BUILD_ARCHITECTURE_TESTS=ON \ + -D BUILD_BENCHMARK=ON \ + -D XSIMD_ENABLE_WERROR=ON \ + -D XSIMD_HARDEN_TRIVIAL_AUTO_VAR_INIT=ON \ - name: Build - run: cmake --build _build + run: cmake --build build/ diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 14132f5db..ba873e432 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -8,16 +8,23 @@ jobs: build: strategy: matrix: - os: - - 14 - - 15 - - 15-intel - runs-on: macos-${{ matrix.os }} - name: 'macos-${{ matrix.os }}' + sys: + - { os: '14', arch: 'native' } + - { os: '15', arch: 'neon64' } + - { os: '15-intel', arch: 'sse4.2' } + runs-on: macos-${{ matrix.sys.os }} + name: 'macos-${{ matrix.sys.os }} - ${{ matrix.sys.arch }}' steps: - uses: actions/checkout@v6 - name: Setup - run: cmake -B _build -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DBUILD_BENCHMARK=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" + run: | + cmake -B _build \ + -D CMAKE_BUILD_TYPE=Release \ + -D BUILD_TESTS=ON \ + -D DOWNLOAD_DOCTEST=ON \ + -D BUILD_BENCHMARK=ON \ + -D BUILD_EXAMPLES=ON \ + -D TARGET_ARCH="${{ matrix.sys.arch }}" - name: Build run: cmake --build _build --verbose - name: Testing sequential @@ -25,7 +32,7 @@ jobs: - name: Set CPU feature test expectations run: | echo "XSIMD_TEST_CPU_ASSUME_RVV=0" >> "$GITHUB_ENV" - if echo '${{ matrix.os }}' | grep -q intel; then + if echo '${{ matrix.sys.os }}' | grep -q intel; then echo "XSIMD_TEST_CPU_ASSUME_NEON64=0" >> "$GITHUB_ENV" echo "XSIMD_TEST_CPU_ASSUME_SSE4_2=1" >> "$GITHUB_ENV" echo "XSIMD_TEST_CPU_ASSUME_MANUFACTURER=intel" >> "$GITHUB_ENV" diff --git a/.github/workflows/style-check.yml b/.github/workflows/style-check.yml index f308b99eb..07262277a 100644 --- a/.github/workflows/style-check.yml +++ b/.github/workflows/style-check.yml @@ -44,7 +44,7 @@ jobs: -DDOWNLOAD_DOCTEST=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - -DCMAKE_CXX_FLAGS='-march=tigerlake' + -DTARGET_ARCH=avx512vnni_avx512vbmi2 . - name: Check run: run-clang-tidy -p _build diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 65c37917e..92e4b3c23 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -6,7 +6,7 @@ concurrency: jobs: build-windows-x86: - name: 'MSVC ${{ matrix.os }}, ${{ matrix.target }} ${{ matrix.sys.set }}' + name: 'MSVC ${{ matrix.os }}, ${{ matrix.target }} ${{ matrix.arch }}' defaults: run: shell: bash {0} @@ -18,19 +18,19 @@ jobs: target: - x86 - x64 - sys: - - { set: SSE, flags: "/arch:SSE2" } - - { set: AVX, flags: "/arch:AVX" } - - { set: AVX2, flags: "/arch:AVX2" } - - { set: AVX512, flags: "/arch:AVX512" } + arch: + - sse2 + - avx + - avx2 + - avx512bw exclude: # AVX on both platforms has a codegen error # On 2019 in _mm256_rsqrt_ps, on 2022 in _mm256_blend_p* - - { sys: { set: AVX } } + - { arch: avx } # On both platforms x86 + AVX512 triggers a compiler crash - - { target: x86, sys: { set: AVX512 } } + - { target: x86, arch: avx512bw } # /arch:SSE2 is not available on x64 platforms (SSE2 is enabled by default) - - { target: x64, sys: { set: SSE} } + - { target: x64, arch: sse2 } runs-on: windows-${{ matrix.os }} steps: - name: Setup compiler @@ -44,11 +44,19 @@ jobs: - name: Checkout xsimd uses: actions/checkout@v6 - name: Setup - run: cmake -B _build -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DBUILD_BENCHMARK=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${{ matrix.sys.flags }}" -G Ninja + run: | + cmake -B _build \ + -DBUILD_TESTS=ON \ + -DDOWNLOAD_DOCTEST=ON \ + -DBUILD_BENCHMARK=ON \ + -DBUILD_EXAMPLES=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DTARGET_ARCH=${{ matrix.arch }} \ + -G Ninja - name: Build run: cmake --build _build - name: Testing xsimd - if: ${{ !startsWith(matrix.sys.set, 'AVX512') }} + if: ${{ !startsWith(matrix.arch, 'avx512') }} env: # Set CPU feature test expectations # Assuming the runner always has AVX2 (independent of compilation option) @@ -86,7 +94,14 @@ jobs: - name: Checkout xsimd uses: actions/checkout@v6 - name: Configure - run: cmake -B _build -DBUILD_TESTS=ON -DBUILD_BENCHMARK=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release -DDOWNLOAD_DOCTEST=ON -G Ninja + run: | + cmake -B _build \ + -DBUILD_TESTS=ON \ + -DBUILD_BENCHMARK=ON \ + -DBUILD_EXAMPLES=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DDOWNLOAD_DOCTEST=ON \ + -G Ninja - name: Build run: cmake --build _build - name: Test @@ -100,8 +115,8 @@ jobs: strategy: matrix: config: - - { name: "AVX2", flags: "/arch:AVX2", benchmark: "ON", examples: "ON" } - - { name: "/fp:fast", flags: "/fp:fast", benchmark: "OFF", examples: "OFF" } + - { name: "AVX2", arch: "avx2", flags: "", benchmark: "ON", examples: "ON" } + - { name: "/fp:fast", arch: "generic", flags: "/fp:fast", benchmark: "OFF", examples: "OFF" } runs-on: windows-2025 steps: - name: Setup compiler @@ -128,6 +143,7 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_COMPILER=clang-cl \ -DCMAKE_CXX_COMPILER=clang-cl \ + -DTARGET_ARCH=${{ matrix.config.arch }} \ -DCMAKE_CXX_FLAGS="${{ matrix.config.flags }} -DXSIMD_REASSOCIATIVE_MATH=1" \ -G Ninja - name: Build @@ -158,7 +174,15 @@ jobs: - name: Checkout xsimd uses: actions/checkout@v6 - name: Setup - run: cmake -B _build -DBUILD_TESTS=ON -DDOWNLOAD_DOCTEST=ON -DBUILD_BENCHMARK=ON -DBUILD_EXAMPLES=ON -DCMAKE_BUILD_TYPE=Release -G Ninja + run: | + cmake -B _build \ + -DBUILD_TESTS=ON \ + -DDOWNLOAD_DOCTEST=ON \ + -DBUILD_BENCHMARK=ON \ + -DBUILD_EXAMPLES=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DTARGET_ARCH=neon64 \ + -G Ninja env: CFLAGS: ${{ matrix.abi.cflags }} CXXFLAGS: ${{ matrix.abi.cflags }} diff --git a/CMakeLists.txt b/CMakeLists.txt index 82f7d0a22..d025ce3aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ project(xsimd) OPTION(ENABLE_XTL_COMPLEX "enables support for xcomplex defined in xtl" OFF) OPTION(BUILD_TESTS "xsimd test suite" OFF) +include (cmake/Hardening.cmake) +include (cmake/Architecture.cmake) + # Versioning # ========== @@ -54,6 +57,19 @@ if(ENABLE_XTL_COMPLEX OR XSIMD_ENABLE_XTL_COMPLEX) ) endif() +# Dev options +# =========== + +option( + XSIMD_HARDEN_TRIVIAL_AUTO_VAR_INIT + "Enable -ftrivial-auto-var-init hardening flag if supported" + OFF +) + +if(XSIMD_HARDEN_TRIVIAL_AUTO_VAR_INIT) + xsimd_harden_trivial_auto_var_init(xsimd INTERFACE) +endif() + if(BUILD_TESTS) enable_testing() add_subdirectory(test) @@ -107,6 +123,7 @@ write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Conf COMPATIBILITY SameMajorVersion) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Architecture.cmake DESTINATION ${XSIMD_CMAKECONFIG_INSTALL_DIR}) install(EXPORT ${PROJECT_NAME}-targets FILE ${PROJECT_NAME}Targets.cmake diff --git a/cmake/Architecture.cmake b/cmake/Architecture.cmake new file mode 100644 index 000000000..e6f3fd948 --- /dev/null +++ b/cmake/Architecture.cmake @@ -0,0 +1,444 @@ +include(CheckCXXCompilerFlag) + +# Get the target architecture family. +function(xsimd_get_target out_var) + # The Emscripten toolchain reports an x86 processor. + if(EMSCRIPTEN) + set(${out_var} "wasm32" PARENT_SCOPE) + return() + endif() + + if(MSVC AND CMAKE_CXX_COMPILER_ARCHITECTURE_ID) + set(proc "${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}") + else() + set(proc "${CMAKE_SYSTEM_PROCESSOR}") + endif() + string(TOLOWER "${proc}" proc) + + # The processor name is the host one when cross-compiling with -m32. + if(proc MATCHES "^(aarch64|arm)") + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(${out_var} "arm32" PARENT_SCOPE) + else() + set(${out_var} "arm64" PARENT_SCOPE) + endif() + elseif(proc MATCHES "^riscv64") + set(${out_var} "riscv64" PARENT_SCOPE) + elseif(proc MATCHES "^loongarch64") + set(${out_var} "loongarch64" PARENT_SCOPE) + elseif(proc MATCHES "^s390x") + set(${out_var} "s390x" PARENT_SCOPE) + elseif(proc MATCHES "^(powerpc64|ppc64)") + set(${out_var} "ppc64" PARENT_SCOPE) + elseif(proc MATCHES "^(x86|x64|x86_64|amd64|i[3-6]86)$") + if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(${out_var} "x86_32" PARENT_SCOPE) + else() + set(${out_var} "x86_64" PARENT_SCOPE) + endif() + else() + set(${out_var} "" PARENT_SCOPE) + endif() +endfunction() + + +# Get xsimd flags for emulated architecture +function(xsimd_get_emulated_arch_flags out_list arch) + if(arch MATCHES "emulated[-_<]([0-9]+)>?") + set( + ${out_list} + "-DXSIMD_DEFAULT_ARCH=emulated<${CMAKE_MATCH_1}>;-DXSIMD_WITH_EMULATED=1" + PARENT_SCOPE + ) + else() + message(FATAL_ERROR "Unknown xsimd emulated architecture: ${arch}") + endif() +endfunction() + + +# Get flags for native build. +function(xsimd_get_native_arch_flags out_list) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + message(WARNING "Native not supported on MSVC, not setting any flag") + else() + set(${out_list} "-march=native" PARENT_SCOPE) + endif() +endfunction() + + +function(xsimd_get_arm64_arch_flags_unix out_list arch arm64_baseline) + if(arch MATCHES "sve[-_]([0-9]+)") + if(arm64_baseline STREQUAL "") + # Starting point for SVE + set(arm64_baseline "armv8.2-a") + endif() + set( + ${out_list} + "-march=${arm64_baseline}+sve;-msve-vector-bits=${CMAKE_MATCH_1}" + PARENT_SCOPE + ) + elseif(arch MATCHES "neon") + if(arm64_baseline STREQUAL "") + set(arm64_baseline "armv8-a") + endif() + set(${out_list} "-march=${arm64_baseline}" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown xsimd architecture for arm64: ${arch}") + endif() +endfunction() + + +function(xsimd_get_arm64_arch_flags_msvc out_list arch arm64_baseline) + if(arch MATCHES "sve") + message(FATAL_ERROR "SVE not supported on MSVC compilers") + elseif(arch MATCHES "neon") + if(arm64_baseline STREQUAL "") + set(arm64_baseline "armv8.0") + endif() + set(${out_list} "/arch:${arm64_baseline}" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown xsimd architecture for arm64: ${arch}") + endif() +endfunction() + + +# Get the flag to compile with the desired xsimd arch on arm64. +function(xsimd_get_arm64_arch_flags out_list arch arm64_baseline) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + xsimd_get_arm64_arch_flags_msvc(flags "${arch}" "${arm64_baseline}") + else() + xsimd_get_arm64_arch_flags_unix(flags "${arch}" "${arm64_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on riscv64. +function(xsimd_get_riscv64_arch_flags out_list arch riscv64_baseline) + if(NOT arch MATCHES "rvv[-_]([0-9]+)") + message(FATAL_ERROR "Unknown xsimd architecture for riscv64: ${arch}") + endif() + set(vector_bits "${CMAKE_MATCH_1}") + if(riscv64_baseline STREQUAL "") + set(riscv64_baseline "rv64gc") + endif() + # Single-letter extensions must precede the multi-letter ones. + string(REGEX MATCH "^[^_]*" base "${riscv64_baseline}") + string(REGEX MATCH "_.*" extensions "${riscv64_baseline}") + set( + ${out_list} + "-march=${base}v${extensions}_zvl${vector_bits}b;-mrvv-vector-bits=zvl" + PARENT_SCOPE + ) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on loongarch64. +function(xsimd_get_loongarch64_arch_flags out_list arch loongarch64_baseline) + if(arch STREQUAL "lsx") + set(flags "-mlsx;-mno-lasx") + elseif(arch STREQUAL "lasx") + set(flags "-mlasx") + else() + message(FATAL_ERROR "Unknown xsimd architecture for loongarch64: ${arch}") + endif() + if(NOT loongarch64_baseline STREQUAL "") + list(PREPEND flags "-march=${loongarch64_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on wasm32. +function(xsimd_get_wasm32_arch_flags out_list arch) + if(NOT arch STREQUAL "wasm") + message(FATAL_ERROR "Unknown xsimd architecture for wasm32: ${arch}") + endif() + set(${out_list} "-msimd128" PARENT_SCOPE) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on ppc64. +function(xsimd_get_ppc64_arch_flags out_list arch ppc64_baseline) + if(NOT arch STREQUAL "vsx") + message(FATAL_ERROR "Unknown xsimd architecture for ppc64: ${arch}") + endif() + if(ppc64_baseline STREQUAL "") + # 64-bit integer vector operations require ISA 2.07. + set(ppc64_baseline "power8") + endif() + set(${out_list} "-mcpu=${ppc64_baseline};-maltivec;-mvsx" PARENT_SCOPE) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on s390x. +function(xsimd_get_s390x_arch_flags out_list arch s390x_baseline) + if(NOT arch STREQUAL "vxe") + message(FATAL_ERROR "Unknown xsimd architecture for s390x: ${arch}") + endif() + if(s390x_baseline STREQUAL "") + # Vector-enhancements facility 1 first appeared on z14. + set(s390x_baseline "z14") + endif() + set(${out_list} "-march=${s390x_baseline};-mzvector" PARENT_SCOPE) +endfunction() + + +# Get the flag to compile with the desired xsimd arch on arm32. +function(xsimd_get_arm32_arch_flags out_list arch arm32_baseline) + if(NOT arch MATCHES "neon") + message(FATAL_ERROR "Unknown xsimd architecture for arm32: ${arch}") + endif() + + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + # Neon is mandatory on Windows on ARM. + if(NOT arm32_baseline STREQUAL "") + message(WARNING "ARM32_BASELINE is ignored on MSVC: ${arm32_baseline}") + endif() + else() + if(arm32_baseline STREQUAL "") + set(arm32_baseline "armv7-a") + endif() + # -mfloat-abi is left to the toolchain as it must match the sysroot ABI. + set(${out_list} "-march=${arm32_baseline};-mfpu=neon" PARENT_SCOPE) + endif() +endfunction() + + +function(xsimd_get_x86_arch_flags_unix out_list arch) + if(arch STREQUAL "sse2") + set(flags "-msse2;-mno-sse3") + elseif(arch STREQUAL "sse3") + set(flags "-msse3;-mno-ssse3") + elseif(arch STREQUAL "ssse3") + set(flags "-mssse3;-mno-sse4.1") + elseif(arch STREQUAL "sse4.1") + set(flags "-msse4.1;-mno-sse4.2") + elseif(arch STREQUAL "sse4.2") + set(flags "-msse4.2;-mno-avx") + elseif(arch STREQUAL "avx") + set(flags "-mavx;-mno-avx2") + elseif(arch MATCHES "avx[_-]128") + set(flags "-mavx;-mno-avx2;-DXSIMD_DEFAULT_ARCH=${arch}") + elseif(arch STREQUAL "avx2") + set(flags "-mavx2;-mno-avx512f") + elseif(arch MATCHES "avx2[_-]128") + set(flags "-mavx2;-mno-avx512f;-DXSIMD_DEFAULT_ARCH=${arch}") + elseif(arch MATCHES "^avx512") + set(flags "-mavx;-mavx2;-mavx512f") + # Extensions not enabled are explicitly disabled. + set(avx512_extensions cd dq bw er pf ifma vbmi vbmi2 vnni) + if(arch STREQUAL "avx512f") + set(enabled) + elseif(arch STREQUAL "avx512cd") + set(enabled cd) + elseif(arch STREQUAL "avx512dq") + set(enabled cd dq) + elseif(arch STREQUAL "avx512bw") + set(enabled cd dq bw) + elseif(arch STREQUAL "avx512er") + set(enabled cd dq er) + elseif(arch STREQUAL "avx512pf") + set(enabled cd dq er pf) + elseif(arch STREQUAL "avx512ifma") + set(enabled cd dq bw ifma) + elseif(arch STREQUAL "avx512vbmi") + set(enabled cd dq bw ifma vbmi) + elseif(arch STREQUAL "avx512vbmi2") + set(enabled cd dq bw ifma vbmi vbmi2) + elseif(arch STREQUAL "avx512vnni_avx512bw") + set(enabled cd dq bw vnni) + elseif(arch STREQUAL "avx512vnni_avx512vbmi2") + set(enabled cd dq bw ifma vbmi vbmi2 vnni) + elseif(arch MATCHES "^avx512vl[_-](128|256)$") + set(enabled cd dq bw) + list(APPEND flags "-mavx512vl" "-DXSIMD_DEFAULT_ARCH=${arch}") + else() + message(FATAL_ERROR "Unknown xsimd architecture for x86: ${arch}") + endif() + foreach(ext IN LISTS avx512_extensions) + if(ext IN_LIST enabled) + list(APPEND flags "-mavx512${ext}") + else() + list(APPEND flags "-mno-avx512${ext}") + endif() + endforeach() + else() + message(FATAL_ERROR "Unknown xsimd architecture for x86: ${arch}") + endif() + + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_arch_flags_msvc out_list arch sse2_flags) + set(mismatch) + if(arch STREQUAL "sse2") + set(flags ${sse2_flags}) + elseif(arch MATCHES "^(sse3|ssse3|sse4\\.1)$") + set(flags ${sse2_flags}) + set(mismatch "no /arch flag for ${arch}, falling back to SSE2") + elseif(arch STREQUAL "sse4.2") + set(flags "/arch:SSE4.2") + elseif(arch STREQUAL "avx") + set(flags "/arch:AVX") + elseif(arch STREQUAL "avx_128") + set(flags "/arch:AVX;-DXSIMD_DEFAULT_ARCH=${arch}") + elseif(arch STREQUAL "avx2") + set(flags "/arch:AVX2") + set(mismatch "/arch:AVX2 also enables FMA3") + elseif(arch STREQUAL "avx2_128") + set(flags "/arch:AVX2;-DXSIMD_DEFAULT_ARCH=${arch}") + set(mismatch "/arch:AVX2 also enables FMA3") + elseif(arch MATCHES "^avx512vl_(128|256)$") + set(flags "/arch:AVX512;-DXSIMD_DEFAULT_ARCH=${arch}") + set(mismatch "/arch:AVX512 also enables FMA3") + elseif(arch MATCHES "^avx512(f|cd|dq|bw)$") + set(flags "/arch:AVX512") + set(mismatch "/arch:AVX512 enables the full AVX512F/CD/DQ/BW/VL set and FMA3") + elseif(arch MATCHES "^avx512(er|pf|ifma|vbmi|vbmi2|vnni_avx512bw|vnni_avx512vbmi2)$") + set(flags "/arch:AVX512") + set(mismatch "no /arch flag for ${arch}, falling back to AVX512F/CD/DQ/BW/VL") + else() + message(FATAL_ERROR "Unknown xsimd architecture for x86: ${arch}") + endif() + + if(mismatch) + message(WARNING "MSVC flags do not exactly match xsimd architecture ${arch}: ${mismatch}") + endif() + + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_32_arch_flags_unix out_list arch x86_32_baseline) + xsimd_get_x86_arch_flags_unix(flags "${arch}") + if(NOT x86_32_baseline STREQUAL "") + list(PREPEND flags "-march=${x86_32_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_32_arch_flags_msvc out_list arch x86_32_baseline) + if(NOT x86_32_baseline STREQUAL "") + message(WARNING "X86_32_BASELINE is ignored on MSVC: ${x86_32_baseline}") + endif() + xsimd_get_x86_arch_flags_msvc(flags "${arch}" "/arch:SSE2") + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_32_arch_flags out_list arch x86_32_baseline) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + xsimd_get_x86_32_arch_flags_msvc(flags "${arch}" "${x86_32_baseline}") + else() + xsimd_get_x86_32_arch_flags_unix(flags "${arch}" "${x86_32_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_64_arch_flags_unix out_list arch x86_64_baseline) + xsimd_get_x86_arch_flags_unix(flags "${arch}") + # Default to the microarchitecture level just below the requested arch. + if(x86_64_baseline STREQUAL "") + if(arch MATCHES "^avx512") + set(x86_64_baseline "x86-64-v3") + elseif(arch MATCHES "^avx") + set(x86_64_baseline "x86-64-v2") + elseif(arch MATCHES "^(sse3|ssse3|sse4)") + set(x86_64_baseline "x86-64") + endif() + endif() + if(NOT x86_64_baseline STREQUAL "") + list(PREPEND flags "-march=${x86_64_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_64_arch_flags_msvc out_list arch x86_64_baseline) + if(NOT x86_64_baseline STREQUAL "") + message(WARNING "X86_64_BASELINE is ignored on MSVC: ${x86_64_baseline}") + endif() + # SSE2 is the x64 baseline, /arch:SSE2 does not exist there. + xsimd_get_x86_arch_flags_msvc(flags "${arch}" "") + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_get_x86_64_arch_flags out_list arch x86_64_baseline) + if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + xsimd_get_x86_64_arch_flags_msvc(flags "${arch}" "${x86_64_baseline}") + else() + xsimd_get_x86_64_arch_flags_unix(flags "${arch}" "${x86_64_baseline}") + endif() + set(${out_list} ${flags} PARENT_SCOPE) +endfunction() + + +function(xsimd_target_set_arch target scope) + # Names of option parameters (without arguments) + set(options) + # Names of named parameters with a single argument + set( + one_value_args + ARCH + ARM32_BASELINE ARM64_BASELINE + LOONGARCH64_BASELINE + PPC64_BASELINE + RISCV64_BASELINE + S390X_BASELINE + X86_32_BASELINE X86_64_BASELINE + ) + # Names of named parameters with a multiple arguments + set(multi_values_args) + cmake_parse_arguments(ARG "${options}" "${one_value_args}" "${multi_values_args}" ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message( + AUTHOR_WARNING + "Unrecognized options passed to ${CMAKE_CURRENT_FUNCTION}: " + "${ARG_UNPARSED_ARGUMENTS}" + ) + endif() + + if(NOT scope STREQUAL "PUBLIC" AND NOT scope STREQUAL "PRIVATE" AND NOT scope STREQUAL "INTERFACE") + message(FATAL_ERROR "scope must be PUBLIC, PRIVATE, or INTERFACE, got: ${scope}") + endif() + + if(NOT ARG_ARCH) + message(FATAL_ERROR "Select an xsimd architecture") + endif() + string(TOLOWER "${ARG_ARCH}" arch) + + xsimd_get_target(target_arch) + if(arch STREQUAL "native") + xsimd_get_native_arch_flags(flags) + elseif(arch STREQUAL "generic") + set(flags) + elseif(arch MATCHES "emulated") + xsimd_get_emulated_arch_flags(flags "${arch}") + elseif(target_arch STREQUAL "arm32") + xsimd_get_arm32_arch_flags(flags "${arch}" "${ARG_ARM32_BASELINE}") + elseif(target_arch STREQUAL "arm64") + xsimd_get_arm64_arch_flags(flags "${arch}" "${ARG_ARM64_BASELINE}") + elseif(target_arch STREQUAL "loongarch64") + xsimd_get_loongarch64_arch_flags(flags "${arch}" "${ARG_LOONGARCH64_BASELINE}") + elseif(target_arch STREQUAL "wasm32") + xsimd_get_wasm32_arch_flags(flags "${arch}") + elseif(target_arch STREQUAL "ppc64") + xsimd_get_ppc64_arch_flags(flags "${arch}" "${ARG_PPC64_BASELINE}") + elseif(target_arch STREQUAL "s390x") + xsimd_get_s390x_arch_flags(flags "${arch}" "${ARG_S390X_BASELINE}") + elseif(target_arch STREQUAL "riscv64") + xsimd_get_riscv64_arch_flags(flags "${arch}" "${ARG_RISCV64_BASELINE}") + elseif(target_arch STREQUAL "x86_32") + xsimd_get_x86_32_arch_flags(flags "${arch}" "${ARG_X86_32_BASELINE}") + elseif(target_arch STREQUAL "x86_64") + xsimd_get_x86_64_arch_flags(flags "${arch}" "${ARG_X86_64_BASELINE}") + endif() + + target_compile_options(${target} ${scope} ${flags}) +endfunction() + diff --git a/cmake/Hardening.cmake b/cmake/Hardening.cmake new file mode 100644 index 000000000..8fb9ffa8b --- /dev/null +++ b/cmake/Hardening.cmake @@ -0,0 +1,33 @@ +include(CheckCXXCompilerFlag) + + +function(xsimd_harden_trivial_auto_var_init target scope) + # Names of option parameters (without arguments) + set(options) + # Names of named parameters with a single argument + set(one_value_args PATTERN) + # Names of named parameters with a multiple arguments + set(multi_values_args) + cmake_parse_arguments(ARG "${options}" "${one_value_args}" "${multi_values_args}" ${ARGN}) + if(ARG_UNPARSED_ARGUMENTS) + message( + AUTHOR_WARNING + "Unrecoginzed options passed to ${CMAKE_CURRENT_FUNCTION}: " + "${ARG_UNPARSED_ARGUMENTS}" + ) + endif() + + if(NOT scope STREQUAL "PUBLIC" AND NOT scope STREQUAL "PRIVATE" AND NOT scope STREQUAL "INTERFACE") + message(FATAL_ERROR "scope must be PUBLIC, PRIVATE, or INTERFACE, got: ${scope}") + endif() + + if(NOT ARG_PATTERN) + set(ARG_PATTERN "pattern") + endif() + + set(flag "-ftrivial-auto-var-init=${ARG_PATTERN}") + check_cxx_compiler_flag("${flag}" XSIMD_HAS_FTRIVIAL_AUTO_VAR_INIT_${ARG_PATTERN}) + if(XSIMD_HAS_FTRIVIAL_AUTO_VAR_INIT_${ARG_PATTERN}) + target_compile_options(${target} ${scope} "${flag}") + endif() +endfunction() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e47c15b1e..87b258b45 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -17,6 +17,7 @@ if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) enable_testing() find_package(xsimd REQUIRED CONFIG) + include("${xsimd_DIR}/Architecture.cmake") endif () if(NOT CMAKE_BUILD_TYPE) @@ -32,28 +33,6 @@ string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) OPTION(XSIMD_ENABLE_WERROR "Turn on -Werror" OFF) - - -################ -# ARM SETTINGS # -################ - -OPTION(CROSS_COMPILE_ARM "cross compile for ARM targets" OFF) - -# Note: to compile on ARM (or cross compile), you may need to add the following: -# -DTARGET_ARCH="armv8-a -mfpu=neon -mfloat-abi=softfp -target arm-linux-gnueabi" -set(TARGET_ARCH "native" CACHE STRING "Target architecture arguments") -string(REGEX MATCH "emulated\\<[0-9]+\\>" TARGET_EMULATED ${TARGET_ARCH}) - -if (TARGET_EMULATED) - message(STATUS "Using emulated target: ${TARGET_EMULATED}") - set(EMULATED_COMPILE_FLAGS -DXSIMD_DEFAULT_ARCH=${TARGET_ARCH};-DXSIMD_WITH_EMULATED=1) - unset(TARGET_ARCH CACHE) -elseif (XSIMD_DEFAULT_ARCH) - message(STATUS "Forcing default arch to xsimd::${XSIMD_DEFAULT_ARCH}") - set(EMULATED_COMPILE_FLAGS -DXSIMD_DEFAULT_ARCH=${XSIMD_DEFAULT_ARCH}) -endif() - if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Intel") if (NOT WIN32 AND NOT ANDROID) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wunused-parameter -Wextra -Wreorder") @@ -61,54 +40,7 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU" set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshorten-64-to-32") endif() - if (NOT CROSS_COMPILE_ARM) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fPIC") - endif() - endif() - - if (ANDROID) - # Nothing to do here, we assume the cmake Android NDK toolchain sets the - # correct options for arm and neon. - elseif (CROSS_COMPILE_ARM) - # We're cross-compiling with clang++ on Azure Pipelines, this is all pretty specific and just for testing - set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) - set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) - set(CMAKE_THREAD_LIBS_INIT) - - set(CMAKE_SYSTEM_PROCESSOR arm) - set(CMAKE_C_COMPILER_TARGET arm-linux-gnueabi) - set(CMAKE_CXX_COMPILER_TARGET arm-linux-gnueabi) - - set(ARM_ARCH_DIRECTORY "arm-linux-gnueabi" CACHE STRING "ARM arch header dir") - set(ARM_GCC_VER "4.7.3" CACHE STRING "ARM GCC header dir") - include_directories(/usr/${ARM_ARCH_DIRECTORY}/include/c++/${ARM_GCC_VER}/${ARM_ARCH_DIRECTORY}/) - include_directories(/usr/${ARM_ARCH_DIRECTORY}/include/c++/${ARM_GCC_VER}/) - include_directories(/usr/${ARM_ARCH_DIRECTORY}/include/) - if(NOT CMAKE_CXX_FLAGS MATCHES "-march") - message(STATUS "SETTING ARCH TO ${TARGET_ARCH}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TARGET_ARCH}") - endif() - if(ARM_ARCH_DIRECTORY MATCHES "arm-linux-gnueabi") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpu=neon -mfloat-abi=softfp -target arm-linux-gnueabi") - else () - # delegating to gcc here - endif() - message(STATUS "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}") - message(STATUS "CMAKE_CXX_LINK_EXECUTABLE: ${CMAKE_CXX_LINK_EXECUTABLE}") - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^ppc64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mcpu=${TARGET_ARCH} -mtune=${TARGET_ARCH}") - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "riscv64") - # Nothing specific - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") - # Nothing specific - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "powerpc") - # Nothing specific - elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "s390x") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=z14 -mzvector") - elseif(NOT WIN32 AND NOT EMSCRIPTEN) - if(TARGET_ARCH AND NOT CMAKE_CXX_FLAGS MATCHES "-march" AND NOT CMAKE_CXX_FLAGS MATCHES "-arch" AND NOT CMAKE_OSX_ARCHITECTURES) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${TARGET_ARCH}") - endif() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fPIC") endif() endif() @@ -170,8 +102,30 @@ if(NOT MSVC) list(APPEND XSIMD_TESTS test_gnu_source.cpp) endif() +set(TARGET_ARCH "native" CACHE STRING "Target architecture arguments") + add_executable(test_xsimd ${XSIMD_TESTS}) target_link_libraries(test_xsimd PRIVATE xsimd) +# Enable SIMD flag and set low baseline to ensure we do not accidentally +# rely on other features. +if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + set(XSIMD_ARM64_BASELINE "armv8.0") +else() + set(XSIMD_ARM64_BASELINE "armv8-a") +endif() +xsimd_target_set_arch( + test_xsimd + PRIVATE + ARCH "${TARGET_ARCH}" + ARM32_BASELINE "armv7-a" + ARM64_BASELINE "${XSIMD_ARM64_BASELINE}" + LOONGARCH64_BASELINE "loongarch64" + PPC64_BASELINE "power8" + RISCV64_BASELINE "rv64gc" + S390X_BASELINE "z14" + X86_32_BASELINE "i386" + X86_64_BASELINE "x86-64" +) option(DOWNLOAD_DOCTEST OFF) find_package(doctest QUIET) @@ -209,11 +163,7 @@ endif() add_test(NAME test_xsimd COMMAND test_xsimd) -if (CROSS_COMPILE_ARM) - add_custom_target(xtest COMMAND qemu-arm -L /usr/arm-linux-gnueabi/ test_xsimd DEPENDS test_xsimd) -else() - add_custom_target(xtest COMMAND test_xsimd DEPENDS test_xsimd) -endif() +add_custom_target(xtest COMMAND test_xsimd DEPENDS test_xsimd) if (XSIMD_ENABLE_WERROR) target_compile_options(test_xsimd PRIVATE -Werror -Wall -DXSIMD_SKIP_ON_WERROR) @@ -231,10 +181,13 @@ if(EMULATED_COMPILE_FLAGS) endif() if(EMSCRIPTEN) - set_target_properties(test_xsimd PROPERTIES LINK_FLAGS "-s MODULARIZE=1 -s EXPORT_NAME=test_xsimd_wasm -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -lembind") + set_target_properties( + test_xsimd + PROPERTIES + LINK_FLAGS "-s MODULARIZE=1 -s EXPORT_NAME=test_xsimd_wasm -s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -lembind" + ) target_compile_options(test_xsimd PUBLIC --std=c++17 - PUBLIC "SHELL: -msimd128" PUBLIC "SHELL: -msse2" ) endif() diff --git a/test/test_wasm/test_wasm.sh b/test/test_wasm/test_wasm.sh index ccc4aa920..fd5e5e238 100755 --- a/test/test_wasm/test_wasm.sh +++ b/test/test_wasm/test_wasm.sh @@ -34,6 +34,7 @@ emcmake cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_CXX_STANDARD=17 \ -DDOWNLOAD_DOCTEST=ON \ + -DTARGET_ARCH=wasm \ $SRC_DIR emmake make -j4