ARM嵌入式编译器编译优化选项 -O

news2024/11/24 2:13:01

Arm嵌入式编译器可以执行一些优化来减少代码量并提高应用程序的性能。不同的优化级别有不同的优化目标,不仅如此,针对某个目标进行优化会对其他目标产生影响。比如想减小生成的代码量,势必会影响到该代码的性能。所以优化级别总是这些不同目标(代码量,程序性能,debug信息)之间的权衡。

目录

Optimization level -O0

Optimization level -O1 

Optimization level -O2

Optimization level -O3

Optimization level -Os

Optimization level -Oz

Optimization level -Omin

Optimization level -Ofast

Optimization level -Omax


Arm Compiler for Embedded提供了各种优化级别来控制不同的优化目标:

优化目标可用的优化级别
更小的代码量-Oz-Omin
更快的性能-O2-O3-Ofast-Omax
兼顾代码量和debug信息-O1
源代码和生成代码之间更好的相关性-O0 (no optimization)
更快的编译和构建时间-O0 (no optimization)
在代码量和性能之间的平衡-Os
  • 如果对性能使用更高的优化级别,那么它对其他目标的影响也会更大,例如调试体验降低、代码大小增加和编译和构建时间增加。
  • 如果优化目标是减少代码大小,那么它会对其他目标产生影响,例如降低调试体验、降低性能和增加编译和构建时间。 

所以用户可以根据自己的编译目标,选择适合自己的编译优化等级:

Optimization level -O0

-O0 将禁用所有优化

这个优化级别是默认的。使用-O0的结果是更快的编译和构建时间,但产生的代码,其性能比其他优化级别低,代码大小和堆栈使用也会明显高于其他优化级别。由于没有任何优化,所以生成的代码与源代码密切相关,这导致生成的代码明显更多,包括死代码(dead code)。

Optimization level -O1 

-O1在编译器中启用内核优化(core optimizations)。-O1便于用户调试,代码质量优于-O0。此外,堆栈的使用也比使用-O0时得到了改善。如果想调试程序,建议使用-O1来获取更多的调试信息。与使用-O0相比,使用-O1的不同之处在于:

  • 启用了优化,这可能会降低调试信息的保真度(fidelity)。
  • 启用了内联,这意味着函数调用栈的回溯,可能不会像阅读源代码那样,具有层级关系,内联会把函数体直接加载到函数调用的地方。
  • 如果不需要函数返回的结果,则一个没有副作用的函数在预期的地方可能不会被调用,甚至会被忽略。
  • 局部变量的值在不再使用后可能无法在其作用域中被获取使用。例如,它们所在栈位置可能已经被其他模块使用了。

Optimization level -O2

与-O1相比,-O2对性能进行了更高的优化。这一层是编译器自动生成矢量指令(vector instructions)的第一个优化层。它还降低了调试体验,并且可能导致代码量的增加。与使用- O1相比,使用-O2的不同之处在于:

  • 增加内联函数调用的阈值。
  • 执行的循环展开次数可能会增加。
  • 矢量指令可以为简单循环和独立标量操作的相关序列生成。可以使用armclang命令行选项-fno-vectorize来禁止矢量指令的创建。

Optimization level -O3

与-O2相比,-O3是更高的性能优化。此优化级别需要大量编译时分析和资源的优化,-O3指示编译器优化生成代码的性能,而忽略生成代码的量,这可能导致代码量增加。与-O2相比,它还降低了调试体验。并且:

  • 增加内联函数调用的阈值。
  • 执行的循环展开次数可能会增加。
  • 在编译器流水线上,实施更加激进的指令优化策略。

Optimization level -Os

-Os的目标在不显著增加代码大小的情况下提供高性能。取决于用户的代码,-Os提供的性能可能与-O2或-O3相似。与-O3相比,-Os减少了代码量。与-O1相比,它还降低了调试体验。与使用-O3相比,使用-Os的不同之处在于:

  • 降低了内联函数调用的阈值。
  • 执行的循环展开的数量显著降低。

Optimization level -Oz

-Oz的目标是在不使用链接时间优化(LTO)的情况下提供更小的代码量。如果LTO不适合用户的应用程序,Arm建议可以使用此选项以获得最佳代码大小。与-O1相比,此优化级别降低了调试体验。与使用-Oz相比:

  • 编译器只针对代码大小进行优化,而忽略性能优化,这可能导致代码变慢。
  • 未禁用函数内联。在某些情况下,内联可以减少总体代码大小,例如,如果一个函数只被调用一次。
  • 禁止一些可能增加代码量的优化,比如将循环展开,循环矢量化等。
  • 针对M系列的AArch32以及其他的AArch64目标,将使能外联(outlining)功能。外联器(outliner )将搜索代码中相同sequence的代码,并将它们放在同一个函数当中,然后用调用同一个函数的方式来取代这些相同的代码段。外联可以减小代码大小,但是增加了代码执行时间。用户可以使用-moutline, -mno-outline选项来手动开启或者关闭该功能。

Optimization level -Omin

通过使用LTO功能的子集,-Omin旨在提供比-Oz更小的代码量。与使用-Oz相比,使用-Omin的不同之处在于:

  • -Omin支持一组基本的LTO,旨在删除未使用的代码和数据,同时还尝试优化全局内存访问。
  • -Omin支持消除虚函数(C++)。

如果希望在-Omin下进行编译,并使用单独的编译和链接步骤,那么还必须在armlink命令行中包含-Omin。

Optimization level -Ofast

-Ofast执行-O3级的优化,包括那些使用armclang选项-ffast-math执行的优化。该级别还执行其他可能违反严格遵守语言标准的激进优化。与-O3相比,此级别降低了调试体验,并且可能导致代码大小增加。

Optimization level -Omax

-Omax执行最大优化,并专门针对性能优化。它支持从-Ofast到LTO的所有优化。在这个优化级别上,Arm嵌入式编译器可能会违反严格遵守语言标准。使用此优化级别可以获得最快的性能。与-Ofast相比此级别降低了调试体验,并且可能导致代码大小增加。如果用户希望在-Omax下进行编译,并且有单独的编译和链接步骤,那么您还必须在armlink命令行中包含-Omax。

示例

int test()
{
    int x=10, y=20;
    int z;
    z=x+y;
    return 0;
}

在上述代码中,int x=10 z=x+y ,两行代码为死代码(dead code),如果使用-O0,则不进行任何优化,这两行将会被编译生成到源文件中:

armclang --target=arm-arm-none-eabi -march=armv7-a -O0 -S file.c

如果使用-O1,这两行将会被忽略:

armclang --target=arm-arm-none-eabi -march=armv7-a -O1 -S file.c

Selecting optimization optionsicon-default.png?t=N3I4https://developer.arm.com/documentation/100748/0620/Using-Common-Compiler-Options/Selecting-optimization-options?lang=en

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/461911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python中 re.findAll()、re.sub()、set()的使用

1. re.findall() re.findall():函数返回包含所有匹配项的列表。返回string中所有与pattern相匹配的全部字串,返回形式为list / 数组。 由函数原型代码可知,findall() 函数存在三个参数: 1. pattern:正则表达式中的 ‘模…

RK3568平台开发系列讲解(驱动基础篇)IO 模型的分类

🚀返回专栏总目录 文章目录 一、阻塞 IO二、非阻塞 IO三、IO 多路复用四、信号驱动五、异步 IO沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇将针对IO模型进行分类。 假设有这样一个场景,从磁盘中循环读取 100M 的数据并处理,磁盘读取 100M 需要花费 20 秒的…

HR真的会嫌弃跳槽频繁的测试人员吗?

我们都知道:“跳槽≠涨薪”,但是对于测试人来说,跳槽绝哔能和升职加薪画上等号啊。 所以,有很多测试人在一家公司常常待不到1年,就另觅新东家,来借此达成升职加薪的目的。 有人提出质疑:为什么测…

【老王读SpringMVC-2】url 与 controller method 的映射关系注册

上文提到,如果我们自己要实现 spring mvc 框架的话,大致需要实现如下功能: 0、将 url 与 Controller method 的对应关系进行注册1、通过请求的 url 找到 Controller method (即 url 与 Controller method 的映射)2、将请求参数进行绑定&…

【python中的迭代器了解一下?】

基本说明 在 Python 中,迭代器是一种用于遍历可迭代对象(如列表、元组、字符串等)的方式。迭代器提供了一种简洁而有效的方法来遍历序列,而不需要创建临时变量或使用循环语句。 在 Python 中,迭代器是一个实现了 __i…

没有U盘电脑如何使用本地硬盘安装Ubuntu20.04(双系统)

环境: DELL7080台式机 Ubuntu20.04 两块硬盘 问题描述: 没有U盘电脑如何使用本地硬盘安装Ubuntu20.04(双系统) 解决方案: 一、下载镜像文件 1.上线自行下载安装镜像文件 二、分区 1.win10下磁盘管理压缩2个分区一个10G左右制作安装盘,一个几百G安装系统使用 10…

【Android入门到项目实战-- 7.1】—— 如何使用通知?

目录 一、创建通知的步骤 1、创建一个NotificationManager实例 2、使用一个Builder构造器来创建Notification对象 3、设置标题、文字、时间和图标等信息 4、显示通知 二、通知实例演示 三、实现通知的点击效果 1、PendingIntent 什么是PendingIntent? 如何使…

后台-husky提交代码规范使用

husky是一个git hook工具,可以帮助我们触发git提交的各个阶段:pre-commit、commit-msg、pre-push 1.如何使用husky呢? npx husky-init && npm installWindows安装不成功试试npx husky-init && npm install 2.git commit规范…

线索二叉树的前序遍历

线索二叉树原理 遍历二叉树的其实就是以一定规则将二叉树中的结点排列成一个线性序列,得到二叉树中结点的先序序列、中序序列或后序序列。这些线性序列中的每一个元素都有且仅有一个前驱结点和后继结点。 但是当我们希望得到二叉树中某一个结点的前驱或者后继结点时…

计算机组成原理---第 6 章总线系统

一、总线的概念和结构形态 总线的基本概念 ⑴概述 总线是构成计算机系统的互联机构,是多个系统功能部件之间进行数据传送的公共通路。 ⑵ 分类 总线的分类方式有很多:如被分为外部总线和内部总线、系统总线和非系统总线、片内总线和PCB板级总线、串行…

VS2022+opengl环境配置

glfw下载Download | GLFW glad下载https://glad.dav1d.de/ Freeglut下载 https://freeglut.sourceforge.net/index.php#download cmake下载 Download | CMake glfwFreeglut 用cmake配置Freeglut,生成vs工程项目,用vs2022编译项目,生成fr…

27.Spring的事务控制

目录 一、编程式事务控制相关对象。 (1)事务管理器。 (2)事务定义信息对象(如隔离级别、传播行为)。 (3)事务状态对象。 (4) 知识要点。 二、声明式事务…

基于STM32的开源简易示波器项目

目录 ​一、前言 二、硬件接线 三、信号的采集 四、代码配置 五、数据的处理 六、模拟正弦波输出 七、模拟噪声或三角波输出 八、显示函数与按键控制 ​一、前言 该项目是基于正点原子精英板制作的一个简易示波器,可以读取信号的频率和幅值,并可…

JetpackCompose从入门到实战学习笔记14

JetpackCompose从入门到实战学习笔记14——Coli的简单使用 1.简介: Coil 是一个 Android官方出的配合Jetpack的图片加载库,通过 Kotlin 协程的方式加载图片。 优点如下: 更快: Coil 在性能上有很多优化,包括内存缓存和磁盘缓存…

C/C++基础知识

专栏:C/C 个人主页: C/C基础知识 前言C关键字(C98)命名空间命名空间的定义正常的命名空间的定义如何使用命名空间 命名空间可以嵌套同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中(一个工程中的.h文件和test.…

(数字图像处理MATLAB+Python)第七章图像锐化-第一、二节:图像锐化概述和微分算子

文章目录 一:图像边缘分析二:一阶微分算子(1)梯度算子A:定义B:边缘检测C:示例D:程序 (2)Robert算子A:定义B:示例C:程序 &a…

Tailscale: Please Restart the Tailscale Windows Service

之前用的好好的,最近重新升级了一下Tailscale后发现一直连不上。右击win10右下角的Tailscale图标,第一行显示:Please Restart the Tailscale Windows Service。 我查看了一下服务,发现Tailscale是自动的,这里的启动类…

vuex存储数组(新建,增,删,更新),并存入localstorage定时删除

vuex存储数组(新建,增,删,更新),并存入localstorage定时删除 本文目录 vuex存储数组(新建,增,删,更新),并存入localstorage定时删除使用背景store中实现增删改组件中维护数组&#x…

缩小数据文件

今天又出现12.2c 环境的问题,1T的数据空间还剩下2G,吓了一身冷汗,赶紧查看原因,不知道哪路业务大神作妖了。 发现sysaux和system增加N多数据文件,而且目前使用不多, 缩小表空间的数据文件 可以使用下面的语…

直升机空气动力学基础---002 桨叶的主要参数

源于 1.桨叶的平面形状和主要参数 由于其设计制造比较简单,早期直升机大多采用矩形桨叶,缺点是在高速气流中,无法抑制桨尖涡,会消耗向下的诱导速度,降低旋翼的拉力。现代多采用梯形桨叶。 桨尖后掠能够降低桨尖涡 …