Compile for Specific x86-64 Microarchitecture Level using CMake

Compile for Specific x86-64 Microarchitecture Level using CMake

When building C or C++ applications with CMake, compiler optimizations can be tailored to a particular CPU feature set. Modern compilers support predefined x86-64 microarchitecture levels (such as v2, v3, and v4), each enabling a group of CPU instruction set extensions. Selecting an appropriate level allows binaries to take advantage of newer CPU capabilities while maintaining compatibility constraints. This tutorial explains how to compile for specific x86-64 microarchitecture level using CMake.

  • x86-64-v2 - extends the original x86-64 baseline with instructions such as SSE3, SSSE3, SSE4.1, SSE4.2.
  • x86-64-v3 - adds AVX, AVX2, BMI1, BMI2, and related features.
  • x86-64-v4 - includes advanced extensions like AVX-512 and newer instruction sets.

By default, builds typically target a generic architecture for maximum portability. However, in performance-sensitive scenarios, it is often desirable to enable a specific x86-64 microarchitecture level explicitly. This can be achieved in CMake by introducing a configurable option and conditionally applying the corresponding compiler option.

Below is an example CMakeLists.txt demonstrating this approach:

cmake_minimum_required(VERSION 3.27)
project(myapp)

set(CMAKE_CXX_STANDARD 17)

set(X86_64_MICROARCH_LEVEL "" CACHE STRING "x86-64 microarchitecture level (v2, v3, v4)")

add_executable(${PROJECT_NAME} main.cpp)

function(target_microarch_level_option target language level)
    include(CheckCompilerFlag)
    check_compiler_flag(${language} -march=x86-64-${level} HAVE_${language}_x86_64_${level})

    if (HAVE_${language}_x86_64_${level})
        target_compile_options(${target}
                PRIVATE "$<$<COMPILE_LANGUAGE:${language}>:-march=x86-64-${level}>")
    endif ()
endfunction()

if (X86_64_MICROARCH_LEVEL)
    target_microarch_level_option(${PROJECT_NAME} C ${X86_64_MICROARCH_LEVEL})
    target_microarch_level_option(${PROJECT_NAME} CXX ${X86_64_MICROARCH_LEVEL})
endif ()

This configuration introduces a cache variable named X86_64_MICROARCH_LEVEL, allowing selection of a desired level during configuration. A helper function checks whether the compiler supports the corresponding -march option and applies it only when available, ensuring portability across toolchains.

To configure the build with a specific level:

cmake -S . -B build -DX86_64_MICROARCH_LEVEL=v2

During compilation, the appropriate optimization option (for example, -march=x86-64-v2) will be added if supported by the compiler.

-- Performing Test HAVE_C_x86_64_v2
-- Performing Test HAVE_C_x86_64_v2 - Success
-- Performing Test HAVE_CXX_x86_64_v2
-- Performing Test HAVE_CXX_x86_64_v2 - Success

Here are commands for the remaining levels:

cmake -S . -B build -DX86_64_MICROARCH_LEVEL=v3
cmake -S . -B build -DX86_64_MICROARCH_LEVEL=v4

Leave a Comment

Cancel reply

Your email address will not be published.