go-libwebp

Experimental translation from libwebp to Go source.
Log | Files | Refs | README | LICENSE

cpu.cmake (6372B)


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