【发布时间】:2021-11-04 19:29:10
【问题描述】:
我通过 Clippy 运行我的代码,它建议更改以下内容:
const SPECIAL_VALUE: u8 = 0; // May change eventually.
pub fn version1(value: u8) -> bool {
(value >= 1 && value <= 9) || value == SPECIAL_VALUE
}
进入
pub fn version2(value: u8) -> bool {
(1..=9).contains(&value) || value == SPECIAL_VALUE
}
因为它更具可读性。不幸的是,即使优化级别为 3,生成的程序集输出的长度也是两倍。手动内联它(向下嵌套 2 次),提供与 version1 几乎相同的代码,并且同样高效。
pub fn manually_inlined(value: u8) -> bool {
(1 <= value && value <= 9) || value == SPECIAL_VALUE
}
如果我删除|| value == SPECIAL_VALUE,它们都会以相同的方式解析(尽管在比较之前添加了另外 1 条指令来减少参数值)。此外,如果我将SPECIAL_VALUE 更改为不与范围相邻的内容,它们都会解析为与version2 相同的汇编代码,这就是我保留0 的原因,除非我最终必须更改它。
我有一个到 Godbolt 的链接,这里有代码:https://rust.godbolt.org/z/bMYzfcYob
为什么编译器无法正确内联/优化version2?这是一个“优化错误”吗?还是我误解了 Rust 的某些语义,也许借用的东西阻止了优化,但是编译器不能假设由于别名和引用规则而没有值的突变?
尝试在 C++ 建议中做同样的事情,在这两种情况下都会产生更糟糕的选择 (https://godbolt.org/z/zahfz65W3)
编辑:将我的 C++ 版本的编译器更改为 GCC 使其在两种情况下都得到优化。
【问题讨论】:
-
一般来说,不能保证会发生特定的优化,但这种情况确实感觉很奇怪。如果你在这里没有得到很好的回复,我建议在 Rust 用户论坛上提问或在 GitHub 上提交问题 - 特别是因为这是 clippy 建议的更改。
-
我现在已经在 Rust 问题跟踪器上询问过了。如果我得到答案,如果回答者不这样做,我会在这里重复。
标签: optimization rust inlining rust-clippy