MaskRay

3 篇内容

技术文章MaskRay

Estimating branch probabilities

文章深入解析LLVM分支概率信息(BranchProbabilityInfo)在没有PGO(Profile-Guided Optimization)资料时的静态估计机制。作者首先梳理了LLVM估算分支概率的多级回退流程,重点剖析了calcEstimatedHeuristics算法,该算法利用不可达、noreturn、cold等区块的种子权重,通过支配树和后支配树反向传播,并结合循环结构对出口边进行缩放,从而为多后继终结指令分配概率。文中给出了独立的C++实现,并详细讨论了权重标度、边分类、循环嵌套森林的作用,以及不可归约循环对概率计算的影响。此外,还指出了与LLVM源码bit-per-bit匹配所需注意的实现细节,如种子顺序和工作列表顺序。该方法展示了静态分析中如何仅凭控制流图和循环结构生成合理分支猜测,对理解编译器优化有重要参考价值。

本文为编译器开发者、程序分析研究人员或对底层代码优化感兴趣的人员提供了LLVM分支概率静态估计的深入技术剖析,不仅解释了算法原理、设计取舍和工程考量,还附带可复现代码和对比案例。其详细程度足以帮助读者迁移到其他编译系统或静态分析工具的开发中,适合作为长期技术参考资料收录。

技术文章MaskRay

Irreducible loops

文章聚焦于编译器和程序分析中的不可约循环(irreducible loops)问题,首先回顾了支配树和自然循环在可约控制流图上的局限性,指出在优化后的机器码及反编译输出中常见的多入口循环无法被基于支配关系的方法识别。随后详细介绍了韦韬等人在SAS 2007提出的单趟DFS算法,该算法无需支配树或UNION-FIND,通过将遍历中遇到的每条边分为五种情况,并结合“头部链”合并机制,在一次深度优先搜索中同时完成循环识别与头部标记。文章提供了完整的C++实现,并借助不可约核心图和嵌套结构示例验证了算法输出Havlak最细化循环嵌套森林,同时展示了可约情况下与自然循环的一致性。该算法的时间复杂度为O(N+k*E),其中k为衡量非结构化程度的系数,在实际代码中接近线性。文章也指出了算法对DFS顺序的依赖以及不可约循环头的不唯一性。

推荐收录,本文不是简单的算法复述,而是从理论缺陷出发,逐步引出单趟DFS解决方案,并配有清晰图示、完整代码和可运行示例。它对编译器工程、程序分析和反编译领域的读者具有直接的参考意义,能够帮助他们理解如何处理非结构化控制流,并将这套轻量级循环识别方法迁移到自己的静态分析工具中。

工程实践MaskRay

A deep dive into SmallVector::push_back

这篇文章围绕 LLVM SmallVector 的 push_back 热路径优化展开,分析了约 trivially copyable 元素在容量不足时为何会把本应只发生在慢路径的状态保存,意外带到快路径上。作者通过 clang、GCC 和不同库实现的汇编对比指出,fast/slow 合流会迫使 this 和元素值占用被调用者保存寄存器,shrink wrapping 无法消除这些开销。随后提出把 grow-and-store 拆成独立的尾调用慢路径,让快路径只保留一次比较、一次存储和一次递增,从而显著缩短指令序列并减少寄存器压力。文章还验证了 libc++、libstdc++、Boost small_vector 的类似问题,并说明这个改动对二进制体积、编译时指令数和少数内联阈值敏感点的影响。其边界在于慢路径会更慢且 noinline 很关键,但由于扩容本就要搬移元素,额外一次调用的代价通常可接受。

收录依据很明确:文章给出了汇编、shrink-wrap 诊断和编译时统计,证明问题出在快慢路径合流导致的寄存器溢出,而非简单的代码风格差异。适合做 C++ 标准库、LLVM/编译器后端和性能优化的参考,尤其对需要理解尾调用、内联与寄存器分配权衡的读者可迁移价值很高。