使用 llvm 和本地值编号算法擦除冗余表达式
Erasing redundant expression with llvm and local value numbering algorithm
所以我的C代码是:
#include <stdio.h>
void main(){
int a, b,c, d;
b = 18, c = 112;
b = a - d;
d = a - d;
}
其部分 IR 是:
%5 = load i32, i32* %1, align 4
%6 = load i32, i32* %4, align 4
%7 = sub nsw i32 %5, %6
store i32 %7, i32* %2, align 4
%8 = load i32, i32* %1, align 4
%9 = load i32, i32* %4, align 4
%10 = sub nsw i32 %8, %9
store i32 %10, i32* %4, align 4
我已经实现了 LVN 算法来检测冗余表达式,即 d = a - d。现在为了优化,我需要操作指令并使其 d = b。我不确定如何使用 llvm 进行操作以及如何操作 IR。
我是llvm的新手,所以这可能是一个愚蠢的问题,但我真的很困惑。由于 llvm 在 IR 上工作,我知道当它看到"d = a - d"时,它将首先加载 a 和 d,但需要更改 IR 中的二进制操作和存储指令,以便 %4 从 %2 获取值。谁能帮我检查我是否正确理解了这一点,以及如何操纵 IR 来优化代码。
首先,让我们用一个不调用未定义行为(由于访问未初始化的变量)的程序替换您的示例程序,以便 UB 不会混淆问题:
void f(int a, int b, int c, int d){
b = a - d;
d = a - d;
// Code that uses b and d
}
(我还删除了这两个作业,因为它们没有任何影响,无论如何mem2reg
后都会消失。
现在实际回答您的问题:大多数优化在mem2reg
传递之后运行,这会在可能的情况下将内存访问转换为寄存器。这很重要,因为与内存位置不同,LLVM 寄存器只能从源中的单个点分配,因此mem2reg
将代码转换为 SSA 形式,这是许多优化工作所必需的。
如果我们将mem2reg
应用于示例代码,我们将得到:
define void @f(i32, i32, i32, i32) #0 {
%5 = sub nsw i32 %0, %3
%6 = sub nsw i32 %0, %3
; Code that uses b and d
}
所以现在我们应用您的分析来发现%6
等同于%5
。有了这些信息,我们可以删除%6
的定义,并将所有出现的%6
替换为%5
(请注意,如果%5
和%6
位于不同的基本块中,其中一个不支配另一个,这将更加复杂)。为此,您可以使用uses()
方法找到%6
的所有用法,该方法告诉您哪些指令%6
为哪个操作数。然后,您可以将该操作数设置为对%5
的引用。
相关文章:
- 引用一个已擦除类型(void*)的指针
- 擦除while循环中迭代的元素
- 在运行时处理类型擦除的数据-如何不重新发明轮子
- C++擦除(如果存在)
- 在映射擦除c++期间执行循环的次数
- 为什么擦除方法会影响结束方法
- C++ 字符串类擦除成员函数的时空复杂性
- 类型擦除的std::function与虚拟函数调用的开销
- C++14 中unordered_map矢量和擦除删除成语的奇怪行为
- C++ 擦除函数中需要澄清
- 循环挂起迭代的 std::擦除 on std::list
- 擦除许多矢量元素,同时使用'auto'
- 如何擦除冗余输入?
- C++ STL 设置按值擦除
- 如何在C++中允许成员函数的自定义返回类型进行类型擦除?
- 为什么我的向量::擦除调用会抛出"vector subscript out of range"?
- 使用 llvm 和本地值编号算法擦除冗余表达式
- 如何使用STL算法和函数按值擦除std::映射单元格
- 在std::multiset中,如果找到一个元素,有一个函数或算法可以只擦除一个样本(单播或重复)
- 用算法擦除向量中的特定元素