【编译之美】【4. 代码优化:为什么你的代码比他的更高效】

news2025/1/16 5:37:03

什么是代码优化

代码优化是编译器后端的两大工作之一,弄懂它,你就掌握了一大块后端技术。

  • 代码优化的目标
    代码优化的目标,是优化程序对计算机资源的使用。

  • 代码优化的对象

大多数的代码优化都是在 IR 上做的,而不是在前一阶段 AST 的后一阶段汇编代码上进行的,为什么呢?

  • 在 AST 上做优化,抽象层次太高,含有硬件架构信息太少,难以执行很多优化算法
  • 在汇编代码上进行优化会让算法跟机器相关,当换一个目标机器的时候,还要重新编写优化代码。

所以,在 IR 上是最合适的,尽量做到机器独立,又暴露出很多优化的机会。

  • 代码优化的范围

从优化的范围看,分为本地优化、全局优化和过程间优化。

优化通常针对一组指令,最常用也最重要的指令组,就是基本块。基本块的基本特点是:每个基本块只能从入口进入,从最后一条指令退出,每条指令都会被顺序执行。

这种针对基本块的优化,我们叫做本地优化(Local Optimization)

超越基本块的范围进行分析,我们需要用到控制流图(Control Flow Graph,CFG)。CFG 是一种有向图,它体现了基本块之前的指令流转关系。如果从 BB1 的最后一条指令是跳转到 BB2,那么从 BB1 到 BB2 就有一条边。一个函数(或过程)里如果包含多个基本块,可以表达为一个 CFG。
在这里插入图片描述
如果通过分析 CFG,我们发现 t 在其他地方没有被使用,就可以把第二行删掉。这种针对一个函数、基于 CFG 的优化,叫做全局优化(Global Optimization)

比全局优化更大范围的优化,叫做过程间优化(Inter-procedural Optimization),它能跨越函数的边界,对多个函数之间的关系进行优化,而不是仅针对一个函数做优化。

常见的代码优化场景

  • 代数优化(Algebraic Optimazation)

代数优化是最简单的一种优化,当操作符是代数运算的时候,你可以根据学过的数学知识进行优化。

比如“x:=x+0 ”这行代码,操作前后 x 没有任何变化,所以这样的代码可以删掉;又比如“x:=x0” 可以简化成“x:=0”;对某些机器来说,移位运算的速度比乘法的快,那么“x:=x8”可以优化成“x:=x<<3”。

  • 常数折叠(Constant Folding)

它是指,对常数的运算可以在编译时计算,比如 “x:= 20 * 3 ”可以优化成“x:=60”。另外,在 if 条件中,如果条件是一个常量,那就可以确定地取某个分支。比如:“If 2>0 Goto BB2” 可以简化成“Goto BB2”就好了。

  • 删除不可达的基本块

有些代码永远不可能被激活。比如在条件编译的场景中,我们会写这样的程序:“if(DEBUG) {…}”。如果编译时,DEBUG 是一个常量 false,那这个代码块就没必要编译了。

  • 删除公共子表达式(Common Subexpression Elimination)

下面这两行代码,x 和 y 右边的形式是一样的,如果这两行代码之间,a 和 b 的值没有发生变化(比如采用 SSA 形式),那么 x 和 y 的值一定是一样的。

  • 拷贝传播(Copy Propagation)和常数传播(Constant Propagation)

下面的示例代码中,第三行可以被替换成“z:= 2 * x”, 因为 y 的值就等于 x,这叫做拷贝传播。

x := a + b
y := x
z := 2 * y

如果 y := 10,常数 10 也可以传播下去,把最后一行替换成 z:= 2 * 10,这叫做常数传播。再做一次常数折叠,就变成 z:=20 了。

  • 死代码删除(Ded code elimination)

在上面的拷贝传播中,如果没有其他地方使用 y 变量了,那么第二行就是死代码,就可以删除掉,这种优化叫做死代码删除。

一个优化可能导致另一个优化,比如,拷贝传播导致 y 不再被使用,我们又可以进行死代码删除的优化。所以,一般进行多次优化、多次扫描。

整一个优化过程

  • 我们首先做一个正向扫描,进行可用表达式分析,建立可用表达式的集合,然后参照这个集合替换公共子表达式,以及做拷贝传播。
  • 接着,我们做一个反向扫描,进行活跃性分析,建立活变量的集合,识别出死变量,并依据它删除给死变量赋值的代码。
  • 上述优化可能需要做不止一遍,才能得到最后的结果。

可用表达式分析和活跃性分析是本地优化时的两个关键算法。这些算法都是由扫描方向、值、转换函数和初始值这四个要素构成的。

  • D(方向)。是朝前还是朝后遍历。
  • V(值)。代码的每一个地方都要计算出一个值。可用表达式分析和活跃性分析的值是一个集合,也有些分析的值并不是集合,在下一讲你会看到这样的例子。
  • F(转换函数,对 V 进行转换)。比如,在做可用表达式分析的时候,遇到了“c := b”时,可用表达式的集合从{a := b, c := a + b}转换成了{a := b, c := b}。这里遵守的转换规则是:因为变量 c 被重新赋值了,那么就从集合里,把变量 c 原来的定义去掉,并把带有 c 的表达式都去掉,因为过去的 c 已经失效了,然后,把变量 c 新的定义加进去。
  • I(初始值,是算法开始时 V 的取值)。做可用表达式分析的时候,初始值是空集。在做活跃性分析的时候,初始值是后面代码中还会访问的变量,也就是活变量。

拷贝传播如何实现

如果一个类是从 Value 继承的,意味着它定义了一个值。另一个类是 User 类,函数和指令也是 User 类的子类,也就是说,在函数和指令中,可以使用别的地方定义的值。
在这里插入图片描述
这两个类是怎么帮助到优化算法中的呢?

在 User 中,可以访问所有它用到的 Value,比如一个加法指令(%c = add nsw i32 %a, %b)用到了 a 和 b 这两个变量。

而在 Value 中,可以访问所有使用这个值的 User,比如给 c 赋值的这条指令。

所以,你可以遍历一个 Value 的所有 User,把它替换成另一个 Value,这就是拷贝传播。

接下来,我们看看如何用程序实现 IR 的优化。

在 LLVM 内部,优化工作是通过一个个的 Pass(遍)来实现的,它支持三种类型的 Pass:

  • 一种是分析型的 Pass(Analysis Passes),只是做分析,产生一些分析结果用于后序操作。
  • 一些是做代码转换的(Transform Passes),比如做公共子表达式删除。
  • 还有一类 pass 是工具型的,比如对模块做正确性验证。你可以查阅 LLVM 所支持的各种 Pass。

LLVM 所支持的 各种 Pass

下面的代码创建了一个 PassManager,并添加了两个优化 Pass:


// 创建一个PassManager
TheFPM = std::make_unique<legacy::FunctionPassManager>(TheModule.get());

// 窥孔优化和一些位计算优化
TheFPM->add(createInstructionCombiningPass());

// 表达式重关联
TheFPM->add(createReassociatePass());

TheFPM->doInitialization();

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

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

相关文章

wvp-GB28181-pro /ZLMediaKit 部署学习

前言&#xff1a; 请认真阅读作者提供的文档&#xff01;认真阅读&#xff01;认真阅读&#xff01;认真阅读&#xff01; 背景&#xff1a; 公司项目需要对接不同地方的监控设备&#xff08;海康、大华、火星等等未知设备&#xff09;。由于本人对于海康设备不太了解出现一大…

CAD Exchanger SDK 3.20.0 for Linux Crack

引入新格式 Autodesk Revit&#xff0c;支持 BIM 特定数据模型以及 CAD Exchanger 3.19.0 中的原生格式 CDXBIM 独立于 Revit 软件读取 RVT 文件&#xff0c;使用 BIM 特定数据模型探索 BIM 属性&#xff0c;并利用我们专有的 BIM 友好 CDXBIM 格式更快地加载大型模型。 BIM数…

运维自动化前三阶段

运维自动化前三阶段 纯手工阶段&#xff1a;手工操作重复地进行软件部署和运维&#xff1b; 脚本阶段&#xff1a;通过编写脚本、方便地进行软件部署和运维&#xff1b; 工具阶段&#xff1a;借助第三方工具高效、方便地进行软件部署和运维。 这几个阶段是随着运维知识、经验…

tcn介绍

tcn 介绍 背景 对于大多数深度学习从业者来说&#xff0c;序列建模是递归网络的代名词。 然而&#xff0c;最近的结果表明&#xff0c;卷积架构在音频合成和机器翻译等任务上可以优于递归网络。给定一个新的序列建模任务或数据集&#xff0c;应该使用哪种架构&#xff1f;我…

Apple visionOS UI设计规范

果发布首款 MR 设备 Vision Pro&#xff0c;正在倡导用于Vision Pro在真实空间中显示应用程序窗口和内容“空间用户界面设计”&#xff0c;苹果的设计团队解释了开发人员应该知道的空间用户界面设计的原则。visionOSUI设计规范 支持&#xff1a;sketch Vision Pro中安装的visio…

无线电音频-BPA600蓝牙协议分析仪名词解析

1 介绍 2 Baseband基带分析 (1)Delta 是什么含义? "Delta" 有多个含义,取决于上下文。以下是常见的几种含义: 希腊字母:Delta&#x

“layui助力博客管理升级!用增删改查功能打造优质博客体验“

目录 引文1.前置条件2.数据接口2.1 UserDao(CRUD)2.2 R工具类 3.HTML 结构3.1 主界面的HTML3.2 用户的查询所有界面的HTML3.3 新增修改通用的的HTML 4.JavaScript 代码4.1 用户的CRUD javaScript 代码(userManage)4.2 新增修改的javaScript代码(userEdit) 5. 运行截图总结 引文…

【SpringBoot构建Hippo4j-Client安装部署教程】

&#x1f680; 线程池管理工具-Hippo4j &#x1f680; &#x1f332; AI工具、AI绘图、AI专栏 &#x1f340; &#x1f332; 如果你想学到最前沿、最火爆的技术&#xff0c;赶快加入吧✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;CSDN-Java领域优质创作者&#…

uniapp和uview组件实现下拉触底刷新列表

下面是一个在UniApp中使用uView组件实现下拉触底刷新列表的示例&#xff0c;并使用Axios来请求分页数据列表&#xff1a; 首先&#xff0c;确保你已经在UniApp项目中添加了uView组件库。你可以在项目根目录执行以下命令安装它们&#xff1a; npm install uview-ui或者使用 Hb…

一文速览大语言模型在分子领域中的探索

随着 ChatGPT 的快速崛起&#xff0c;大型语言模型&#xff08;LLM&#xff09;已经在人类语言建模领域展示出了其非凡的能力。无论是证明数学公式、编写代码&#xff0c;还是以不同的风格创作诗歌&#xff0c;LLM 都能胜任。然而&#xff0c;尽管 LLM 在人类语言的掌握上已达到…

1、网络基础

网络发展背景、IP、端口、网络通信协议&#xff0c;TCP/IP五层模型、字节序 一、网络发展背景 局域网&#xff1a;网络覆盖在1000m以内的网络 城域网&#xff1a;网络覆盖在20km以内的网络 广域网&#xff1a;网络覆盖在20km以上的网络 因特网、互联网&#xff1a;更大的国…

SSH跳转远程目标服务器的高阶使用

在日常开发和运维的过程中&#xff0c;我一般是使用Xshell的工具对linux服务器的相关操作。我说一下我写这篇文章的背景&#xff1a;甲方因为安全需要&#xff0c;给了一台可以通过vpn访问的跳板机&#xff0c;通过这台跳板机去操作另外的十多台应用服务器&#xff0c;那么肯定…

MySQL 8目录结构与源码

目录 一、主要目录结构 二、获取MySQL 源代码 一、主要目录结构 MySQL的主要目录结构说明bin目录所有MySQL的可执行文件。如&#xff1a;mysql.exedata目录系统数据库所在的目录my.ini文件MySQL的主要配置文件D:\MySQL\Data用户创建的数据库所在的目录 二、获取MySQL 源代码 …

【OpenCV • c++】图像几何变换 | 图像平移

&#x1f680; 个人简介&#xff1a;CSDN「博客新星」TOP 10 &#xff0c; C/C 领域新星创作者&#x1f49f; 作 者&#xff1a;锡兰_CC ❣️&#x1f4dd; 专 栏&#xff1a;【OpenCV • c】计算机视觉&#x1f308; 若有帮助&#xff0c;还请关注➕点赞➕收藏&#xff…

代码随想录算法训练营day3 | 203. 移除链表元素,707. 设计链表,206. 反转链表

目录 203. 移除链表元素 707. 设计链表 206. 反转链表 203. 移除链表元素 难度&#xff1a;easy 思路&#xff1a; 代码&#xff1a; // 使用虚拟头结点 class Solution {public ListNode removeElements(ListNode head, int val) {if (head null) {return head;}// 虚拟…

Waves 14 Complete对Mac和Windows系统的最低要求

Waves 14 Complete是一款功能齐全的音频编辑软件&#xff0c;适用于音乐制作、音频工程和声音设计等领域。它提供了一系列强大的工具和效果&#xff0c;帮助用户在音频处理过程中实现专业水平的效果和混音。 Waves 14 Complete包含了多个实用的插件&#xff0c;如均衡器、压缩…

垃圾收集器CMS-JVM(十一)

Jvm类的创建过程包括类的加载&#xff0c;类的验证&#xff0c;准备&#xff0c;分析&#xff0c;初始化。 验证是不是.class文件。 准备过程则是先赋值初始化的值&#xff0c;并不是直接赋值原始值。 分析比较复杂&#xff0c;会有静态链接处理和动态链接处理。 最后就是类…

亚马逊云科技,加速生成式AI的落地

编辑&#xff1a;阿冒 设计&#xff1a;沐由 “展望今天的世界&#xff0c;在机遇之外&#xff0c;更多事后我们看到的是前所未有的巨大挑战。事实证明&#xff0c;惟有通过创新、专注创新&#xff0c;方能挖掘和发现更多的增长机会。” 在2023亚马逊云科技中国峰会的第二天&am…

【笔记】oracle线上生产数据库使用exp的方式更新到本地

笔记来源 今天的任务是&#xff1a;将线上老的数据库里的数据同步到本地现有的二期数据库中来&#xff0c;即二期项目需要线上数据进行最后测试&#xff0c;于是就有了今天这篇&#xff0c;线上生产数据库更新到本地数据库的笔记。 由于数据量较大&#xff0c;我尝试过将线上…

建表与数据准备

自己新建数据库: create table Student(sid varchar(10),sname varchar(10),sage datetime,ssex nvarchar(10));insert into Student values(01 , 赵雷 , 1990-01-01 , 男); insert into Student values(02 , 钱电 , 1990-12-21 , 男); insert into Student values(03 , 孙风 ,…