Fix runtime CPU feature detection for ARM
We had no routines for checking compiler support instead only compiler currently enabled. Change-Id: I5543e4cff2b0bab494e11abf257061147baaf0d7 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
parent
cc8a71e211
commit
70738cf726
@ -67,6 +67,7 @@ if(GCC OR CLANG OR QCC)
|
||||
set(QT_CFLAGS_NEON "${__prefix}-mfpu=neon")
|
||||
endif()
|
||||
set(QT_CFLAGS_ARM_SVE "${__prefix}-march=armv8-a+sve")
|
||||
set(QT_CFLAGS_ARM_CRYPTO "${__prefix}-march=armv8-a+crypto")
|
||||
set(QT_CFLAGS_MIPS_DSP "${__prefix}-mdsp")
|
||||
set(QT_CFLAGS_MIPS_DSPR2 "${__prefix}-mdspr2")
|
||||
unset(__prefix)
|
||||
|
@ -1283,6 +1283,31 @@ function(qt_config_compile_test_x86simd extension label)
|
||||
set(TEST_subarch_${extension} "${TEST_X86SIMD_${extension}}" CACHE INTERNAL "${label}")
|
||||
endfunction()
|
||||
|
||||
function(qt_config_compile_test_armintrin extension label)
|
||||
if (DEFINED TEST_ARMINTRIN_${extension})
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(flags "-DSIMD:string=${extension}")
|
||||
|
||||
qt_get_platform_try_compile_vars(platform_try_compile_vars)
|
||||
list(APPEND flags ${platform_try_compile_vars})
|
||||
|
||||
message(STATUS "Performing Test ${label} intrinsics")
|
||||
try_compile("TEST_ARMINTRIN_${extension}"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/config.tests/armintrin_${extension}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/config.tests/armintrin"
|
||||
armintrin
|
||||
CMAKE_FLAGS ${flags})
|
||||
if(${TEST_ARMINTRIN_${extension}})
|
||||
set(status_label "Success")
|
||||
else()
|
||||
set(status_label "Failed")
|
||||
endif()
|
||||
message(STATUS "Performing Test ${label} intrinsics - ${status_label}")
|
||||
set(TEST_subarch_${extension} "${TEST_ARMINTRIN_${extension}}" CACHE INTERNAL "${label}")
|
||||
endfunction()
|
||||
|
||||
function(qt_config_compile_test_machine_tuple label)
|
||||
if(DEFINED TEST_MACHINE_TUPLE OR NOT (LINUX OR HURD) OR ANDROID)
|
||||
return()
|
||||
|
@ -244,6 +244,7 @@ endmacro()
|
||||
|
||||
defstub(qt_add_qmake_lib_dependency)
|
||||
defstub(qt_config_compile_test)
|
||||
defstub(qt_config_compile_test_armintrin)
|
||||
defstub(qt_config_compile_test_machine_tuple)
|
||||
defstub(qt_config_compile_test_x86simd)
|
||||
defstub(qt_config_compiler_supports_flag_test)
|
||||
|
@ -248,7 +248,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:"
|
||||
#if defined(__ARM_FEATURE_CRC32) || (defined(_M_ARM64) && __ARM_ARCH >= 800)
|
||||
" crc32"
|
||||
#endif
|
||||
#if defined(__ARM_FEATURE_CRYPTO) || (defined(_M_ARM64) && __ARM_ARCH >= 800)
|
||||
#if defined(__ARM_FEATURE_AES) || defined(__ARM_FEATURE_CRYPTO) || (defined(_M_ARM64) && __ARM_ARCH >= 800)
|
||||
" crypto"
|
||||
#endif
|
||||
#ifdef __ARM_FEATURE_SVE
|
||||
|
21
config.tests/armintrin/CMakeLists.txt
Normal file
21
config.tests/armintrin/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
# Copyright (C) 2024 The Qt Company Ltd.
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(armintrin LANGUAGES CXX)
|
||||
|
||||
include(../../cmake/QtPlatformSupport.cmake)
|
||||
include(../../cmake/QtCompilerOptimization.cmake)
|
||||
|
||||
string(TOUPPER "${SIMD}" upper_simd)
|
||||
|
||||
if(NOT DEFINED "QT_CFLAGS_ARM_${upper_simd}")
|
||||
# Don't use CMake error() because a configure error also fails the try_compile() call.
|
||||
# Instead use a compile flag that doesn't exist to force a compiler error.
|
||||
set(QT_CFLAGS_${upper_simd} "--qt-cflags-not-found")
|
||||
endif()
|
||||
|
||||
add_executable("SimdTest${SIMD}")
|
||||
target_sources("SimdTest${SIMD}" PRIVATE main.cpp)
|
||||
target_compile_options("SimdTest${SIMD}" PRIVATE ${QT_CFLAGS_ARM_${upper_simd}})
|
||||
target_compile_definitions("SimdTest${SIMD}" PRIVATE QT_COMPILER_SUPPORTS_${upper_simd})
|
37
config.tests/armintrin/main.cpp
Normal file
37
config.tests/armintrin/main.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2024
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#if defined QT_COMPILER_SUPPORTS_CRYPTO
|
||||
#include <arm_neon.h>
|
||||
void aeshash(uint8x16_t &state0, uint8x16_t data)
|
||||
{
|
||||
auto state1 = state0;
|
||||
state0 = vaeseq_u8(state0, data);
|
||||
state0 = vaesmcq_u8(state0);
|
||||
auto state2 = state0;
|
||||
state0 = vaeseq_u8(state0, state1);
|
||||
state0 = vaesmcq_u8(state0);
|
||||
auto state3 = state0;
|
||||
state0 = vaeseq_u8(state0, state2);
|
||||
state0 = vaesmcq_u8(state0);
|
||||
state0 = veorq_u8(state0, state3);
|
||||
}
|
||||
#elif defined QT_COMPILER_SUPPORTS_SVE
|
||||
#include <arm_sve.h>
|
||||
void qt_memfill64_sve(uint64_t *dest, uint64_t color, int64_t count)
|
||||
{
|
||||
int64_t i = 0;
|
||||
const svuint64_t vdup = svdup_n_u64(color);
|
||||
svbool_t pg = svwhilelt_b64_s64(i, count);
|
||||
do {
|
||||
svst1_u64(pg, (uint64_t*)(dest + i), vdup);
|
||||
i += svcntd();
|
||||
pg = svwhilelt_b64_s64(i, count);
|
||||
} while (svptest_any(svptrue_b64(), pg));
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
@ -370,6 +370,12 @@ qt_config_compile_test_x86simd(avx512vbmi2 "AVX512VBMI2")
|
||||
# x86: vaes
|
||||
qt_config_compile_test_x86simd(vaes "VAES")
|
||||
|
||||
# arm: crypto
|
||||
qt_config_compile_test_armintrin(crypto "CRYPTO")
|
||||
|
||||
# arm: sve
|
||||
qt_config_compile_test_armintrin(sve "SVE")
|
||||
|
||||
# localtime_r
|
||||
qt_config_compile_test(localtime_r
|
||||
LABEL "localtime_r()"
|
||||
@ -923,7 +929,7 @@ qt_feature_definition("arm_crc32" "QT_COMPILER_SUPPORTS_CRC32" VALUE "1")
|
||||
qt_feature_config("arm_crc32" QMAKE_PRIVATE_CONFIG)
|
||||
qt_feature("arm_crypto" PRIVATE
|
||||
LABEL "AES"
|
||||
CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND TEST_arch_${TEST_architecture_arch}_subarch_crypto
|
||||
CONDITION ( ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) AND ( TEST_arch_${TEST_architecture_arch}_subarch_crypto OR TEST_subarch_crypto )
|
||||
)
|
||||
qt_feature_definition("arm_crypto" "QT_COMPILER_SUPPORTS_CRYPTO" VALUE "1")
|
||||
qt_feature_definition("arm_crypto" "QT_COMPILER_SUPPORTS_AES" VALUE "1")
|
||||
@ -931,7 +937,7 @@ qt_feature_config("arm_crypto" QMAKE_PRIVATE_CONFIG)
|
||||
|
||||
qt_feature("arm_sve" PRIVATE
|
||||
LABEL "SVE"
|
||||
CONDITION ( TEST_architecture_arch STREQUAL arm64 ) AND TEST_arch_${TEST_architecture_arch}_subarch_sve
|
||||
CONDITION ( TEST_architecture_arch STREQUAL arm64 ) AND ( TEST_arch_${TEST_architecture_arch}_subarch_sve OR TEST_subarch_sve )
|
||||
)
|
||||
qt_feature_definition("arm_sve" "QT_COMPILER_SUPPORTS_SVE" VALUE "1")
|
||||
qt_feature_config("arm_sve" QMAKE_PRIVATE_CONFIG)
|
||||
@ -1291,7 +1297,7 @@ qt_configure_add_summary_entry(
|
||||
)
|
||||
qt_configure_add_summary_entry(
|
||||
TYPE "featureList"
|
||||
ARGS "neon arm_crc32 arm_crypto"
|
||||
ARGS "neon arm_crc32 arm_crypto arm_sve"
|
||||
MESSAGE "ARM Extensions"
|
||||
CONDITION ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 )
|
||||
)
|
||||
|
@ -99,7 +99,7 @@ QT_WARNING_DISABLE_INTEL(103)
|
||||
|
||||
#define QT_COMPILER_SUPPORTS(x) (QT_COMPILER_SUPPORTS_ ## x - 0)
|
||||
|
||||
#if defined(Q_PROCESSOR_ARM)
|
||||
#if defined(Q_PROCESSOR_ARM_64)
|
||||
# define QT_COMPILER_SUPPORTS_HERE(x) ((__ARM_FEATURE_ ## x) || (__ ## x ## __) || QT_COMPILER_SUPPORTS(x))
|
||||
# if defined(Q_CC_GNU)
|
||||
/* GCC requires attributes for a function */
|
||||
@ -107,6 +107,10 @@ QT_WARNING_DISABLE_INTEL(103)
|
||||
# else
|
||||
# define QT_FUNCTION_TARGET(x)
|
||||
# endif
|
||||
#elif defined(Q_PROCESSOR_ARM_32)
|
||||
/* We do not support for runtime CPU feature switching on ARM32 */
|
||||
# define QT_COMPILER_SUPPORTS_HERE(x) ((__ARM_FEATURE_ ## x) || (__ ## x ## __))
|
||||
# define QT_FUNCTION_TARGET(x)
|
||||
#elif defined(Q_PROCESSOR_MIPS)
|
||||
# define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __)
|
||||
# define QT_FUNCTION_TARGET(x)
|
||||
@ -345,7 +349,7 @@ inline uint32x4_t qvsetq_n_u32(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
|
||||
|
||||
#if defined(Q_PROCESSOR_ARM_64)
|
||||
#if defined(Q_CC_CLANG)
|
||||
#define QT_FUNCTION_TARGET_STRING_AES "crypto"
|
||||
#define QT_FUNCTION_TARGET_STRING_AES "aes"
|
||||
#define QT_FUNCTION_TARGET_STRING_CRC32 "crc"
|
||||
#define QT_FUNCTION_TARGET_STRING_SVE "sve"
|
||||
#elif defined(Q_CC_GNU)
|
||||
@ -395,7 +399,7 @@ static const uint64_t qCompilerCpuFeatures = 0
|
||||
#if defined __ARM_FEATURE_CRC32
|
||||
| CpuFeatureCRC32
|
||||
#endif
|
||||
#if defined __ARM_FEATURE_CRYPTO
|
||||
#if defined (__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)
|
||||
| CpuFeatureAES
|
||||
#endif
|
||||
#endif // Q_OS_LINUX && Q_PROCESSOR_ARM64
|
||||
|
@ -732,7 +732,7 @@ static size_t aeshash(const uchar *p, size_t len, size_t seed, size_t seed2) noe
|
||||
|
||||
// Compared to x86 AES, ARM splits each round into two instructions
|
||||
// and includes the pre-xor instead of the post-xor.
|
||||
const auto hash16bytes = [](uint8x16_t &state0, uint8x16_t data) {
|
||||
const auto hash16bytes = [](uint8x16_t &state0, uint8x16_t data) QT_FUNCTION_TARGET(AES) {
|
||||
auto state1 = state0;
|
||||
state0 = vaeseq_u8(state0, data);
|
||||
state0 = vaesmcq_u8(state0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user