xref: /aosp_15_r20/external/webp/cmake/cpu.cmake (revision b2055c353e87c8814eb2b6b1b11112a1562253bd)
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