Misexpect¶
当开发者使用 llvm.expect
内联函数,即通过使用 __builtin_expect(...)
,他们试图向优化器传达他们的代码在运行时的预期行为。然而,这些注释可能由于各种原因而错误:代码库的更改会静默地使它们失效,开发者错误地注释了它们(例如,使用 LIKELY
而不是 UNLIKELY
),或者他们可能在编写注释时错误地假设了一些东西。无论出于何种原因,检测这些情况都是有用的,这样优化器可以对代码做出更有用的决策。
MisExpect 诊断旨在通过将 llvm.expect
内联函数添加的分支权重与通过分析收集的分支权重进行比较,帮助开发者识别和解决这些情况。只要这些值不匹配,就会向用户显示一个诊断信息。有关 LLVM 后端中检查如何运作的详细信息,请参阅 LLVM 的文档。
默认情况下,MisExpect 检查非常严格,因为 llvm.expect
内联函数的使用专为特殊情况设计,在这种情况下,条件的结果严重偏向。因此,优化器可能非常激进,如果结果不如注释建议的那样可预测,可能会导致性能下降。即使注释 90% 的时间都是正确的,也可能有利于删除注释或使用其他内联函数,该内联函数可以更直接地传达概率。
由于这可能过于严格,因此 MisExpect 诊断默认情况下未启用,并支持一个额外的标志来容忍与精确阈值的一些偏差。-fdiagnostic-misexpect-tolerance=N
在比较分支权重时,接受在预期值的 N%
内的偏差。因此,传递 -fdiagnostic-misexpect-tolerance=5
如果来自概要文件的权重在 llvm.expect
内联函数添加的权重的 5% 之内,将不会报告诊断消息。
MisExpect 诊断也以优化备注的形式提供,可以序列化并通过 LLVM 中的 opt-viewer.py
脚本来处理。
- -Rpass=misexpect¶
当分析数据与
llvm.expect
内联函数的使用冲突时,启用 misexpect 优化备注。
- -Wmisexpect¶
当分析数据与
llvm.expect
内联函数的使用冲突时,启用 misexpect 警告。
- -fdiagnostic-misexpect-tolerance=N¶
放松 MisExpect 检查,以容忍分析值在预期分支权重的 N% 之内。例如,
N=5
的值允许 MisExpect 检查0.95 * Threshold
LLVM 支持 4 种类型的概要文件格式:前端、IR、CS-IR 和采样。MisExpect 诊断与所有概要文件格式兼容。
概要文件类型 |
描述 |
---|---|
前端 |
在编译期间由前端添加的概要文件检测,例如 |
IR |
由 LLVM 后端在编译期间添加的概要文件检测 |
CS-IR |
基于上下文敏感 IR 的概要文件 |
采样 |
通过使用外部工具(例如 Linux 上的 |