ARM嵌入式编译器(五) 优化循环的4种方法

发布时间:2022-12-09  

1. 循环展开


循环执行的时间取决于循环的次数,循环中每次检查是否进行循环的条件会降低循环的性能。使用循环展开可以减少检查条件的判断次数,但是展开循环就意味着增加代码量。例如:在精确的时钟周期循环中,可以使用#pragma unroll (n)来展开循环。


“pragma”(编译指示)仅在选择优化等级为-O2/-O3/-Ofast和-Omax时有效。


编译指示的相关用法:

注:虽然给出了循环展开的编译指示,但Arm官方不建议使用,这样会影响编译器的展开优化和其他循环优化。

将代码分别复制到file.c文件中,然后使用以下命令进行编译和反汇编。


armclang --target=arm-arm-none-eabi -march=armv8-a file.c -O2 -S -o file.s


可以看到展开循环时,代码执行会更快,但代码量也更大。


2. 循环向量化


如果编译的目标含有SIMD单元,那么编译器就可以使用向量引擎来优化代码的向量部分。在优化等级为-O1,可以使用-fvectorize 来启动优化,而在-O2或更高等级时向量优化是自动启用。


要使用向量优化,在编写代码的时候需要将结构体的成员放到同一个循环中,而不能使用独立的循环。

对于每个例子,将代码分别复制到file.c文件中,然后使用以下命令进行编译和反汇编。


armclang --target=arm-arm-none-eabi -march=armv8-a file.c -O2 -S -o file.s

在64位运行状态下要避免编译器使用SIMD向量优化可以在-march或-mcpu后+nosimd;


例如:


armclang --target=aarch64-arm-none-eabi -march=armv8-a+nosimd -O2 file.c -S -o file.s


在32位运行状态下要避免编译器使用SIMD向量优化,可以通过设置-mfpu=fp-armv8;


例如:


armclang --target=aarch32-arm-none-eabi -march=armv8-a -mfpu=fp-armv8 -O2 file.c -S -o file.s


3. 循环终止


在写循环的时候如果编写不当会使得代码的运行效率降低和代码量增大。建议使用以下的终止条件:


1)使用变量类型为:unsigned int


2)使用向下减少的计数方式,以减到0作为计数结束。


3)使用简单的终止条件。


单独或组合使用以上原则的终止条件,可以获得更好的代码大小或效率。


例如:这是一个实现n!的计算程序。

用以下命令反汇编以下armclang -Os -S --target=arm-arm-none-eabi -march=armv8-a 

对比反汇编代码可以看出在递减循环中用SUBS指令代替了递增循环中ADD 和CMP两条指令。这是因为SUBS指令会自动更新Z标志。


此外在递减循环中变量n不必再循环的过程实时使用,从而减少了寄存器的数量。


如果终止条件是一个函数,则循环的每次都调用该函数,这种情况下递减的循环优势就更明显了。例如:


for (...; i < get_limit(); ...);


说明:这种递减循环计数的方式也适用于while-do 命令。




4. 无限循环


在某些情况下armclang会删除一些编译器认为没有影响的无限循环,从而导致最终程序无法正常运行。


为确保无限循环的正确编译执行,ARM官方建议在无限循环中添加__arm volatile的声明。这个声明的目的是告诉编译器删除这个无限循环会有影响,不能被优化删除。在无限循环中,把处理器设置为低功耗模式是一个不错的做法,当有中断或事件触发时再回到正常模式。


下面是一个包含__arm volatile声明的无限循环例子:


void infinite_loop(void) {


while (1)


  __asm volatile("wfe");


}




注:wfe(Wait for Event)是给处理器一个提示,使处理器进入低功耗状态,直到事件或中断触发。 作者:亿道电子 https://www.bilibili.com/read/cv18803688/ 出处:bilibili


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

相关文章

    是GCC,作为一个完全开源的编译器,很多MCU厂商的IDE都由它改写而来。但最近一段时间,业界出现不同的声音,表示“开源才是最贵的”,这些编译器在开源背后潜藏许多隐形成本。 跑RTOS,GCC没打......
    就需要自行添加一个C和C++的编译器,其实就是提供路径 然后选择qmake的路径,指明版本。 最后一步,在kit中添加自己刚才配置的套件。 4、接下来创建个工程来编译一下看看。 创建......
    X86的gcc。   然后就需要自行添加一个C和C++的编译器,其实就是提供路径    然后选择qmake的路径,指明版本。    最后一步,在kit中添加自己刚才配置的套件。   4......
    我选择Linux64): 解压下来是tar.ba2格式包,使用命令tar -jxf <要解压的文件>解压到我们要安装的目录: 为了以后使用方便,将文件夹重命名: 它下面的bin目录就是我们要使用的编译......
    实现就是system_stm32f10x.c文件(似乎还应该加上外设的函数库)。   接下来就来了解一下Core_cm3.c里面有什么东东: 首先是汇编关键字__ASM和__INLINE的宏定义,支持不同的编译器。由于使用的是Keil......
    panic - not syncing: Attempted to kill init! 其中一个原因是内核不是用带eabi的的编译器编译的,而制作rootfs是的busybox使用带eabi的编译器编译......
    门高级语言,它需要经过编译成汇编语言机器才能读懂,所以每个平台的编译器编译成对应平台汇编的程序,每个平台的汇编不一样,当然编译器也不一样。 DOS上的TC2 TC3 WINDOWS上的VC 8051的......
    、alloca out-of-scope free。 方舟编译器在上应用后,带来了以下性能优势: 提高系统流畅度:方舟编译器采用了全新的系统及应用的编译和运行机制,对所有的Java语义全部做到静态编译......
    序员编写的源代码转换为底层硬件可以执行的机器指令。一款优秀的编译器既需要对程序进行优化,确保程序可以高效地运行,同时又需要保证转换的一致性。 因此,对于嵌入式系统开发人员来讲,在选择以编译器......
    符号的链接特性是由链接器决定的,并不是C语言语法本身的特性。所以如果使用的是不同的编译工具链,这个特性不一定存在。看到这里,想必大家已经清楚STM32中printf重定向背后的原理了。 ......

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>