编译原理——代码优化学习笔记

动态规划入门==》转换为DAG问题——最短路径|矩阵嵌套|硬币问题 动态规划刚刚开始学习,到现在做过几道题,借鉴了各位大神的书籍文章后,对其有了新的看法。 现在我总结目前我遇到题目动态规划思想的共性——很多动态规划都可以转化为带权DAG问题,以下是几道题题,我从中总结了他们的DAG特性 一、DAG最短路径 在我们聊DAG时先来介绍一个最直接的DAG问题 问题描述: 给一个带权有向无环图G=(V,E),找出这个图里S==>E的最短路径。 这个问题 阅读详情

代码优化

基本块

基本块是满足下列条件的最大的连续三地址指令序列

  • 控制流只能从基本块的第一个指令进入该块。也就是说,没有跳转到基本块中间或末尾指令的转移指令
  • 除了基本块的最后一个指令,控制流在离开基本块之前不会跳转或者停机

基本块划分算法

输入:三地址指令序列
输出:输入序列对应的基本块列表,其中每个指令恰好被分配给一个基本块
方法:首先,确定指令序列中哪些指令是首指令(eaders),即某个基本块的第
一个指令

  • 指令序列的第一个三地址指令是一个首指令
  • 任意一个条件或无条件转移指令的目标指令是一个首指令
  • 紧跟在一个条件或无条件转移指令之后的指令是一个首指令

然后,每个首指令对应的基本块包括了从它自己开始,直到下一个首指令(不含)或者指令序列结尾之间的所有指令

基本块的优化

在阅读完常用的代码优化方法后阅读此节
很多重要的局部优化技术首先把一个基本块转换成为一个无环有向图(DAG)

  • 基本块中的每个语句S都对应一个内部结点N
    • 结点N的标号是s中的运算符;同时还有一个定值变量表被关联到N,表示S是在此基本块内最晚对表中变量进行定值的语句
    • N的子结点是基本块中在s之前、最后一个对s所使用的运算分量进行定值的语句对应的结点。如果s的某个运算分量在基本块内没有在s之前被定值,则这个运算分量对应的子结点就是代表该运算分量初始值的叶结点(为区别起见,叶节点的定值变量表中的变量加上下脚标0)
    • 在为语句=y+z构造结点N的时候,如果x已经在某结点M的定值变量表中,则从M的定值变量表中删除变量X

对于形如x=y+z的三地址指令如果已经有一个结点表示y+z就不往DAG中增加新的结点,而是给已经存在的结点附加定值变量x

基于基本块的DAG删除无用代码

从一个DAG上删除所有没有附加活跃变量(活跃变量是指其值可能会在以后被使用的变量)的根结,点(即没有父结点的结点)。重复应用这样的处理过程就可以从DAG中消除所有对应于无用代码的结点

数组元素赋值指令的表示

对于形如a[j]=y的三地址指令创建一个运算符为“[]=”的结点,这个结点有3个子结点,分别表示a、j和y
该结点没有定值变量表
该结点的创建将杀死所有已经建立的、其值依赖于a的结点
一个被杀死的结点不能再获得任何定值变量,也就是说,它不可能成为一个公共子表达式

DAG获得的信息
  • 确定哪些变量的值在该基本块中赋值前被引用过
  • 确定哪些语句计算的值可以在基本块外被引用
从DAG到基本块的重组
  • 对每个具有若干定值变量的节点,构造一个三地址语句来计算其中某个变量的值
  • 如果结点有多个附加的活跃变量,就必须引入复制语句,以便给每一个变量都赋予正确的值

流图

流图的结点是一些基本块
从基本块B到基本块C之间有一条边当且仅当基本块C的第一个指令可能紧跟在B的最后一条指令之后执行
此时称B是C的前驱,C是B的后继
有两种方式可以确认这样的边

  • 有一个从B的结尾跳转到C的开头的条件或无条件跳转语句
  • 按照原来的三地址语句序列中的顺序,C紧跟在之B后,且B的结尾不存在无条件跳转语句

常用的代码优化方法

优化的分类

  • 机器无关优化:针对中间代码
  • 机器相关优化:针对目标代码
  • 局部代码优化:单个基本块范围内的优化
  • 全局代码优化:面向多个基本块的优化

常用的优化方法

  • 删除公共子表达式
  • 删除无用代码
  • 常量合并
  • 代码移动
  • 强度削弱
  • 删除归纳变量
删除公共子表达式

公共子表达式定义

如果表达式x op y先前已被计算过,并且从先前的计算到现在,x op y中变量的值没有改变,那么x op y的这次出现就称为公共子表达式

删除无用代码

常用的公共子表达式消除算法和其它一些优化算法会引入一些复制语句(形如x=y的赋值语句)
复制传播:在复制语句x=y之后尽可能地用y代替x,复制传播给删除无用代码带来机会
无用代码:其计算结果永远不会被使用的语句

常量合并

如果在编译时刻推导出一个表达式的值是常量,就可以使用该常量来替代这个表达式。该技术被称为常量合并

代码移动

这个转换处理的是那些不管循环执行多少次都得到相同结果的表达式(即循环不变计算)在进入循环之前就对它们求值

循环不变的相对性

对于多重嵌套的循环,循环不变计算是相对于某个循环而言的。可能对于更加外层的循环,它就不是循环不变计算

强度削弱

用较快的操作代替较慢的操作,如用加代替乘

删除归纳变量

对于一个变量x,如果存在一个正的或负的常数c使得每次x被赋值时它的值总增加c,那么x就称为归纳变量
归纳变量可以通过在每次循环迭代中进行一次简单的增量运算(加法或减法)来计算
在沿着循环运行时,如果有组归纳变量的值的变化保持步调一致,常常可以将这组变量删除为只剩一个

数据流分析

定义:组用来获取程序执行路径上的数据流信息的技术
在每一种数据流分析应用中,都会把每个程序,点和一个数据流值关联起来
IN[s]:语句S之前的数据流值
OUT[s]:语句S之后的数据流值
Fs:语句s的传递函数
设基本块B由语句s1,s2,…,Sn顺序组成
则IN[si+1]=OUT[si] i=1,2,…,n-1

到达定值分析

定值:变量x的定值是(可能)将一个值赋给x的语句
到达定值:直观地讲,如果某个变量x的一个定值d到达点p,在点p处使用的x的值可能就是由d最后赋予的

主要用途

循环不变计算的检测

如果循环中含有赋值x=y+z,而y和z所有可能的定值都在循环外面(包括y或z是常数的特殊情况),那么y+z就是循环不变计算

常量合并

如果对变量x的某次使用只有一个定值可以到达,并且该定值把一个常量赋给x,那么可以简单地把x替换为该常量

判定变量x在P点上是否未经定值就被引用

生成与杀死定值

定值d:u=v+w
该语句“生成”了一个对变量u的定值d,并“杀死”了程序中其它对u的定值

到达定值的传递函数

fd:定值d:u=v+w的传递函数
fd(x)=gend∪(x−killd)f_d(x)=gen_d\cup(x-kill_d)fd​(x)=gend​∪(x−killd​)

  • gendgen_dgend​:由语句d生成的定值的集合
  • killdkill_dkilld​:由语句d杀死的定值的集合(程序中所有其它对u的定值)

到达定值的数据流方程

OUT[ENTRY]=ΦOUT[ENTRY]=\PhiOUT[ENTRY]=Φ
OUT[B]=fB(IN[B])B≠ENTRYOUT[B]=f_B(IN[B])\quad B\neq ENTRYOUT[B]=fB​(IN[B])B​=ENTRY
fB(x)=genB∪(x−killB)f_B(x)=gen_B\cup(x-kill_B)fB​(x)=genB​∪(x−killB​)
IN[B]=∪P是B的一个前驱OUT[P]B≠ENTRYIN[B]=\cup_{P是B的一个前驱}OUT[P]\quad B\neq ENTRYIN[B]=∪P是B的一个前驱​OUT[P]B​=ENTRY

计算方法

输入:流图G,其中每个基本块B的genBgen_BgenB​和killBkill_BkillB​都已计算出来
输出:IN[B]和OUT[B]
方法:
OUT[ENTRY]=ΦOUT[ENTRY]=\PhiOUT[ENTRY]=Φ
for(除ENTRY之外的每个基本块B) OUT[B]=ΦOUT[B]=\PhiOUT[B]=Φ;
while(某个OUT值发生了改变)
for(除ENTRY之外的每个基本块B)
{
IN[B]=∪P是B的一个前驱OUT[P]IN[B]=\cup_{P是B的一个前驱}OUT[P]IN[B]=∪P是B的一个前驱​OUT[P]
OUT[B]=genB∪(IN[B]−killB)OUT[B]=gen_B\cup(IN[B]-kill_B)OUT[B]=genB​∪(IN[B]−killB​)
}

引用定值链(ud链)

  • 如果块B中变量a的引用之前有a的定值,那么只有a的最后一次定值会在该引用的ud链中
  • 如果块B中变量a的引用之前没有a的定值,那么a的这次引用的ud链就是N[B]中a的定值的集合

活跃变量分析

对于变量x和程序点p,如果在流图中沿着从p开始的某条路径会引用变量x在p点的值,则称变量x在点p是活跃的,否则称变量x在点p不活跃

主要用途

  • 删除无用变量
  • 为基本块分配寄存器

可用表达式分析

如果从流图的首节点到达程序点P的每条路径都对表达式x op y进行计算,并且从最后一个这样的计算到点p之间没有再次对x或y定值,那么表达式x op y在点p是可用的

【编译原理笔记18】代码优化:活跃变量分析,可用表达式分析 关于活跃变量与可用表达式的分析。 阅读详情

相关推荐

【从零开始学习计算机科学】编译原理(八)代码优化 与 目标代码生成

划分基本块的思路主要为:入口语句可以是程序的第一个语句、能由条件语句或无条件转移语句转到的语句、紧跟在条件转移语句后面的语句;通常,在进行了归纳变量的替换后,相应的赋值代码成了可删除的死代码。如果,条件或无条件语句从B1转到B2,且B2紧跟在B1后面(且B1最后语句不是无条件转移语句),此时称B2为B1的后继,B1为B2的前驱。窥孔优化是一种简单有效的局部优化方法,它通过检查目标指令的短序列(称为窥孔),并尽可能用更小更短的指令代替这些指令以提高目标程序的性能。复制传播的目的是使某些变量的赋值变为无用。

AI科研社 1262

编译原理:代码优化

常用的优化方法 删除公共子表达式 删除无用代码 常量合并 代码移动 强度削弱 删除归纳变量 基本块的优化: 局部优化技术大部分都是将基本块转为有向无环图(DAG). 每个语句s都对应一个内部结点N 结点N的标号是s中的运算符;同时还有一个定值变量表被关联到N ,表示s是在此基本块内最晚对表中变量进行定值的语句 N的子结点是基本块中在s之前、最后一个对s所使用的运算分量进行定值的语句对应的结点。 基于DAG删除无用代码: 删除所有没有附加活跃变量(活跃变量是指其值可能会在以后被使用的变量)的根结点(即

Keep Fighting! 5469

由基本块构造DAG图的程序实现(编译原理课设报告)

问题描述 输入任意给定的基本块,构造与之等价的DAG图,并以图形方式输出。 基本要求 输入的形式和输入值的范围 以四元式的形式输入任意给定的基本块,即一个字符串,最左边和右边是两个括号(),四个符号之间用三个逗号相隔。 在系统输出,基本块对应的三地址代码时。用户应当告诉系统自己以后还要用哪个变量。 输出的形式 (1)以三地址代码方式输出用户输入的基本块 (2)以图形方式输出DAG图 (3)输出化简之后的三地址代码 程序所能达到的功能 用户输入任意给定的基本块,先通过三地址代码的方式,将用户输入的基本块以三地址的方式进行输出,构造出DAG,以图形的方式进行输出。输出简化之后的三地址代码。

编译技术-优化理论

这是我们学的第一个全局数据流分析,但是只能说教材封装得太好了。肯定这些分析是全局数据流分析,但是以基本块为颗粒度是怎么一回事?即使分析出了基本块的 in 或者 out,对于实际的改写程序并没有办法起到指导意义,这是因为改写的颗粒度是指令级的。显然一个粗粒度的分析没办法指导一个细粒度的改写。进行块级颗粒度的数据流分析,这个部分具有全局性质,会统筹考虑 CFG 的数据流向问题。在每个块内进行指令级颗粒度的数据流分析,这个部分发生在局部,利用的是块级颗粒度分析的结果,不需要考虑全局信息。

living_frontier的博客 1543

PID详解

1、什么是PID及其作用 设定一个输出目标,反馈系统传回输出值,如与目标不一致,则存在一个误差,PID 根据此误差调整输入值,直至输出达到设定值. 为什么需要PID呢,比如控制温度,我们需要设置一个要达到的目标温度值,当将温度稳定在目标温度值 例如,我们希望水的目标温度值为70°,其希望无非就是可以快速而且无抖动的达到70°,并稳定在70° 如果我们使用普通的方式加热,当温度到达70°后就以及停止加热,岂不是简单快速,当然用在要求不高的场合也可以,但是如果要求更高的场合呢,会出现温度到达70°后......

weixin_48435215的博客 5万+

《UE4游戏开发》之 《查cook资源失败,问题记录》

当项目打包时,cook出错,但是从原始引擎提供的信息中,没有提示具体的那个资源出错,要查到出错资源,还是非常麻烦。 下面就材质cook出错,增加一些日志,方便查找问题做简单记录 材质cook的一个阶段,是收集MaterialShaderMap,如果在这个阶段收集的信息出错,将会在FShaderMapContent::GetOutdatedTypes函数中,因为Shaders指针指向的内存有问题而出错,通过断点发现,FShaderMapContent这个类对象指针为null,而这个类对象的来源于AllMat.

qq_21919621的博客 2580

三种数据流分析的方程、用途

坐标:编译原理,代码优化 数据流分析的应用 引用定义链的到达-定义分析(前向数据流问题)、活跃变量分析(逆向数据流问题)、可用表达式分析。 在每一种数据流分析应用中,都会把每个程序点和一个数据流值关联起来。基本上这个程序点是基本块层级。 基本块的数据流分析方程 B:基本块,IN[B]: 紧靠基本块之前的数据流值,OUT[B]: 紧随基本块之后的数据流值,fB: 基本块B的传递函数。注意数据流的方向。 正向: 教课书中则是这样的数据流方程,S是一条语句 其中,gen[S]是在S中...

u011730792的专栏 3820

Modelsim 安装步骤详解

Modelsim 安装步骤详解目录一、modelsim简述及下载1、简介及特点2、modelsim版本3、modelsim下载二、安装步骤详解三、注册简述四、总结与参考资料1、总结2、参考资料 目录 本篇文章主要对Modelsim SE版本安装步骤的介绍。 一、modelsim简述及下载 1、简介及特点 简介 modelsim是Mentor公司开发的优秀的HDL语言仿真软件。 它能提供友好的仿真环境,采用单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术和单

执迷不悟 15万+

【编译原理】编译原理知识点汇总·代码优化

为什么打算开始这一系列的文章——编译原理🎄🎄其实本学期开始就一直想持续更新,陆陆续续主要更新了实验部分。正好趁着快要考试,便和大家一起花费几天的时间回顾编译原理的知识点。目前,​本来没有想处理代码优化和目标代码生成部分,但是考虑到完整性还是选择肝一肝更新完整祝大家都能取得好成绩呀~~🥰🥰英文名:Compilers: Principles,Techniques,and Tools (龙书)🦖作者:Alfred V.Aho,Ravi Sethi,Jeffrey D.Ullman。

十二月的猫 2201

[SystemC]SystemC中的模块和程序

SystemC 中的层次结构是使用类 sc_module 创建的。sc_module 可以直接使用,也可以使用宏 SC_MODULE “隐藏”。上面的示例 SC_MODULE 创建了一个名为 nand2 的 sc_module 类对象。它的输出纯粹是输入值的函数。因此,模型可以使用最简单的 SystemC 进程,即 SC_METHOD。摘要:本节包含一个完整的简单设计,用于演示 SystemC 中模块和流程的使用。同样,重要的是要注意这不是典型的设计风格 - 但它很好而且易于理解。为什么要看模块和流程?

元直的博客 1867

petalinux2022.2启动文件编译配置

petalinux2021之前的版本里,导入目录components/yocto/下的“environment-setup-aarch64-xilinx-linux” 和 “layers/core/oe-init-build-env”的环境,能使用Yocto的devtool工具。(加入下面内容,先petalinux-build下载完成后才能有源码)制作 BOOT.BIN 启动文件:petalinux-package --boot --fsbl --fpga --u-boot --force。

wangjie36的博客 1389

编译原理学习笔记(十二)代码优化

代码优化 以老师PPT为标准,借鉴部分教材内容,AlvinZH学习笔记。 概述 .1. 目的:提高目标代码运行效率。时间效率(减少运行时间);空间效率(减少内存容量)。 原则:进行优化必须严格遵循“不能改变原有程序语义”原则。 2. 优化的分类 从优化的层次,与机器是否有关,分为:独立于机器的优化、与机器有关的优化。 从优化涉及的范围,又分为:局部优化、循环优化、全局优化。 3. 满足以下三个条件...

weixin_30384031的博客 208

MyBatis-Plus 实战:敏感字段自动加解密支持模糊查询

本文基于MyBatis-Plus框架提出了一种全链路敏感字段加密方案。通过自定义TypeHandler实现数据入库自动加密和查询自动解密,结合重写LambdaQueryWrapper处理查询条件加密,并适配多种查询方式。方案核心包括:1)AESUtil工具类提供加解密基础能力;2)EncryptTypeHandler实现字段类型转换;3)实体类通过注解配置加密字段。该方案在保证数据安全的同时,对业务代码侵入性小,支持姓名、手机号等敏感信息的全流程加密处理,满足系统开发的安全需求。

蔡定努 596

编译原理学习笔记

属性是附加在产生式中节点的语义定义。这个定义有点抽象,结合下面这个产生式,会有更好的理解:第一列是产生式,第二列是具体的语义定义。这个产生式语义定义表示的是算法加法。(关于上面的语义定义我的理解:比如说 '+' 这个符号,可理解成字符串连接,也可以,理解成是算法加法,具体如何定义,就看语义规则是如何定义的。E1.val,val就是E1的属性值T.val ,val就是T.val的属性值E.val ,val就是E.val的属性值综合属性自下而上传递信息语法规则:产生式右部确定左部。

Twilightly的博客 1146

基于FPGA的以太网设计(1)----大白话解释什么是以太网

基于FPGA的千兆以太网设计(1)----大白话解释什么是以太网

孤独的单刀 3869

7、CUDA 软件架构与开发工具详解

本文深入探讨了CUDA的软件架构与核心开发工具,涵盖CUDA数组与纹理、表面引用、图形互操作性机制,以及CUDA运行时与驱动程序API的功能对比。详细解析了nvcc编译器的使用方法、编译轨迹与代码生成选项,并结合实际示例说明其应用。文章旨在帮助开发者理解不同技术的选择依据,合理利用CUDA工具链,提升GPU计算性能,适用于从入门到进阶的CUDA开发人员参考。

nnn11的博客 98

Spring Boot3零基础教程,JVM 编译原理,笔记87

Spring Boot3零基础教程,JVM 编译原理,笔记87

道友 566

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

编译原理(8):代码优化

声明:本系列文章,是根据中国大学MOOC网 哈工大的编译原理 这门课学习而成的学习笔记。 一、流图 基本块(Basic Block) 基本块是满足下列条件的最大的连续三地址指令序列 控制流只能从基本块的第一个指令进入该块。也就是说,没有跳转到基本块中间或末尾指令的转移指令 除了基本块的最后一个指令,控制流在离开基本块之前不会跳转或者停机 基本块划分算法 首先(1)指令是首指令,其次跟在...

weixin_44226857的博客 6528

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

编译原理之代码优化

前面介绍完了词法分析、语法分析和语义分析,以及各阶段如何利用符号表来实现代码合理性确认以及代码地址拉链式回填等工作。编译原理出于代码编译的模块化组装考虑,一般会在语义分析的阶段生成平台无关的中间代码,经过中间代码级的代码优化,而后作为输入进入代码生成阶段,产生最终运行机器平台上的目标代码,再经过一次目标代码级别的代码优化(一般和具体机器的硬件结构高度耦合,复杂且不通用)。故而出于理解编译原理的角度考

墨篙和小奶猫 2万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

编译原理实验六—代码优化

实验目的: 1. 通过上机实习,加深对代码优化的理解,掌握基本块优化、循环优化的方法。  2.  掌握利用 DAG 进行基本块优化的技术。  坑....闷头写了两天总算模拟出了个能跑得起来的差不多的代码,里面还有很多地方可以优化,函数和结构都有很多....先懒着这样吧 实现代码(待改进版) #include #define PB push_back using n

Jazz_Charles的博客 4034

[编译原理] 中间代码生成 代码优化

编译原理 —— 代码优化

Tumb1eweed的博客 1655

【编译原理笔记16】代码优化:流图,常用代码优化方法, 基本块的优化

以基本块为单位,进行运算上的推导优化。堪称妙!原来编译器这么强大!

记录学习痕迹的公众号:Piper蛋窝 6378

【编译原理】一篇就够了——学习笔记与课程实验超详细整理

编译原理学习笔记,一篇就够!,对应龙书的1-9章内容,详细介绍了相关方法原理与步骤。同时整理基于Java的词法分析与语法分析的课程实验

一棵灬大树的博客 1万+

[编译原理学习笔记1] 引论

[编译原理学习笔记1] 引论 文章目录[编译原理学习笔记1] 引论[1.1] 编译程序[1.2] 编译过程[1.3] 编译程序与程序设计环境 [1.1] 编译程序 编译器 就是一个程序,它读入用某种语言编写的源程序,并翻译成一个与之等价的另一种语言编写的源程序。 [1.2] 编译过程 词法分析:输入源程序,对构成源程序的字符串进行扫描和分解,识别出一个个单词(也称单词符号,或简...

TalesOV的博客 1062
上一篇: ics大作业
下一篇: java学习笔记——文档注释标记总结
StrangeStranger
博客等级 码龄6年 24粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值