Alive2: LLVM 编译器优化正确性验证工具
文章目录
编译器会进行很多的代码转换和优化的操作,如何保证这些操作的正确性尤为重要。这时候就需要翻译验证(translation validation) 工具了,本文简单介绍下发现了 LLVM 转换中 10 多个 bug 的 Alive2。
1、Alive2
我们可以看到很多 LLVM 的 .ll 文件里的 LIT 测试套件,这个是用来跑 LLVM 单元/回归测试的测试套件,但这些测试更多是验证结果是否一致。这种测试,对于格式转换、文本处理、语义结构化都很有帮助。不过对于识别 LLVM 转换中的问题还不够。
|
|
Alive2 主要服务于 LLVM,可以发现各种形式的未定义行为(UB、undefined behavior),它检查函数在 LLVM IR(intermediate representation) 上的 refinement 关系。
Alive2 还提供了独立的工具 alive-tv 来判断转换是否正确:https://alive2.llvm.org/ 。
2、refinement
refinement 关系不代表等价,它代表目标函数在所有可能的输入状态下,是否表现为源函数行为的子集。即目标函数的行为,都包含在源函数的行为当中了。
例如,在 C/C++ 中,两个 int 类型变量相加,只要在 -32767..32767 之间就行,当它降级(lower) 到 LLVM IR 时,这个有效值范围被 refine 成 -2147483648..2147483647,然后当 LLVM IR 降级到具体的平台时(ARM 或 x86-64),结果超出范围的加法会从 undefined 被 refine 成 two’s complement wraparound(二进制补码的操作)。这里面的 refinement 都是合法的,但如果反过来转换(递升、raise) 就是不正确的。
3、LLVM UB
LLVM 中主要有这几种 UB:
- Undef。IR 中显式声明的值、未初始化的变量等导致的出现不固定值。
|
|
- Poison。支持特定操作执行的可能 overflow 的指令、违背运算规则的指令等。poison 值不会立即发生 UB,但可能会一直传递。
|
|
- True undefined behavior。比较直接的 UB,如除 0 操作、非法内存访问等。
4、SMT
SMT(Satisfiability Modulo Theories、基于模理论的可满足性),用来判定数学公式是否是可满足的。在 Alive2 中,用来判断 LLVM IR 的转换的合法性。它可以验证 LLVM 中所有过程内的内存优化操作。
Z3 是高性能的 SMT solver 解析器,这里采用的是 BTV(bounded translation validation),即证明对特定的输入程序(特定函数) 的优化是否为正确的(即使是循环,也是有限次数的循环),而非验证所有输入程序的正确性。
这里通过一个案例去说明 SMT 编码,下图为一个函数转换的案例,优化了堆内存分配的操作,直接返回结果:
这里的转换是合法且正确的,因为 LLVM IR 使用的是抽象的虚拟内存模型,不提供直接的内存访问操作,需要通过 load 和 store 去对内存读写。而根据 LLVM IR 的设定,新分配内存都会指向新的内存块。这里 q 指向了新的内存块,而 r 并没有去拿 q 的地址,所以不会有错误优化这种风险。
我们人工可以判断出这是没问题的,那么怎么去自动化验证呢?就需要把这些状态进行编码操作了。
编码会涉及到指针、范围内内存块的数量、别名规则、内存访问等,然后尝试给源函数和目标函数建立 refinement 关系,证明转换是否合法正确。(这部分涉及比较多的数学定义和运算,不做展开,尝试用一张图说明对这个案例的 refinement 判断)
5、扩展
Alive2 也是可以用于其他编译器的转换验证的,不过最近看到一个使用 python z3 库对 GCC 进行验证的案例,可以看下系列文章了解下:GCC Translation Validation。
它会获取 GCC 中的 GIMPLE IR 进行验证 refinement 关系,跟上述证明一样,主要是:
- 对于没有 UB 的所有输入,两个函数的返回值是一致的。
- 目标函数不存在源函数所没有的 UB。
- 对于没有 UB 的输入,全局内存在触发函数之后行为一致。
参考
- AliveToolkit/alive2
- 《LLVM Techniques, Tips, and Best Practices》
- Alive2 Part 1: Introduction
- Alive2 Verifying existing optimizations
- Undefined Behavior in LLVM
- Poison Values
- Two’s complement
- Alive2: Bounded Translation Validation for LLVM
- An SMT Encoding of LLVM’s Memory Model for Bounded Translation Validation
- paper - An SMT Encoding of LLVM’s Memory Model for Bounded Translation Validation
- Satisfiability modulo theories
- GCC Translation Validation
- Z3:考公行测轻松应对,排班问题一键解决的"神器"?
文章作者 calssion
上次更新 2023-07-23