1*b2055c35SXin Li# Copyright (c) 2021 Google LLC. 2*b2055c35SXin Li# 3*b2055c35SXin Li# Use of this source code is governed by a BSD-style license 4*b2055c35SXin Li# that can be found in the LICENSE file in the root of the source 5*b2055c35SXin Li# tree. An additional intellectual property rights grant can be found 6*b2055c35SXin Li# in the file PATENTS. All contributing project authors may 7*b2055c35SXin Li# be found in the AUTHORS file in the root of the source tree. 8*b2055c35SXin Li 9*b2055c35SXin Li# Check for SIMD extensions. 10*b2055c35SXin Liinclude(CMakePushCheckState) 11*b2055c35SXin Li 12*b2055c35SXin Lifunction(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD) 13*b2055c35SXin Li if(NOT ENABLE_SIMD) 14*b2055c35SXin Li message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.") 15*b2055c35SXin Li set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) 16*b2055c35SXin Li return() 17*b2055c35SXin Li endif() 18*b2055c35SXin Li unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE) 19*b2055c35SXin Li cmake_push_check_state() 20*b2055c35SXin Li set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}) 21*b2055c35SXin Li check_c_source_compiles( 22*b2055c35SXin Li " 23*b2055c35SXin Li #include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\" 24*b2055c35SXin Li int main(void) { 25*b2055c35SXin Li #if !defined(WEBP_USE_${WEBP_SIMD_FLAG}) 26*b2055c35SXin Li this is not valid code 27*b2055c35SXin Li #endif 28*b2055c35SXin Li return 0; 29*b2055c35SXin Li } 30*b2055c35SXin Li " 31*b2055c35SXin Li WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) 32*b2055c35SXin Li cmake_pop_check_state() 33*b2055c35SXin Li if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG}) 34*b2055c35SXin Li set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE) 35*b2055c35SXin Li else() 36*b2055c35SXin Li set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE) 37*b2055c35SXin Li endif() 38*b2055c35SXin Liendfunction() 39*b2055c35SXin Li 40*b2055c35SXin Li# those are included in the names of WEBP_USE_* in c++ code. 41*b2055c35SXin Liset(WEBP_SIMD_FLAGS "SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA") 42*b2055c35SXin Liset(WEBP_SIMD_FILE_EXTENSIONS 43*b2055c35SXin Li "_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c") 44*b2055c35SXin Liif(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC") 45*b2055c35SXin Li # With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2 46*b2055c35SXin Li # or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4 47*b2055c35SXin Li # flag, but an AVX one. Using that with SSE4 code risks generating illegal 48*b2055c35SXin Li # instructions when used on machines with SSE4 only. The flags are left for 49*b2055c35SXin Li # older (untested) versions to avoid any potential compatibility issues. 50*b2055c35SXin Li if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:") 51*b2055c35SXin Li set(SIMD_ENABLE_FLAGS) 52*b2055c35SXin Li else() 53*b2055c35SXin Li set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;") 54*b2055c35SXin Li endif() 55*b2055c35SXin Li set(SIMD_DISABLE_FLAGS) 56*b2055c35SXin Lielse() 57*b2055c35SXin Li set(SIMD_ENABLE_FLAGS "-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa") 58*b2055c35SXin Li set(SIMD_DISABLE_FLAGS "-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa") 59*b2055c35SXin Liendif() 60*b2055c35SXin Li 61*b2055c35SXin Liset(WEBP_SIMD_FILES_TO_INCLUDE) 62*b2055c35SXin Liset(WEBP_SIMD_FLAGS_TO_INCLUDE) 63*b2055c35SXin Li 64*b2055c35SXin Liif(ANDROID AND ANDROID_ABI) 65*b2055c35SXin Li if(${ANDROID_ABI} STREQUAL "armeabi-v7a") 66*b2055c35SXin Li # This is because Android studio uses the configuration "-march=armv7-a 67*b2055c35SXin Li # -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon 68*b2055c35SXin Li # optimizations but should (as this configuration does not exist anymore). 69*b2055c35SXin Li set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ") 70*b2055c35SXin Li endif() 71*b2055c35SXin Liendif() 72*b2055c35SXin Li 73*b2055c35SXin Lilist(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH) 74*b2055c35SXin Limath(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1") 75*b2055c35SXin Li 76*b2055c35SXin Liforeach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE}) 77*b2055c35SXin Li # With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the source 78*b2055c35SXin Li # will fail to compile. 79*b2055c35SXin Li if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 2) 80*b2055c35SXin Li break() 81*b2055c35SXin Li endif() 82*b2055c35SXin Li 83*b2055c35SXin Li list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG) 84*b2055c35SXin Li 85*b2055c35SXin Li # First try with no extra flag added as the compiler might have default flags 86*b2055c35SXin Li # (especially on Android). 87*b2055c35SXin Li unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE) 88*b2055c35SXin Li cmake_push_check_state() 89*b2055c35SXin Li set(CMAKE_REQUIRED_FLAGS) 90*b2055c35SXin Li webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) 91*b2055c35SXin Li if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG}) 92*b2055c35SXin Li list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 93*b2055c35SXin Li if(EMSCRIPTEN) 94*b2055c35SXin Li set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}") 95*b2055c35SXin Li endif() 96*b2055c35SXin Li set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG}) 97*b2055c35SXin Li webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD}) 98*b2055c35SXin Li else() 99*b2055c35SXin Li if(MSVC AND SIMD_ENABLE_FLAGS) 100*b2055c35SXin Li # The detection for SSE2/SSE4 support under MSVC is based on the compiler 101*b2055c35SXin Li # version so e.g., clang-cl will require flags to enable the assembly. 102*b2055c35SXin Li list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 103*b2055c35SXin Li else() 104*b2055c35SXin Li set(SIMD_COMPILE_FLAG " ") 105*b2055c35SXin Li endif() 106*b2055c35SXin Li endif() 107*b2055c35SXin Li # Check which files we should include or not. 108*b2055c35SXin Li list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION) 109*b2055c35SXin Li file(GLOB SIMD_FILES 110*b2055c35SXin Li "${CMAKE_CURRENT_LIST_DIR}/../sharpyuv/*${WEBP_SIMD_FILE_EXTENSION}" 111*b2055c35SXin Li "${CMAKE_CURRENT_LIST_DIR}/../src/dsp/*${WEBP_SIMD_FILE_EXTENSION}") 112*b2055c35SXin Li if(WEBP_HAVE_${WEBP_SIMD_FLAG}) 113*b2055c35SXin Li # Memorize the file and flags. 114*b2055c35SXin Li foreach(FILE ${SIMD_FILES}) 115*b2055c35SXin Li list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE}) 116*b2055c35SXin Li list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG}) 117*b2055c35SXin Li endforeach() 118*b2055c35SXin Li else() 119*b2055c35SXin Li # Remove the file from the list. 120*b2055c35SXin Li foreach(FILE ${SIMD_FILES}) 121*b2055c35SXin Li list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE}) 122*b2055c35SXin Li endforeach() 123*b2055c35SXin Li # Explicitly disable SIMD. 124*b2055c35SXin Li if(SIMD_DISABLE_FLAGS) 125*b2055c35SXin Li list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG) 126*b2055c35SXin Li include(CheckCCompilerFlag) 127*b2055c35SXin Li if(SIMD_COMPILE_FLAG) 128*b2055c35SXin Li # Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal 129*b2055c35SXin Li # variable at parent scope while check_cxx_source_compiles() continues 130*b2055c35SXin Li # to set an internal cache variable, so we unset both to avoid the 131*b2055c35SXin Li # failure / success state persisting between checks. See 132*b2055c35SXin Li # https://gitlab.kitware.com/cmake/cmake/-/issues/21207. 133*b2055c35SXin Li unset(HAS_COMPILE_FLAG) 134*b2055c35SXin Li unset(HAS_COMPILE_FLAG CACHE) 135*b2055c35SXin Li check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG) 136*b2055c35SXin Li if(HAS_COMPILE_FLAG) 137*b2055c35SXin Li # Do one more check for Clang to circumvent CMake issue 13194. 138*b2055c35SXin Li if(COMMAND check_compiler_flag_common_patterns) 139*b2055c35SXin Li # Only in CMake 3.0 and above. 140*b2055c35SXin Li check_compiler_flag_common_patterns(COMMON_PATTERNS) 141*b2055c35SXin Li else() 142*b2055c35SXin Li set(COMMON_PATTERNS) 143*b2055c35SXin Li endif() 144*b2055c35SXin Li set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG}) 145*b2055c35SXin Li check_c_source_compiles( 146*b2055c35SXin Li "int main(void) {return 0;}" FLAG_${SIMD_COMPILE_FLAG} FAIL_REGEX 147*b2055c35SXin Li "warning: argument unused during compilation:" ${COMMON_PATTERNS}) 148*b2055c35SXin Li if(NOT FLAG_${SIMD_COMPILE_FLAG}) 149*b2055c35SXin Li unset(HAS_COMPILE_FLAG) 150*b2055c35SXin Li unset(HAS_COMPILE_FLAG CACHE) 151*b2055c35SXin Li endif() 152*b2055c35SXin Li endif() 153*b2055c35SXin Li if(HAS_COMPILE_FLAG) 154*b2055c35SXin Li set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}") 155*b2055c35SXin Li endif() 156*b2055c35SXin Li endif() 157*b2055c35SXin Li endif() 158*b2055c35SXin Li endif() 159*b2055c35SXin Li cmake_pop_check_state() 160*b2055c35SXin Liendforeach() 161