diff --git a/cmake/QtCompilerOptimization.cmake b/cmake/QtCompilerOptimization.cmake index e1e31893ab1..bc370247412 100644 --- a/cmake/QtCompilerOptimization.cmake +++ b/cmake/QtCompilerOptimization.cmake @@ -68,6 +68,8 @@ if(GCC OR CLANG OR QCC) endif() set(QT_CFLAGS_ARM_SVE "${__prefix}-march=armv8-a+sve") set(QT_CFLAGS_ARM_CRYPTO "${__prefix}-march=armv8-a+crypto") + set(QT_CFLAGS_LSX "${__prefix}-mlsx") + set(QT_CFLAGS_LASX "${__prefix}-mlasx") set(QT_CFLAGS_MIPS_DSP "${__prefix}-mdsp") set(QT_CFLAGS_MIPS_DSPR2 "${__prefix}-mdspr2") unset(__prefix) diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake index 189cf0e2b55..1ab8858bc68 100644 --- a/cmake/QtFeature.cmake +++ b/cmake/QtFeature.cmake @@ -1308,6 +1308,31 @@ function(qt_config_compile_test_armintrin extension label) set(TEST_subarch_${extension} "${TEST_ARMINTRIN_${extension}}" CACHE INTERNAL "${label}") endfunction() +function(qt_config_compile_test_loongarchsimd extension label) + if (DEFINED TEST_LOONGARCHSIMD_${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_LOONGARCHSIMD_${extension}" + "${CMAKE_CURRENT_BINARY_DIR}/config.tests/loongarch_simd_${extension}" + "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/loongarch_simd" + loongarch_simd + CMAKE_FLAGS ${flags}) + if(${TEST_LOONGARCHSIMD_${extension}}) + set(status_label "Success") + else() + set(status_label "Failed") + endif() + message(STATUS "Performing Test ${label} intrinsics - ${status_label}") + set(TEST_subarch_${extension} "${TEST_LOONGARCHSIMD_${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() diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake index 6fdce4082d7..4d495748f6e 100644 --- a/cmake/QtProcessConfigureArgs.cmake +++ b/cmake/QtProcessConfigureArgs.cmake @@ -245,6 +245,7 @@ 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_compile_test_loongarchsimd) defstub(qt_config_compiler_supports_flag_test) defstub(qt_config_linker_supports_flag_test) defstub(qt_configure_add_report_entry) diff --git a/config.tests/loongarch_simd/CMakeLists.txt b/config.tests/loongarch_simd/CMakeLists.txt new file mode 100644 index 00000000000..84748e9c9a7 --- /dev/null +++ b/config.tests/loongarch_simd/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +cmake_minimum_required(VERSION 3.16) +project(loongarch_simd LANGUAGES CXX) + +include(../../cmake/QtPlatformSupport.cmake) +include(../../cmake/QtCompilerOptimization.cmake) + +# FIXME: Make the this project handle a list of SIMD entries. +# FIXME: Make this project handle appending of the cflags (similar to the qmake project). +# This is needed for the loongarchsimd configure test ( +# aka we test to see if setting no SIMD (-mlsx) cflags at all, will result in their implicit +# addition by the compiler). +string(TOUPPER "${SIMD}" upper_simd) + +if(NOT DEFINED "QT_CFLAGS_${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_${upper_simd}}) +target_compile_definitions("SimdTest${SIMD}" PRIVATE QT_COMPILER_SUPPORTS_${upper_simd}) diff --git a/config.tests/loongarch_simd/main.cpp b/config.tests/loongarch_simd/main.cpp new file mode 100644 index 00000000000..2524b1e11b7 --- /dev/null +++ b/config.tests/loongarch_simd/main.cpp @@ -0,0 +1,29 @@ +// Copyright (C) 2017 Intel Corporation. +// SPDX-License-Identifier: BSD-3-Clause + +#define T(x) (QT_COMPILER_SUPPORTS_ ## x) + +#if T(LSX) +#include +void test_lsx() +{ + __m128i a = __lsx_vldi(0); + (void) __lsx_vshuf_h(__lsx_vldi(0), a, a); +} +#endif + +#if T(LASX) +#include +#include +void test_lasx() +{ + __m256i a = __lasx_xvldi(0); + __m256i b = __lasx_xvadd_b(a, a); + (void) __lasx_xvadd_b(a, b); +} +#endif + +int main() +{ + return 0; +} diff --git a/configure.cmake b/configure.cmake index cad38caccb7..08202a703d0 100644 --- a/configure.cmake +++ b/configure.cmake @@ -376,6 +376,12 @@ qt_config_compile_test_armintrin(crypto "CRYPTO") # arm: sve qt_config_compile_test_armintrin(sve "SVE") +# loongarch: lsx +qt_config_compile_test_loongarchsimd(lsx "LSX") + +# loongarch: lasx +qt_config_compile_test_loongarchsimd(lasx "LASX") + # localtime_r qt_config_compile_test(localtime_r LABEL "localtime_r()" @@ -901,6 +907,18 @@ qt_feature("shani" PRIVATE ) qt_feature_definition("shani" "QT_COMPILER_SUPPORTS_SHA" VALUE "1") qt_feature_config("shani" QMAKE_PRIVATE_CONFIG) +qt_feature("lsx" PRIVATE + LABEL "LSX" + CONDITION ( TEST_architecture_arch STREQUAL loongarch64 ) AND TEST_subarch_lsx +) +qt_feature_definition("lsx" "QT_COMPILER_SUPPORTS_LSX" VALUE "1") +qt_feature_config("lsx" QMAKE_PRIVATE_CONFIG) +qt_feature("lasx" PRIVATE + LABEL "LASX" + CONDITION ( TEST_architecture_arch STREQUAL loongarch64 ) AND TEST_subarch_lasx +) +qt_feature_definition("lasx" "QT_COMPILER_SUPPORTS_LASX" VALUE "1") +qt_feature_config("lasx" QMAKE_PRIVATE_CONFIG) qt_feature("mips_dsp" PRIVATE LABEL "DSP" CONDITION ( TEST_architecture_arch STREQUAL mips ) AND TEST_arch_${TEST_architecture_arch}_subarch_dsp @@ -1301,6 +1319,12 @@ qt_configure_add_summary_entry( MESSAGE "ARM Extensions" CONDITION ( TEST_architecture_arch STREQUAL arm ) OR ( TEST_architecture_arch STREQUAL arm64 ) ) +qt_configure_add_summary_entry( + TYPE "featureList" + ARGS "lsx lasx" + MESSAGE "LOONGARCH Extensions" + CONDITION ( TEST_architecture_arch STREQUAL loongarch64 ) +) qt_configure_add_summary_entry( ARGS "mips_dsp" CONDITION ( TEST_architecture_arch STREQUAL mips ) diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index ae58326289f..ebaf8d4de04 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -119,6 +119,8 @@ QMAKE_CFLAGS_VAES += -mvaes QMAKE_CFLAGS_NEON += -mfpu=neon QMAKE_CFLAGS_MIPS_DSP += -mdsp QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2 +QMAKE_CFLAGS_LSX += -mlsx +QMAKE_CFLAGS_LASX += -mlasx # -march=haswell is supported as of GCC 4.9 and Clang 3.6 QMAKE_CFLAGS_ARCH_HASWELL = -march=core-avx2 diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf index 8e041297d2f..a825fdd4a6f 100644 --- a/mkspecs/features/simd.prf +++ b/mkspecs/features/simd.prf @@ -146,6 +146,8 @@ addSimdCompiler(rdseed) addSimdCompiler(neon) addSimdCompiler(mips_dsp) addSimdCompiler(mips_dspr2) +addSimdCompiler(lsx) +addSimdCompiler(lasx) # Haswell sub-architecture defineTest(addSimdArch) { diff --git a/src/corelib/global/qsimd.cpp b/src/corelib/global/qsimd.cpp index 6f1e12312f9..15755b1ca22 100644 --- a/src/corelib/global/qsimd.cpp +++ b/src/corelib/global/qsimd.cpp @@ -33,7 +33,7 @@ # endif #elif defined(Q_OS_LINUX) && defined(Q_PROCESSOR_MIPS_32) # include "private/qcore_unix_p.h" -#elif QT_CONFIG(getauxval) && defined(Q_PROCESSOR_ARM) +#elif QT_CONFIG(getauxval) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_LOONGARCH)) # include // the kernel header definitions for HWCAP_* @@ -95,6 +95,19 @@ static const char features_string[] = " dsp\0" " dspr2\0"; +static const int features_indices[] = { + 0, 1, 6 +}; +#elif defined(Q_PROCESSOR_LOONGARCH) +/* Data: + lsx + lasx +*/ +static const char features_string[] = + "\0" + " lsx\0" + " lasx\0"; + static const int features_indices[] = { 0, 1, 6 }; @@ -192,6 +205,40 @@ static inline quint64 detectProcessorFeatures() return features; } +#elif defined(Q_PROCESSOR_LOONGARCH) +static inline quint64 detectProcessorFeatures() +{ + quint64 features = 0; +# if QT_CONFIG(getauxval) + quint64 hwcap = getauxval(AT_HWCAP); + + if (hwcap & HWCAP_LOONGARCH_LSX) + features |= CpuFeatureLSX; + if (hwcap & HWCAP_LOONGARCH_LASX) + features |= CpuFeatureLASX; +# else + enum LoongArchFeatures { + LOONGARCH_CFG2 = 0x2, + LOONGARCH_CFG2_LSX = (1 << 6), + LOONGARCH_CFG2_LASX = (1 << 7) + }; + + quint64 reg = 0; + + __asm__ volatile( + "cpucfg %0, %1 \n\t" + : "+&r"(reg) + : "r"(LOONGARCH_CFG2) + ); + + if (reg & LOONGARCH_CFG2_LSX) + features |= CpuFeatureLSX; + if (reg & LOONGARCH_CFG2_LASX) + features |= CpuFeatureLASX; +# endif + return features; +} + #elif defined(Q_PROCESSOR_X86) #ifdef Q_PROCESSOR_X86_32 diff --git a/src/corelib/global/qsimd.h b/src/corelib/global/qsimd.h index 8ee3e9b15d8..7132d650872 100644 --- a/src/corelib/global/qsimd.h +++ b/src/corelib/global/qsimd.h @@ -21,6 +21,8 @@ * sse4_1 | x86 * sse4_2 | x86 * avx | x86 + * lsx | loongarch + * lasx | loongarch * * Code can use the following constructs to determine compiler support & status: * - #if QT_COMPILER_USES(XXX) (e.g: #if QT_COMPILER_USES(neon) or QT_COMPILER_USES(sse4_1) @@ -53,6 +55,20 @@ # define QT_COMPILER_USES_mips_dspr2 -1 #endif +#if defined(Q_PROCESSOR_LOONGARCH) && defined(__loongarch_sx) +# include +# define QT_COMPILER_USES_lsx 1 +#else +# define QT_COMPILER_USES_lsx -1 +#endif + +#if defined(Q_PROCESSOR_LOONGARCH) && defined(__loongarch_asx) +# include +# define QT_COMPILER_USES_lasx 1 +#else +# define QT_COMPILER_USES_lasx -1 +#endif + #if defined(Q_PROCESSOR_X86) && defined(Q_CC_MSVC) // MSVC doesn't define __SSE2__, so do it ourselves # if (defined(_M_X64) || _M_IX86_FP >= 2) && defined(QT_COMPILER_SUPPORTS_SSE2) diff --git a/src/corelib/global/qsimd_p.h b/src/corelib/global/qsimd_p.h index 86c23418fc6..233c7a3167a 100644 --- a/src/corelib/global/qsimd_p.h +++ b/src/corelib/global/qsimd_p.h @@ -120,6 +120,9 @@ QT_WARNING_DISABLE_INTEL(103) # if !defined(__MIPS_DSPR2__) && defined(__mips_dspr2) && defined(Q_PROCESSOR_MIPS_32) # define __MIPS_DSPR2__ # endif +#elif defined(Q_PROCESSOR_LOONGARCH) +# define QT_COMPILER_SUPPORTS_HERE(x) QT_COMPILER_SUPPORTS(x) +# define QT_FUNCTION_TARGET(x) #elif defined(Q_PROCESSOR_X86) # if defined(Q_CC_CLANG) && defined(Q_CC_MSVC) # define QT_COMPILER_SUPPORTS_HERE(x) (__ ## x ## __) @@ -383,6 +386,9 @@ enum CPUFeatures { #elif defined(Q_PROCESSOR_MIPS) CpuFeatureDSP = 2, CpuFeatureDSPR2 = 4, +#elif defined(Q_PROCESSOR_LOONGARCH) + CpuFeatureLSX = 2, + CpuFeatureLASX = 4, #endif }; @@ -411,6 +417,12 @@ static const uint64_t qCompilerCpuFeatures = 0 #endif #if defined __mips_dspr2 | CpuFeatureDSPR2 +#endif +#if defined __loongarch_sx + | CpuFeatureLSX +#endif +#if defined __loongarch_asx + | CpuFeatureLASX #endif ; #endif