在前文《如何为嵌入式软件开发选择编译器》中讲到编译器对于嵌入式软件开发的重要性,以及如何选择一款优秀的编译器。文中也比较了现有主流编译器的编译优化性能,IAR Embedded Workbench编译器不论在输出代码体积还是性能均处于业界领先地位。
本文中,我们将以IAR Embedded Workbench编译器为例,阐述如何配置编译优化选项,以达到嵌入式软件代码性能和体积的最佳平衡。由于篇幅关系,本主题将会分成上、下两篇。
在介绍如何配置编译器优化选项之前,让我们先来了解下编译器构建的过程。以IAR Embedded Workbench编译器为例,其代码构建过程如下图。
构建过程分为两部分:前端和后端。
前端主要将C代码通过解析器(Parser)生产中间代码(Intermediate Code),在这个过程中会介入优化器(High-Level Optimizer),其优化策略包括函数内联(Function in lining), 冗余代码消除(Dead code elimination), 循环展开(Loop unrolling)等。
后端则将中间代码通过目标代码生成器(Code Generator)生成目标汇编代码(Target Code),在这个过程中也会介入优化器(Low-Level Optimizer),其优化策略包括调度(Scheduling), 窥视孔(Peephole), 函数调用优化(Cross call)等。然后由汇编器(Assembler)将汇编代码转换成目标机器码(Object Code)。最后,通过链接器(Linker),将所有的目标机器码链接成elf格式的可执行二进制代码文件。在链接阶段也有相应的优化器(Linker time optimization)进行优化。
在IAR Embedded Workbench(基于EWARM v9.32.2)中通过菜单栏(Project -> Options)打开项目选项界面,选中“C/C++ Compiler”栏目,并且在右边选项卡选中“Optimizations”,即可进行编译优化选项配置,如下图所示。
1. 编译优化等级配置
如下图所示,IAR Embedded Workbench共分为4个优化等级(None, Low, Medium, High),其中等级“High”又分为3个子优化等级(Balanced, Size, Speed)。下表是各个优化等级对应的优化策略总览。
关于编译优化微调项(Enabled transformations)配置方法,我们将在《深入浅出编译优化选项(下)》详细介绍。
2. 多文件编译(Multi-file Compilation)
通常情况下,编译器逐个编译C/C++源文件。编译器的单次编译视野仅限于当前C/C++源文件,不能获知其他源文件的情况,包括全局变量,函数调用,指针别名等关系。因此编译器会采用较为保守和安全的优化假设。
IAR Embedded Workbench则为用户提供了 “多文件编译” 功能,如下图。编译器在工程全局级别或者文件组级别,允许一次编译多个文件,从而增加了编译视野,可以进行更为深度的编译优化策略实施,通常能获得更好的编译优化效果。
3. 灵活配置编译优化选项作用域
IAR Embedded Workbench提供了不同作用域的编译优化选项设置,使用户能够更加灵活的进行配置,对不同编译优化需求的代码进行分别配置。
4. 链接阶段优化选项
IAR Embedded Workbench在链接阶段也提供了相应的代码优化选项,如下图。
嵌入式系统中通常硬件资源有限,特别是存储器容量,直接与MCU硬件成本挂钩,影响整个系统的硬件物料成本;另一方面,嵌入式软件又需要对外部信号进行实时响应,对外部设备进行实时控制,比如马达控制组件;除此之外,电池供电的嵌入式设备需要具备低功耗特性,要求CPU尽可能处于深度睡眠状态,以尽可能延长设备的单次电池工作时间。结合上述情况,对于嵌入式软件进行编译优化选项配置需要进行差异化考量,具体如下:
对于经常需要唤醒执行的软件任务,可以考虑极致代码性能优化。这样会减少动态功耗的时间,以达到整体功耗的下降,从而增加设备的电池使用寿命。
IAR Embedded Workbench是一款业界领先的编译工具链,除了提供卓越的性能之外,还提供了丰富灵活的编译优化选项配置,以帮助用户在不同的嵌入式应用需求下,都能找到最佳的嵌入式软件代码性能和体积的平衡点。
在下一篇《深入浅出编译优化选项(下)》中,我们将介绍编译过程中的优化策略以及如何在IAR Embedded Workbench配置编译优化微调项(Enabled transformations),让用户可以根据代码需求配置出更加精准的编译优化策略组合。
参考文献:
1. www.iar.com/e-book/e-book-cn
2. https://www.embedded.com/understanding-mcu-sleep-modes-and-energy-savings/