如何利用LLVM test-suite及lit测试自定义LLVM IR优化Pass?
用lit实现自定义LLVM Pass的测试流程
完全可以用lit适配你的测试流程,LLVM官方的Pass测试体系本身就是基于lit+FileCheck搭建的,下面是针对源码外Pass开发场景的具体实现步骤:
一、基础准备
- 确保LLVM工具链(
clang,llvm-link,opt,llc,llvm-lit,FileCheck)已正确安装并能在终端直接调用。 - 你的自定义Pass已编译为动态链接库(比如
libMyPass.so或MyPass.dll)。
二、搭建lit测试环境
1. 目录结构
创建独立的测试目录,示例结构如下:
my_pass_test/ ├── lit.cfg.py # lit核心配置文件 └── test_cases/ # 存放所有测试用例 ├── test1.c └── test2.ll
2. 编写lit.cfg.py配置
这个文件用来告诉lit如何识别测试用例、调用工具链和加载你的自定义Pass:
import lit.formats import os # 测试套件名称 config.name = 'MyCustomPassTests' # 使用Shell命令式的测试格式(适合串联编译/优化流程) config.test_format = lit.formats.ShTest() # 识别的测试用例文件后缀 config.suffixes = ['.c', '.ll'] # 配置LLVM工具路径(如果工具不在系统PATH,需替换为绝对路径) config.clang = os.path.join(config.llvm_tools_dir, 'clang') config.opt = os.path.join(config.llvm_tools_dir, 'opt') config.llvm_link = os.path.join(config.llvm_tools_dir, 'llvm-link') config.llc = os.path.join(config.llvm_tools_dir, 'llc') # 自定义Pass动态库路径(根据你的实际编译路径修改) config.my_pass_lib = os.path.abspath('../build/libMyPass.so') # 定义可复用的参数别名,简化测试用例编写 config.substitutions.append(('%load_pass', f'-load-pass-plugin={config.my_pass_lib}')) config.substitutions.append(('%my_pass', '-passes="my-custom-pass"')) # 替换为你的Pass名称
3. 编写测试用例
测试用例采用ShTest格式,用RUN:指令串联你的测试流程,最后用FileCheck验证执行结果(%t前缀会自动生成临时文件,避免污染目录)。
示例1:基于C源码的测试用例(test1.c)
// RUN: clang -emit-llvm -c %s -o %t1.bc // RUN: llvm-link %t1.bc -o %t_combined.bc # 多个IR文件直接追加即可,比如%t1.bc %t2.bc // RUN: opt %load_pass %my_pass -S %t_combined.bc -o %t_optimized.bc // RUN: llc %t_optimized.bc -o %t_optimized.o // RUN: clang %t_optimized.o -o %t_executable // RUN: %t_executable | FileCheck %s // CHECK: Hello from optimized code! #include <stdio.h> int main() { printf("Hello from optimized code!\n"); return 0; }
示例2:基于LLVM IR的测试用例(test2.ll)
如果已有现成的IR文件,可以跳过C编译步骤:
; RUN: llvm-link %s other_test.bc -o %t_combined.bc ; RUN: opt %load_pass %my_pass -S %t_combined.bc -o %t_optimized.bc ; RUN: llc %t_optimized.bc -o %t_optimized.o ; RUN: clang %t_optimized.o -o %t_executable ; RUN: %t_executable | FileCheck %s ; CHECK: Result: 42 define i32 @main() { entry: ret i32 42 }
三、运行测试
在终端执行以下命令启动测试,-v参数会输出详细执行日志,方便排查问题:
llvm-lit -v my_pass_test/test_cases/
四、额外建议
- 如果你的测试只需要验证IR优化结果(不需要生成可执行文件),可以简化流程:直接用
opt输出优化后的IR,再用FileCheck对比IR内容,这也是LLVM官方Pass测试的常用方式。 - 若想接入LLVM test-suite,需要编写CMakeLists.txt将测试用例注册到LLVM的测试体系中,但源码外开发场景下,独立搭建lit测试环境更灵活,无需修改LLVM源码。
- 可以通过
lit.cfg.py中的config.excludes字段排除不需要执行的文件或目录。
内容的提问来源于stack exchange,提问作者ADNRs
相关产品推荐
相关产品推荐

