用途
本技能引导使用者以“用户”身份操作 LLVM:生成和检查 IR、用 opt 运行已有的优化 pass、用 llc 将 IR 降级为汇编,以及诊断未发生的优化。若目标是编写新的 LLVM pass(PassPlugin、llvm-lit 测试),应改用 skills/compiler-internals/llvm-passes。
触发场景
- “显示这个函数的 LLVM IR”
- “如何运行 LLVM 优化 pass?”
- “这条 LLVM IR 指令是什么意思?”
- “如何编写自定义 LLVM pass?”
- “为什么 LLVM 没有进行自动向量化?”
使用方式
1. 生成 LLVM IR
# 输出文本 IR(.ll)
clang -O0 -emit-llvm -S src.c -o src.ll
# 输出 bitcode(.bc)
clang -O2 -emit-llvm -c src.c -o src.bc
# 将 bitcode 反汇编为文本
llvm-dis src.bc -o src.ll
2. 用 opt 运行优化 pass
# 应用指定 pass
opt -passes='mem2reg,instcombine,simplifycfg' src.ll -S -o out.ll
# 标准优化流水线
opt -passes='default<O2>' src.ll -S -o out.ll
opt -passes='default<O3>' src.ll -S -o out.ll
# 列出可用 pass
opt --print-passes 2>&1 | less
# 打印某 pass 前后的 IR
opt -passes='instcombine' --print-before=instcombine --print-after=instcombine src.ll -S -o out.ll 2>&1 | less
3. 用 llc 将 IR 降级为汇编
# 编译 IR 为目标文件
llc -filetype=obj src.ll -o src.o
# 编译为汇编
llc -filetype=asm -masm-syntax=intel src.ll -o src.s
# 指定目标 CPU
llc -mcpu=skylake -mattr=+avx2 src.ll -o src.s
# 显示可用目标
llc --version
4. 检查 IR
需要理解的关键 IR 构造:
| 构造 | 含义 |
|---|---|
| alloca | 栈分配(SSA 之前;mem2reg 会提升为寄存器) |
| load/store | 内存访问 |
| getelementptr (GEP) | 指针运算 / 字段访问 |
| phi | SSA φ 节点:合并前驱基本块的值 |
| call/invoke | 函数调用(invoke 带异常边) |
| icmp/fcmp | 整数 / 浮点比较 |
| br | 分支(条件或无条件) |
| ret | 返回 |
| bitcast | 重新解释位(代码生成中为空操作) |
| ptrtoint/inttoptr | 指针与整数互转(尽量避免) |
5. 关键 pass
| Pass | 作用 |
|---|---|
| mem2reg | 将 alloca 提升为 SSA 寄存器 |
| instcombine | 指令合并 / 窥孔优化 |
| simplifycfg | CFG 清理、删除死块 |
| loop-vectorize | 自动向量化 |
| slp-vectorize | 超字级并行(直线代码向量化) |
| inline | 函数内联 |
| gvn | 全局值编号(公共子表达式消除) |
| licm | 循环不变量外提 |
| loop-unroll | 循环展开 |
| argpromotion | 将指针参数提升为值 |
| sroa | 聚合体的标量替换 |
6. 调试未发生的优化
# 为什么循环没有被向量化?
clang -O2 -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize src.c
# 输出 pass 流水线
clang -O2 -mllvm -debug-pass=Structure src.c -o /dev/null 2>&1 | less
# 打印每个 pass 之后的 IR(非常冗长)
opt -passes='default<O2>' -print-after-all src.ll -S 2>&1 | less
7. 常用 LLVM 工具
| 工具 | 用途 |
|---|---|
| llvm-dis | bitcode → 文本 IR |
| llvm-as | 文本 IR → bitcode |
| llvm-link | 链接多个 bitcode 文件 |
| llvm-lto | 独立 LTO |
| llvm-nm | bitcode/目标文件中的符号 |
| llvm-objdump | 反汇编目标文件 |
| llvm-profdata | 合并 / 显示 PGO 剖面 |
| llvm-cov | 覆盖率报告 |
| llvm-mca | 机器码分析器(吞吐 / 延迟) |
binutils 对应工具参见 skills/binaries/binutils。
相关技能
- 编写和测试自定义 LLVM pass:skills/compiler-internals/llvm-passes
- 从 AST 生成 LLVM IR:skills/compiler-internals/compiler-frontend
- LLVM IR 的 ORC JIT 执行:skills/compiler-internals/jit-compilation
- 源码级 Clang 标志:skills/compilers/clang
- 链接期 LTO:skills/binaries/linkers-lto
- 结合 llvm-mca 进行微架构分析:skills/profilers/linux-perf
限制
本技能聚焦于以用户身份使用 LLVM 工具链,不涵盖编写新 pass 的完整流程(应使用 llvm-passes 技能)。资料未提供安装方式、版本要求、平台支持范围及收费信息。