当前位置:网站首页>编译器优化那些事儿(4):归纳变量
编译器优化那些事儿(4):归纳变量
2022-07-07 17:39:00 【openEuler】
0. 基础知识盘点
0.1 循环(loop)
定义
loop(llvm里理解为natural loop)是定义在CFG中的一个结点集合L,并具有以下属性[1][2]:
有单一的入口结点(称为header),该结点支配loop中的所有结点; 存在一条进入循环头的回边;
相关术语
entering block:一个非loop内的结点有一条边连接到loop。当只有一个entering block且其只有一条边连接到header,称之为preheader;作为非loop结点的peheader支配整个loop; latch:有一条边连接到header; backedge:称为回边,一条从latch到header的边; exiting edge:一条边从loop内到loop外,边的出发结点称之为exiting block,目标结点称之为exit block;
上面右图中,黄色区域是一个loop,而红色区域不是,为什么呢?
因为红色区域a和c都是入口结点,不满足单一入口结点的性质。
0.2 Scalar Evolution(SCEV)
定义
SCEV是编译器对变量进行分析的优化(往往只针对整数类型),且主要用于分析循环中变量是如何被更新的,然后根据这个信息来进行优化。
循环链
如图所示,循环中归纳变量var
的起始值为start
,迭代的方式为ϕ
,步长为step
;
它的循环链(chrec,Chains of Recurrences)如下:
var = {start, ϕ , step}
// ϕ∈{+,∗}
// start: starting value
// step: step in each iteration
举个例子:
int m = 0;
for (int i = 0; i < n; i++) {
m = m + n;
*res = m;
}
那么m的循环链为:m = {0,+,n}
。
1. Induction Variable(归纳变量)
1.1 定义
循环的每次迭代中增加或减少固定量的变量,或者是另一个归纳变量的线性函数。
举个例子[3],下面循环中的i和j都是归纳变量:
for (i = 0; i < 10; ++i) {
j = 17 * i;
}
1.2 益处
归纳变量优化的好处,有但不局限于以下几点:
用更简单的指令替换原来的计算方式。
比如,上面的例子中识别到归纳变量,将对应的乘法替换为代价更小的加法。j = -17;
for (i = 0; i < 10; ++i) {
j = j + 17;
}减少归纳变量的数目,降低寄存器压力。
extern int sum;
int foo(int n) {
int i, j;
j = 5;
for (i = 0; i < n; ++i) {
j += 2;
sum += j;
}
return sum;
}当前的loop有两个归纳变量:i、j,用其中一个变量表达另外一个后,如下:
extern int sum;
int foo(int n) {
int i;
for (i = 0; i < n; ++i) {
sum += 5 + 2 * (i + 1);
}
return sum;
}归纳变量替换,使变量和循环索引之间的关系变得明确,便于其他优化分析(如依赖性分析)。举例如下,将c表示为循环索引相关的函数:
int c, i;
c = 10;
for (i = 0; i < 10; i++) {
c = c + 5; // c is incremented by 5 for each loop iteration
}转换为:
int c, i;
c = 10;
for (i = 0; i < 10; i++) {
c = 10 + 5 * (i + 1); // c is explicitly expressed as a function of loop index
}
2. 实践
2.1 相关编译选项
compiler | option |
---|---|
gcc | -fivopt |
毕昇 | -indvars |
2.2 优化用例
归纳变量的优化(ivs)在llvm中的位置是:llvm\lib\Transforms\Scalar\IndVarSimplify.cpp
让我们通过一个用例,看看毕昇编译器的优化过程。
如下图,假设上面func
里面的部分就是要优化的代码,下面func里面就是预期生成的结果:
它的IR用例test.ll
是:
编译命令是:
opt test.ll -indvars -S
当前的例子中,header
、latch
和exiting block
都是同一个BB,即bb5。
步骤一:依据 def-use
关系,遍历loop的 ExitBlock
中phi结点的操作数的来源,计算出最终值同时替换它,继而替换该phi结点的使用。
例子中,计算 %tmp2.lcssa
,其唯一的操作数是 %tmp2 = add nuw nsw i32 %i.01.0, 3
,该表达式所在的loop是bb5,此时 %tmp2
的循环链为
%tmp2 = {3,+,3}<nuw><nsw><%bb5>
获取当前loop的不退出循环的最大值是199999
,那当前 %tmp2=add(3, mul(3,199999))=600000
;接下来会看当前的替换不是高代价(代价的计算会依据不同架构有所不同),同时在phi结点的 user
中替换该值。优化结果如下:
步骤二:遍历 ExitingBlock
,对其跳转条件进行计算,依据 def-use
的关系,删除相应的指令。
例子中,计算出 br i1 %0, label %bb5, label %bb7
的 %0
是 false
,跳转指令替换后,%0 = icmp ult i32 %tmp4,200000
不存在 user
,将其加入到“死指令”中。优化结果如下:
步骤三:删除所有“死指令”,并看看他的操作数是否要一并删除。
例子中,作为 %0
的操作数的 %tmp4
还有其他的 user %x.03.0
,因此不能被视为“死指令”被删除。优化结果如下:
步骤四:删除 HeaderBlock
中的“死”phi结点。
例子中, %tmp4
和phi结点 %x.03.0
构成了一个不会有成果的循环,就会删除它们,同理删除 %tmp2
和 %i.01.0
。优化结果如下:
参考
[1] https://llvm.org/docs/LoopTerminology.html
[2] 《编译原理》 [美]Alfred V.Aho,[美]Monica S.Lam,[美]Ravi Sethi等著,赵建华,郑滔等译
[3] https://en.wikipedia.org/wiki/Induction_variable

点击 阅读原文 开始使用毕昇编译器
本文分享自微信公众号 - openEuler(openEulercommunity)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
边栏推荐
- 转置卷积理论解释(输入输出大小分析)
- R语言使用ggplot2函数可视化需要构建泊松回归模型的计数目标变量的直方图分布并分析构建泊松回归模型的可行性
- Make insurance more "safe"! Kirin Xin'an one cloud multi-core cloud desktop won the bid of China Life Insurance, helping the innovation and development of financial and insurance information technolog
- Le PGR est - il utile au travail? Comment choisir une plate - forme fiable pour économiser le cœur et la main - d'œuvre lors de la préparation de l'examen!!!
- 时间工具类
- 爬虫实战(七):爬王者英雄图片
- R language ggplot2 visualization: use the ggecdf function of ggpubr package to visualize the grouping experience cumulative density distribution function curve, and the linetype parameter to specify t
- 网易云信参与中国信通院《实时音视频服务(RTC)基础能力要求及评估方法》标准编制...
- 关于ssh登录时卡顿30s左右的问题调试处理
- 解决远程rviz报错问题
猜你喜欢
微信公众号OAuth2.0授权登录并显示用户信息
Dynamic addition of El upload upload component; El upload dynamically uploads files; El upload distinguishes which component uploads the file.
杰理之相同声道的耳机不允许配对【篇】
Netease Yunxin participated in the preparation of the standard "real time audio and video service (RTC) basic capability requirements and evaluation methods" issued by the Chinese Academy of Communica
Former richest man, addicted to farming
一张图深入的理解FP/FN/Precision/Recall
杰理之手动配对方式【篇】
[Verilog advanced challenge of Niuke network question brushing series] ~ multi bit MUX synchronizer
项目经理『面试八问』,看了等于会了
CMD command enters MySQL times service name or command error (fool teaching)
随机推荐
LC: string conversion integer (ATOI) + appearance sequence + longest common prefix
# 欢迎使用Markdown编辑器
LC:字符串转换整数 (atoi) + 外观数列 + 最长公共前缀
MySQL、sqlserver oracle数据库连接方式
Interpretation of transpose convolution theory (input-output size analysis)
R language ggplot2 visualization: use the ggstripchart function of ggpubr package to visualize the dot strip plot, set the position parameter, and configure the separation degree of different grouped
2022年投资哪个理财产品收益高?
Tips and tricks of image segmentation summarized from 39 Kabul competitions
CMD command enters MySQL times service name or command error (fool teaching)
How to estimate the value of "not selling pens" Chenguang?
银行理财产品怎么买?需要办银行卡吗?
L1-027 rental (Lua)
LeetCode 515(C#)
关于ssh登录时卡顿30s左右的问题调试处理
how to prove compiler‘s correctness
R language ggplot2 visualization: use the ggviolin function of ggpubr package to visualize the violin diagram, set the palette parameter to customize the filling color of violin diagrams at different
【牛客网刷题系列 之 Verilog进阶挑战】~ 多bit MUX同步器
转置卷积理论解释(输入输出大小分析)
R语言dplyr包select函数、group_by函数、filter函数和do函数获取dataframe中指定因子变量中指定水平中特定数值数据列的值第三大的值
PMP對工作有益嗎?怎麼選擇靠譜平臺讓備考更省心省力!!!