用途:帮助代理读懂 LLVM IR(SSA 形式、类型、终止指令),理解标准优化 Pass 流水线,并使用 opt/llvm-dis 做检查;与工具链类和编写插件类技能互补。
适用场景:分析 -O2 对生成 IR 的影响;在 Clang 版本间排查错误编译;为编写自定义 Pass 做准备;在不写 C++ Pass 的前提下讲解 SSA 与支配关系。
主要用法:
- IR 结构:函数以 SSA 形式呈现,包含基本块、合并处的 PHI 节点,以及带类型的值(i32、ptr、向量)。
- 从 Clang 生成 IR: clang -S -emit-llvm -O0 -o foo.ll foo.c clang -c -emit-llvm -O2 -o foo.bc foo.c llvm-dis foo.bc -o foo.ll
- 标准优化流水线(New PM):Clang -O2 大致经过 SimplifyCFG → InstCombine → GVN → LICM → LoopVectorize 等;可用 opt -passes='default<O2>' -S foo.ll -o foo-opt.ll opt -passes='default<O2>' -print-passes foo.ll 2>&1 | head 查看。
- 分析类 Pass:print<domtree> 显示支配树,print<loops> 显示循环嵌套,print-alias-sets 显示别名集;例如 opt -passes='print<domtree>' -disable-output foo.ll
- PHI 与 UB:PHI 形如 %v = phi i32 [ %a, %then ], [ %b, %else ];IR 中的 undef 与 poison 建模 LLVM poison 语义,与 C 的 UB 相关但不同。
- 前后对比: opt -passes='instcombine,simplifycfg' -S foo.ll -o - | diff -u foo.ll -
- 代理用法示例:/llvm-ir-and-passes Explain this PHI node and which pass likely created it
常见问题:Pass 未找到多为版本重命名,可用 opt --print-passes 核对;IR 不匹配多为 LLVM 主版本不同,需对齐 clang/opt 版本;optnone 会阻止优化,来自 -O0 属性;IR 过大常因头文件内联,可关闭 -fno-discard-value-names 并过滤函数;流水线错误常因旧版与 NPM 混用,应使用 -passes= 语法。
限制:需具备相应 LLVM 版本与工具链;具体 Pass 名称和顺序随版本变化,以上为资料给出的示例而非固定保证;未提供收费、平台、价格等信息。