0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

SCEV如何对变量进行分析优化

openEuler 来源:openEuler 作者:openEuler 2022-07-07 11:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

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;

10e78e90-fd25-11ec-ba43-dac502259ad0.jpg

上面右图中,黄色区域是一个loop,而红色区域不是,为什么呢?
因为红色区域a和c都是入口结点,不满足单一入口结点的性质。

0.2 Scalar Evolution(SCEV)

定义

SCEV是编译器对变量进行分析的优化(往往只针对整数类型),且主要用于分析循环中变量是如何被更新的,然后根据这个信息来进行优化。

循环链

如图所示,循环中归纳变量var的起始值为start,迭代的方式为ϕ,步长为step;

10f6beec-fd25-11ec-ba43-dac502259ad0.jpg

它的循环链(chrec,Chains of Recurrences)如下:

var = {start, ϕ , step}
// ϕ∈{+,∗}
// start: starting value
// step: step in each iteration

举个例子:

intm=0;
for(inti=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;
}

减少归纳变量的数目,降低寄存器压力。

externintsum;
intfoo(intn){
inti,j;
j=5;
for(i=0;i< n; ++i) {
        j += 2;
        sum += j;
    }
    return sum;
}

当前的loop有两个归纳变量:i、j,用其中一个变量表达另外一个后,如下:

externintsum;
intfoo(intn){
inti;
for(i=0;i< n; ++i) {
        sum += 5 + 2 * (i + 1);
    }
    return sum;
}

归纳变量替换,使变量和循环索引之间的关系变得明确,便于其他优化分析(如依赖性分析)。举例如下,将c表示为循环索引相关的函数:

intc,i;
c=10;
for(i=0;i< 10; i++) {
    c = c + 5; // c is incremented by 5 for each loop iteration
}

转换为:

intc,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中的位置是:llvmlibTransformsScalarIndVarSimplify.cpp
让我们通过一个用例,看看毕昇编译器的优化过程。
如下图,假设上面func里面的部分就是要优化的代码,下面func里面就是预期生成的结果:

11136ae2-fd25-11ec-ba43-dac502259ad0.jpg

它的IR用例test.ll是:

11261e44-fd25-11ec-ba43-dac502259ad0.jpg

编译命令是:

opt test.ll -indvars -S

当前的例子中,header、latch和exiting block都是同一个BB,即bb5。

11418b5c-fd25-11ec-ba43-dac502259ad0.jpg

步骤一:依据 def-use 关系,遍历loop的 ExitBlock 中phi结点的操作数的来源,计算出最终值同时替换它,继而替换该phi结点的使用。
例子中,计算 %tmp2.lcssa ,其唯一的操作数是 %tmp2 = add nuw nsw i32 %i.01.0, 3 ,该表达式所在的loop是bb5,此时 %tmp2 的循环链为

%tmp2={3,+,3}<%bb5>

获取当前loop的不退出循环的最大值是199999,那当前 %tmp2=add(3, mul(3,199999))=600000;接下来会看当前的替换不是高代价(代价的计算会依据不同架构有所不同),同时在phi结点的 user 中替换该值。优化结果如下:

1154e684-fd25-11ec-ba43-dac502259ad0.jpg

步骤二:遍历 ExitingBlock ,对其跳转条件进行计算,依据 def-use 的关系,删除相应的指令。
例子中,计算出 br i1 %0, label %bb5, label %bb7 的 %0 是 false,跳转指令替换后,%0 = icmp ult i32 %tmp4,200000 不存在 user,将其加入到“死指令”中。优化结果如下:

11690db2-fd25-11ec-ba43-dac502259ad0.jpg

步骤三:删除所有“死指令”,并看看他的操作数是否要一并删除。
例子中,作为 %0 的操作数的 %tmp4 还有其他的 user %x.03.0,因此不能被视为“死指令”被删除。优化结果如下:

118b3f04-fd25-11ec-ba43-dac502259ad0.jpg

步骤四:删除 HeaderBlock 中的“死”phi结点。
例子中, %tmp4 和phi结点 %x.03.0 构成了一个不会有成果的循环,就会删除它们,同理删除 %tmp2 和 %i.01.0 。优化结果如下:

11c0930c-fd25-11ec-ba43-dac502259ad0.jpg

原文标题:编译器优化那些事儿(4):归纳变量

文章出处:【微信公众号:openEuler】欢迎添加关注!文章转载请注明出处。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5589

    浏览量

    129057
  • 编译器
    +关注

    关注

    1

    文章

    1669

    浏览量

    51080
  • CFG
    CFG
    +关注

    关注

    0

    文章

    10

    浏览量

    10098

原文标题:编译器优化那些事儿(4):归纳变量

文章出处:【微信号:openEulercommunity,微信公众号:openEuler】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    请问Keil的优化等级到底该如何选择?

    做任何优化。代码的执行顺序与源代码完全一致,变量始终存储在内存中(不进行寄存器优化),函数调用栈帧清晰。 -O1 (有限优化 / Opti
    发表于 11-20 07:51

    Coremark测试集分析与性能优化思路

    需要执行switch和if语句。因此,这部分代码使用一个小型摩尔状态机,它将字符串输入标识为数字,并根据格式对其进行划分。 状态机将解析输入字符串,直到遇到“,”分隔符或输入结束。无效数字将导致状态机
    发表于 10-24 08:21

    如何对蜂鸟e203内核乘除法器进行优化

    器:对每个流水线阶段中的数据进行部分商和余数的计算和累加操作。 二、优化方案 优化乘法器 为了提高蜂鸟E203的乘法器性能,可以采取以下几个优化方案: 采用更高效的算法:Booth算
    发表于 10-24 06:47

    推进电机端盖结构的抗冲击分析优化

    。同时以此为基础,在保证推进电机的抗冲击性能的约束前提条件下,以提高电机的转矩密度为目标,建立了相应的数学模型和参数化的有限元模型,对该结构进行了设计优化,为实际工程设计了奠定基础。 纯分享帖,需要者可点
    发表于 06-23 07:12

    VirtualLab:光栅的优化分析

    光栅是光学工程师使用的最基本的工具。为了设计和分析这类组件,快速物理光学建模和设计软件VirtualLab Fusion为用户提供了许多有用的工具。其中包括参数优化,以轻松优化系统,以及参数运行,它
    发表于 05-23 08:49

    VirtualLab 应用:倾斜光栅的参数优化及公差分析

    允许为目标值定义参数约束和权重值。更多信息请参见: 参数优化文档的介绍 第一级次的参数优化 **结果——公差分析 **
    发表于 05-22 08:52

    RAKsmart服务器SEO优化优势分析

    在RAKsmart服务器上搭建SEO网站,可以借助其基础设施和服务特性,从技术层面优化搜索引擎排名。以下是具体优势及分析,主机推荐小编为您整理发布RAKsmart服务器SEO优化优势分析
    的头像 发表于 04-22 10:12 470次阅读

    Ansible Playbook中的变量使用技巧

    在inventory中定义的连接变量(比如ansible_ssh_user);优先级第二。
    的头像 发表于 04-15 10:26 673次阅读

    VirtualLab Fusion应用:使用optiSLang进行光栅优化

    1.摘要 当代光学系统的优化往往涉及大量参数。正如光栅的优化设计,不仅需要考虑光栅的几何参数,更需要分析所需的入射方向。这样的需求导致优化过程面临大量参数的挑战。在本实例中,Virtu
    发表于 03-18 08:51

    VirtualLab Fusion应用:非近轴衍射分束器的设计与优化

    )的结构设计生成一系列分束器的初始设计,然后通过傅里叶模态法或严格耦合波分析(FMM/RCWA)进一步优化。为了给最后一个优化步骤定义一个合适和有效的优化函数,应用了可编程光栅
    发表于 03-10 08:56

    VirtualLab Fusion应用:光栅的鲁棒性分析优化

    一个场景,在这个场景中,我们分析了二元光栅的偏振依赖性,并对结构进行优化,使其在任意偏振角入射光下均能表现良好。 倾斜光栅的鲁棒性优化 这个用例演示了一个具有稍微变化的填充因子的倾
    发表于 02-19 08:54

    VirtualLab Fusion应用:具有连续调制光栅区域的光波导优化

    此用例的一部分) 足迹和光栅分析工具的应用,包括生成满足参数调制所有要求的光学设置 光栅参数所需调制的定义 选择变量并定义评价函数以优化调制光栅参数。 起点是一个现有的、可执行的光波导系统,其中已经
    发表于 02-07 09:34

    FRED应用:LED发光颜色优化

    ” 色度值优化函数定义 X和y色度坐标优化函数需要彩色图像计算他们的值。输入变量g_ana 是分析面“屏幕”的节点数。这里,只有中心像素点的值用于决定X和y的色度值,只在光束重叠区域
    发表于 01-17 09:39

    FRED应用:LED发光颜色优化

    ” 色度值优化函数定义 X和y色度坐标优化函数需要彩色图像计算他们的值。输入变量g_ana 是分析面“屏幕”的节点数。这里,只有中心像素点的值用于决定X和y的色度值,只在光束重叠区域
    发表于 01-07 08:51

    具有连续调制光栅区域的光波导优化

    程 基本光学光波导设置的配置(不属于此用例的一部分) 足迹和光栅分析工具的应用,包括生成满足参数调制所有要求的光学设置 光栅参数所需调制的定义 选择变量并定义评价函数以优化调制光栅参数。 起点是一个现有
    发表于 12-16 08:56