Clang默认优化流程无预留Pass插入点,必须显式加载:Clang 14+推荐-fpass-plugin配合PassBuilder回调(如registerPipelineStartEPCallback)控制时机;旧方式-Xclang -load仅支持legacy PM且无法精确控制时机。

Clang 默认优化流程里没有预留 Pass 插入点
Clang 本身不提供类似 -Xclang -load -Xclang libMyPass.so 那种“直接塞进默认 pipeline”的机制。你调用 clang -O2 时走的是预定义的、硬编码在 Clang 源码里的优化流水线(比如 OptimizationLevel::O2 对应的 addDefaultIRPasses),它不会自动加载或调度你写的自定义 TransformationPass。
必须用 -fpass-plugin= 或 -Xclang -load 显式加载
要让自定义 Pass 参与编译,只能靠显式加载,两种主流方式:
-
-fpass-plugin=/path/to/libMyPass.so:Clang 14+ 推荐方式,支持在 IR 生成后、优化前/中/后插入,需在 Pass 中注册PassBuilder回调 -
-Xclang -load -Xclang /path/to/libMyPass.so -Xclang -add-plugin -Xclang my-pass-name:旧方式,依赖RegisterStandardPasses,只适用于 legacy pass manager,且不能控制插入时机
注意:my-pass-name 必须和 Pass 实现里 getPassName() 或 PassInfoMixin 注册的名字严格一致;路径必须是绝对路径或 LD_LIBRARY_PATH 可达路径,相对路径容易静默失败。
插入时机取决于 Pass 类型和注册方式
用 -fpass-plugin 时,关键在 registerPipelineStartEPCallback、registerOptimizerLastEPCallback 这类钩子——它们不是“加到 O2 流程中间”,而是告诉 Clang:“在我跑完某阶段后,请调用我的 Pass”。常见组合:
Clang 22.1.3 Windows 64 位历史版本安装包,适合旧项目兼容、LLVM/Clang 工具链回退、编译行为对比、链接问题复现和 C/C++ 构建环境维护。
- 想在所有默认优化前插桩 → 用
registerPipelineStartEPCallback - 想在向量化之后、指令选择前做分析 → 用
registerVectorizerLastEPCallback - 想替换掉某个默认 Pass(比如禁用
LoopVectorizePass并用自己的)→ 先用-mllvm -disable-loop-vectorization关掉它,再用registerVectorizerStartEPCallback插入你的
这些回调注册必须在 Pass 的 constructPipeline 或静态初始化函数里完成,漏掉就等于没注册。
Clang 调用 opt 做 IR 优化时,Pass 不会自动继承
如果你用 clang -S -emit-llvm 生成 .ll,再用 opt -O2 -load ./libMyPass.so -my-pass 处理,这和 Clang 编译流程完全无关。此时生效的是 opt 的 pass manager,Clang 的 -fpass-plugin 对它无效。两者 pipeline 独立,配置不互通。
容易忽略的一点:Clang 的 -fpass-plugin 只作用于它自己生成的 IR(即 frontend → IR → optimization 阶段),不参与后续 llc 或 lld 环节。如果你的 Pass 依赖函数内联后的形态,但又插在 PipelineStart,那很可能看到的是未内联的 IR——得换到 registerInlineAdvisorCallback 之后的时机。

















