涵盖 MIL Linking 的原理、使用方法、优化效果、构建影响、注意事项及应用场景。
MIL Linking 是 TASKING VX-toolset for TriCore C 编译器提供的一种全程序跨模块优化(Application-Wide Optimization)机制。
在传统的编译流程中,每个 C 源文件独立编译为独立的目标文件,优化仅在单个翻译单元(Translation Unit)内进行。MIL Linking 打破了这个限制——它在编译的前端阶段,将整个应用程序所有模块的中间表示(MIL)代码合并链接,然后以整个应用程序为作用域重新运行前端优化,从而实现跨模块的全局优化。
备注:通过和客户交流,部分客户代码要进行特殊优化,tasking存在mil Linking的功能,刚好满足客户的需求。欢迎大家一起学习交流:support@softor.com.cn
MIL(Medium Intermediate Language)是 TASKING C 编译器前端处理 C 源文件后生成的中间表示代码。它介于高级 C 源代码和底层机器代码之间,保留了足够的语义信息供优化器分析和变换。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--mil-link 模式) |
C 源文件 1 ──→ 预处理 ──→ 前端优化(模块级)──→ 后端代码生成 ──→ 目标文件 1 ──┐
C 源文件 2 ──→ 预处理 ──→ 前端优化(模块级)──→ 后端代码生成 ──→ 目标文件 2 ──┤
C 源文件 3 ──→ 预处理 ──→ 前端优化(模块级)──→ 后端代码生成 ──→ 目标文件 3 ──┤
├─→ 链接器 ──→ ELF
库文件 ─────────────────────────────────────────────────────────────────────────┘
每个模块独立优化,看不到其他模块的信息。
C 源文件 1 ──→ 预处理 ──→ 生成 MIL 代码 ──┐
C 源文件 2 ──→ 预处理 ──→ 生成 MIL 代码 ──┤
C 源文件 3 ──→ 预处理 ──→ 生成 MIL 代码 ──┤
MIL 库 (.ma) ─────────────────────────────┤
├─→ MIL 链接(合并为单个 MIL 流)
│ │
│ ▼
│ 前端优化(全程序作用域)
│ │
│ ▼
│ 后端代码生成(全程序作用域)
│ │
│ ▼
│ 单个 .src 文件
│ │
├────────┴─→ 链接器(链接运行时库、浮点库、C 库)──→ ELF
库文件(手写汇编)──────────────────────────────────────────────────────────────────┘
所有模块的 MIL 代码合并后,优化器可以”看到”整个应用程序。
C 源文件 1 ──→ 预处理 ──→ 生成 MIL 代码 ──┐
C 源文件 2 ──→ 预处理 ──→ 生成 MIL 代码 ──┤
C 源文件 3 ──→ 预处理 ──→ 生成 MIL 代码 ──┤
MIL 库 (.ma) ─────────────────────────────┤
├─→ MIL 链接(合并为单个 MIL 流)
│ │
│ ▼
│ 前端优化(全程序作用域)
│ │
│ ▼
│ 拆分 MIL 流为独立模块
│ │
│ ├──→ file1.ms ──→ 后端代码生成 ──→ 目标文件 1 ──┐
│ ├──→ file2.ms ──→ 后端代码生成 ──→ 目标文件 2 ──┤
│ └──→ file3.ms ──→ 后端代码生成 ──→ 目标文件 3 ──┤
│ ├─→ 链接器 ──→ ELF
库文件(手写汇编)──────────────────────────────────────────────────────────────────┘
前端全程序优化后,拆分回独立模块分别生成代码,支持增量构建。
命令行语法:
ctc --mil-link file1.c file2.c file3.c
Eclipse 设置路径:
工作方式:
优势:
劣势:
命令行语法:
# 基本用法
ctc --mil-split file1.c file2.c file3.c
# 指定输出文件名
ctc --mil-split=out1.ms,out2.ms,out3.ms file1.c file2.c file3.c
Eclipse 设置路径:
工作方式:
--mil-link 相同,先进行 MIL 链接和全程序前端优化.ms 文件(与 .mil 格式相同).ms 文件会被更新优势:
--mil-link 模式短劣势:
.ms 文件需要更新(全局优化的自然结果)Tip
选择建议如果不需要代码压缩(例如完全优化速度
--tradeoff=0),建议选择--mil-split(Optimize less/Build faster),以获得更短的构建时间。
MIL Linking 后,以下前端优化从模块级提升为全程序级:
|
|
|
|---|---|
| 选项 | -Oc
-OC |
| 模块级 |
|
| 全程序级 |
|
|
|
|
|---|---|
| 选项 | -Op
-OP |
| 模块级 |
|
| 全程序级 |
|
|
|
|
|---|---|
| 选项 | -Oi
-OI |
| 模块级 |
inline 关键字声明的函数) |
| 全程序级 |
|
|
|
|
|---|---|
| 选项 | -Of
-OF |
| 模块级 |
|
| 全程序级 |
|
|
|
|
|---|---|
| 选项 | -Ol
-OL |
| 模块级 |
|
| 全程序级 |
|
|
|
|
|---|---|
| 选项 | -Oo
-OO |
| 模块级 |
|
| 全程序级 |
|
|
|
|
|---|---|
| 后端优化 |
--mil-link 模式下可在全程序范围内执行 |
| 效果 |
|
| –mil-split |
|
TASKING 工具链提供了预编译的 MIL 库文件(扩展名 .ma),包括:
|
|
|
|
|---|---|---|
|
|
libc.a |
libc.ma |
|
|
libfp.a |
libfp.ma |
|
|
libpb.a
|
libpb.ma
|
Important
即使使用了 MIL Linking,仍需链接普通的运行时库、浮点库和 C 库(
.a文件)。
原因:C 库中包含手写汇编函数,这些函数没有 MIL 表示,无法在 MIL 层面链接。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
显著 |
|
|
|
--mil-link
|
|
|
|
--mil-split
|
|
|
|
显著增加 |
|
|
|
|
|
|---|---|---|
--mil-link |
|
|
--mil-split |
|
.ms 模块,但一个源文件的修改可能导致多个 .ms 文件更新 |
|
|
|
|
Warning
编译器缓存(
--cache选项)与--mil-split不兼容。
缓存仅适用于单输入单输出的编译场景。
# 模式一:优化更多,构建更慢(全程序后端优化)
ctc --mil-link app.c module1.c module2.c -O2
# 模式二:优化更少,构建更快(支持增量构建)
ctc --mil-split app.c module1.c module2.c -O2
# 指定自定义 .ms 输出文件名
ctc --mil-split=app.ms,mod1.ms,mod2.ms app.c module1.c module2.c
# 结合优化级别和速度/大小权衡
ctc --mil-link app.c module1.c module2.c -O3 --tradeoff=4
--mil-link)--mil-split)在 Eclipse 中通过控制程序传递:
--mil-link / --mil-splitWarning
MIL Linking 会执行额外的严格类型检查,可能导致正常编译时不会出现的错误。
这是因为 MIL Linking 将所有源文件视为一个翻译单元,类型不一致的问题更容易暴露。
当同时使用 --mil-link 和 --uchar(将 char 视为 unsigned char)时,可能会遇到以下错误:
ctc E289: ["..\..\..\strlen.c" 14/1] "strlen" redeclared with a different type
ctc I802: ["installation-dir\ctc\include\string.h" 44/17]
previous declaration of "strlen"
1 errors, 0 warnings
原因:MIL 库是在没有 --uchar 选项的情况下构建的,导致类型不匹配。
解决方案:重新构建 MIL 库。
在 ISO C 标准中,”翻译单元”(Translation Unit)是一个预处理后的源文件及其所有 #include 文件。MIL Linking 后,编译器将所有链接的源文件视为单个翻译单元,这使得全局优化成为可能,但也意味着:
static 函数和变量的可见性规则可能产生意外行为|
|
|
|---|---|
|
|
--mil-link |
|
|
--mil-split
|
--tradeoff=0) |
--mil-split
|
|
|
--mil-split
|
--mil-split 或不启用 MIL Linking,获得最快的构建速度--mil-split,在保持合理构建时间的同时进行全程序前端优化--mil-link,获得最佳的代码优化效果# 发布构建:最大优化
ctc --mil-link -O3 --tradeoff=4 app.c
# 发布构建:最小代码体积
ctc --mil-link -O2 --tradeoff=10 app.c
# 日常开发:快速构建 + 全程序前端优化
ctc --mil-split -O2 app.c
# 调试构建:不使用 MIL Linking
ctc -O0 -g app.c
|
|
|
|
|---|---|---|
|
|
--mil-link |
--mil-split |
|
|
|
|
|
|
|
--mil-split 或增加系统内存 |
|
|
--mil-link |
--mil-split |
|
|
--mil-split |
--mil-split 不兼容 |
场景描述:ECU 软件通常由多个模块组成,包括传感器数据处理、燃油喷射控制、点火控制等。这些模块之间存在大量的函数调用和数据交换。
MIL Linking 应用:
实际效果:
场景描述:ADAS 系统包含多个复杂模块,如摄像头处理、雷达信号处理、路径规划等,需要实时处理大量数据。
MIL Linking 应用:
实际效果:
场景描述:PLC 软件通常包含多个功能块(FB),这些功能块之间通过数据交换进行协作。
MIL Linking 应用:
实际效果:
场景描述:电机驱动系统需要实时控制电机速度、位置和扭矩,包含速度环、位置环、电流环等多个控制模块。
MIL Linking 应用:
实际效果:
场景描述:飞行控制系统需要极高的可靠性和实时性,包含多个冗余模块和复杂的控制算法。
MIL Linking 应用:
实际效果:
场景描述:导航系统需要处理来自多个传感器的数据,进行复杂的定位和导航计算。
MIL Linking 应用:
实际效果:
项目背景:某汽车制造商的发动机控制软件,包含 15 个模块,代码量约 100,000 行。
优化前:
使用 MIL Linking 后:
关键优化点:
项目背景:工业机器人控制软件,包含运动控制、路径规划、传感器处理等模块。
优化前:
使用 MIL Linking 后:
关键优化点:
集成策略:
--mil-split 模式,保证快速构建--mil-split 模式,进行全程序前端优化--mil-link 模式,获得最佳优化效果配置示例:
# GitLab CI 配置示例
stages:
- build
- test
- deploy
build_dev:
stage: build
script:
- ctc --mil-split -O2 -g src/*.c -o app_dev.elf
only:
- develop
build_release:
stage: build
script:
- ctc --mil-link -O3 --tradeoff=4 src/*.c -o app_release.elf
only:
- master
- tags
调试策略:
-O0 -g 获得最佳调试体验--mil-split 模式,保留一定的调试信息--mil-link 模式,同时启用性能分析选项调试技巧:
__attribute__((noinline)) 标记关键函数,防止过度内联影响调试--keep-debug 选项保留调试信息|
|
|
|
|---|---|---|
--mil-link |
|
|
--mil-split[=file,...] |
|
|
--optimize[=flags]
-O |
|
|
--tradeoff=number
-t |
|
|
--compact-max-size=value |
|
|
--max-call-depth=value |
|
|
--cache |
|
--mil-split 不兼容) |
--uchar
-u |
|
|
作者:tianpengbo / 田朋博。大家如果在项目中遇到相关技术问题,欢迎联系我交流。
support@softor.com.cn
tianpengbo@softor.com.cn
作者:tianpengbo / 田朋博。大家如果在项目中遇到相关技术问题,欢迎联系我交流。
support@softor.com.cn
tianpengbo@softor.com.cn