Merge branch 'feat/llvm-opt-integration' into 'master'

feat(compiler): add ESP-IDF LLVM optimization enablement framework

See merge request espressif/esp-idf!51154
This commit is contained in:
Marius Vikhammer
2026-09-07 10:11:37 +08:00
24 changed files with 742 additions and 2 deletions

View File

@@ -471,6 +471,74 @@ This can be useful if there is upstream code that emits warnings.
When using these commands, place them after the call to ``idf_component_register`` in the component CMakeLists file.
.. only:: esp32p4
.. _cmake-llvm-optimizations:
LLVM Optimizations
^^^^^^^^^^^^^^^^^^
ESP-IDF can apply extra LLVM/Clang optimizations to selected sources. Enable the options in menuconfig. Mark a component or a file list in CMake. ESP-IDF sets the corresponding compiler flags, so projects do not write those flags by hand.
In :ref:`project-configuration-menu`, enable :menuitem:`CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION` under Compiler options > LLVM optimizations. Flags apply only to components or source files you select in CMake.
Apply to the whole component:
.. code-block:: cmake
idf_component_register(SRCS "foo.c" "bar.c"
INCLUDE_DIRS "."
ENABLE_LLVM_OPT)
Apply to one or more source files (call after ``idf_component_register``):
.. code-block:: cmake
idf_component_enable_llvm_opt(SRCS "foo.c" "bar.c")
Source paths must match the paths passed to ``idf_component_register``. As with ``set_source_files_properties``, source-level selection is not supported with sources discovered through ``SRC_DIRS``.
Third-party components such as LVGL do not call these helpers. After ``idf_component_register``, get the dependency's library target and apply the exported flags with standard CMake. ``IDF_LLVM_OPT_ALL`` holds the flags for every LLVM optimization enabled in menuconfig; ``IDF_LLVM_OPT_MEMCPY`` holds only the flags for :menuitem:`CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION`. Both are empty when those options are off or the compiler is not Clang:
Library target of the managed ``lvgl`` component (registry name :code:`lvgl__lvgl`), not its source list:
.. code-block:: cmake
idf_component_get_property(lvgl_lib "lvgl__lvgl" COMPONENT_LIB)
if(IDF_LLVM_OPT_ALL)
target_compile_options(${lvgl_lib} PRIVATE ${IDF_LLVM_OPT_ALL})
endif()
To apply only the memcpy optimization:
.. code-block:: cmake
idf_component_get_property(lvgl_lib "lvgl__lvgl" COMPONENT_LIB)
if(IDF_LLVM_OPT_MEMCPY)
target_compile_options(${lvgl_lib} PRIVATE ${IDF_LLVM_OPT_MEMCPY})
endif()
This does not patch the third-party CMakeLists. Do not apply it to every source in a large component; see the limitations below.
Advanced users can append extra Clang or LLVM flags. These are applied together with any LLVM optimizations enabled in menuconfig. Omit ``SRCS`` to apply them to the whole component:
.. code-block:: cmake
idf_component_enable_llvm_opt(
SRCS "foo.c"
OPTIONS "-mllvm=-my-custom-llvm-option")
The current menuconfig option speeds up ``memcpy`` using the RISC-V PIE extension. Install and select the Espressif Clang toolchain with ``IDF_TOOLCHAIN=clang``; IDF does not substitute flags when the active compiler is GCC. Further menuconfig options can be added later without changing the CMake enable API. See :example:`system/llvm_opt` and :example:`system/llvm_memcpy_opt`.
Limitations:
- Requires the Espressif Clang toolchain. ``ENABLE_LLVM_OPT``, ``idf_component_enable_llvm_opt``, ``IDF_LLVM_OPT_ALL``, and ``IDF_LLVM_OPT_MEMCPY`` have no effect when the selected compiler is not Clang.
- Currently validated on ESP32-P4 only.
- Apply only to hot paths. Prefer a measured file list. Results depend on alignment, size, chip revision, and flash/cache layout.
- Do **not** enable this for the whole project or for every source in a large component. The generated code uses the PIE coprocessor. The first PIE instruction in a task that does not currently own PIE traps into the kernel, which lazy-saves the previous owner's registers and restores this task's; that switch repeats for every such task and can make the application slower overall. Extra code size (I-cache) can also hurt, but is secondary. See :doc:`../api-reference/system/freertos_idf`.
- Do not use this memcpy option from an ISR: PIE coprocessor use in interrupt context is not allowed and aborts.
- Do not treat the CMake markers as a global ``-O`` replacement.
.. _component-configuration:
@@ -1565,6 +1633,10 @@ The arguments for ``idf_component_register`` include:
- KCONFIG_PROJBUILD - override the default Kconfig.projbuild file
- WHOLE_ARCHIVE - if specified, the component library is surrounded by ``-Wl,--whole-archive``, ``-Wl,--no-whole-archive`` when linked. This has the same effect as setting ``WHOLE_ARCHIVE`` component property.
.. only:: esp32p4
On ESP32-P4, ``idf_component_register`` also accepts ``ENABLE_LLVM_OPT`` to apply LLVM optimizations enabled in menuconfig to all source files in the component. Ignored when the selected compiler is not Clang. See :ref:`cmake-llvm-optimizations`.
The following are used for :ref:`embedding data into the component <cmake_embed_data>`, and is considered as source files when determining if a component is config-only. This means that even if the component does not specify source files, a static library is still created internally for the component if it specifies either:
- EMBED_FILES - binary files to be embedded in the component

View File

@@ -471,6 +471,74 @@ ESP-IDF 在搜索所有待构建的组件时,会按照以下优先级搜索组
请注意,上述两条命令只能在组件 CMakeLists 文件的 ``idf_component_register`` 命令之后调用。
.. only:: esp32p4
.. _cmake-llvm-optimizations:
LLVM 优化
^^^^^^^^^^^^^^^^^^
ESP-IDF 可以把额外的 LLVM/Clang 优化应用到选定的源文件上:在 menuconfig 中启用相应选项,再在 CMake 里标记组件或文件列表。menuconfig 选项对应的编译器标志由 ESP-IDF 设置,项目无需手写这些标志。
:ref:`project-configuration-menu` 的 Compiler options > LLVM optimizations 下启用 :menuitem:`CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION`。相关标志仅应用于你在 CMake 中选定的组件或源文件。
应用于整个组件:
.. code-block:: cmake
idf_component_register(SRCS "foo.c" "bar.c"
INCLUDE_DIRS "."
ENABLE_LLVM_OPT)
应用于一个或多个源文件(在 ``idf_component_register`` 之后调用):
.. code-block:: cmake
idf_component_enable_llvm_opt(SRCS "foo.c" "bar.c")
源文件路径必须与传递给 ``idf_component_register`` 的路径一致。与 ``set_source_files_properties`` 一样,通过 ``SRC_DIRS`` 查找到的源文件不支持按文件选择优化。
LVGL 等第三方组件不会调用上述 helper。在 ``idf_component_register`` 之后,用标准 CMake 命令取出依赖的库 target 并套用导出的标志。``IDF_LLVM_OPT_ALL`` 包含 menuconfig 中已启用的全部 LLVM 优化对应的标志;``IDF_LLVM_OPT_MEMCPY`` 只包含 :menuitem:`CONFIG_COMPILER_LLVM_MEMCPY_OPTIMIZATION` 对应的标志。当对应选项关闭或编译器不是 Clang 时,二者均为空:
managed ``lvgl`` 组件的库 target组件仓库名为 :code:`lvgl__lvgl`,不是它的源文件列表):
.. code-block:: cmake
idf_component_get_property(lvgl_lib "lvgl__lvgl" COMPONENT_LIB)
if(IDF_LLVM_OPT_ALL)
target_compile_options(${lvgl_lib} PRIVATE ${IDF_LLVM_OPT_ALL})
endif()
若只应用 memcpy 优化:
.. code-block:: cmake
idf_component_get_property(lvgl_lib "lvgl__lvgl" COMPONENT_LIB)
if(IDF_LLVM_OPT_MEMCPY)
target_compile_options(${lvgl_lib} PRIVATE ${IDF_LLVM_OPT_MEMCPY})
endif()
这样无需修改第三方的 CMakeLists。不要对大型组件中的全部源文件启用见下方限制。
高级用户可以追加额外的 Clang 或 LLVM 标志。这些标志会与 menuconfig 中启用的 LLVM 优化一起应用。省略 ``SRCS`` 时,自定义标志将应用于整个组件:
.. code-block:: cmake
idf_component_enable_llvm_opt(
SRCS "foo.c"
OPTIONS "-mllvm=-my-custom-llvm-option")
当前 menuconfig 选项使用 RISC-V PIE 扩展加速 ``memcpy``。请安装并选用乐鑫 Clang 工具链(``IDF_TOOLCHAIN=clang``);当活动编译器为 GCC 时IDF 不会注入这些标志。后续可在不改动 CMake 启用 API 的情况下,通过 menuconfig 添加新选项。示例见 :example:`system/llvm_opt` 与 :example:`system/llvm_memcpy_opt`
使用限制:
- 需要乐鑫 Clang 工具链。如果所选编译器不是 Clang``ENABLE_LLVM_OPT````idf_component_enable_llvm_opt````IDF_LLVM_OPT_ALL````IDF_LLVM_OPT_MEMCPY`` 不会产生任何效果。
- 当前仅在 ESP32-P4 上完成验证。
- 仅在优化热点路径时启用。优先对已测量的文件列表启用。结果依赖对齐、长度、芯片修订以及 Flash/Cache 布局。
- **不要** 对整个工程或大型组件中的全部源文件启用。生成代码会使用 PIE 协处理器:某个尚未拥有 PIE 的任务第一次执行 PIE 指令时会陷入内核内核惰性保存上一任拥有者的寄存器并恢复当前任务的寄存器每个这样的任务都会重复该切换整体应用可能反而变慢。额外代码体积I-cache也可能有影响但是次要因素。详见 :doc:`../api-reference/system/freertos_idf`
- 不要在 ISR 中使用该 memcpy 选项:中断上下文中使用 PIE 协处理器不被允许,并会导致运行中止。
- 不要把 CMake 标记当作全局 ``-O`` 替代。
.. _component-configuration:
@@ -1565,6 +1633,10 @@ ESP-IDF 组件命令
- KCONFIG_PROJBUILD - 覆盖默认的 Kconfig.projbuild 文件。
- WHOLE_ARCHIVE - 如果指定了此参数,链接时会在组件库的前后分别添加 ``-Wl,--whole-archive````-Wl,--no-whole-archive``。这与设置 ``WHOLE_ARCHIVE`` 组件属性的效果一致。
.. only:: esp32p4
在 ESP32-P4 上,``idf_component_register`` 还接受 ``ENABLE_LLVM_OPT``,用于将 menuconfig 中启用的 LLVM 优化应用于组件中的所有源文件。如果所选编译器不是 Clang该参数会被忽略。详见 :ref:`cmake-llvm-optimizations`
以下内容用于 :ref:`将数据嵌入到组件中<cmake_embed_data>`,并在确定组件是否仅用于配置时被视为源文件。这意味着,即使组件没有指定源文件,如果组件指定了以下其中之一,仍然会在内部为组件创建一个静态库。
- EMBED_FILES - 嵌入组件的二进制文件