用途:解释编译器优化标志之外的各阶段,包括中端 IR 优化、寄存器分配、指令选择与调度、向量化边界、PGO 以及链接后 BOLT,衔接 PGO 技能与 LLVM/GCC 内部机制。
适用场景:-O3 未向量化热点循环、讲解寄存器压力为何导致溢出、规划 PGO 或 BOLT 部署、理解 pass 交互(如 LICM 先于向量化)。
工作流:
- 编译器流水线:前端 → LLVM IR / GCC GIMPLE;中端 DCE、GVN、LICM、内联;循环优化展开与向量化;代码生成准备合法化类型;指令选择(DAG → 机器操作);寄存器分配(贪心、线性扫描);窥孔与调度。
- 向量化失败排查:clang -O3 -Rpass=loop-vectorize -Rpass-missed=loop-vectorize foo.c。常见原因与修复:未知迭代次数可剥离循环或断言次数;依赖可重排或分离累加器;循环内函数调用可内联或外提;对齐未知可用 __builtin_assume_aligned。
- 寄存器分配直觉:活跃区间超过物理寄存器时溢出到栈槽,产生昂贵加载/存储;缩短活跃区间(拆分变量、重物化)有帮助。GCC/LLVM 均用图着色变体(LLVM 为 greedy regalloc)。
- PGO 流程(Clang):clang -fprofile-instr-generate -O2 -o app foo.c;./app 训练负载;llvm-profdata merge default.profraw -o default.profdata;clang -fprofile-instr-use=default.profdata -O2 -o app_pgo foo.c。可改善分支布局、内联与向量化阈值。
- BOLT(链接后):llvm-bolt -instrument app -o app.inst;./app.inst;llvm-bolt -data=perf.fdata -reorder-blocks=+ -o app.bolt app。需保留重定位(-Wl,--emit-relocs)。
- LICM 示例:合法时将循环不变量 x * scale 提升出内层循环,减少每次迭代工作量。
- 智能体用法:/compiler-optimizations-deep Why did LLVM fail to vectorize this reduction loop?
常见问题:PGO 无收益多因训练不具代表性,应匹配生产输入;BOLT 崩溃多因二进制被剥离,需保留符号与重定位;汇编出现溢出因寄存器压力,可简化活跃区间;-O3 变慢因代码膨胀/缓存,可试 -O2 或 PGO;GCC/Clang 差异因 pass 顺序不同,可对比 IR 与汇编。
限制:资料未提供具体收费、平台与效果数据。