Rust Range.contains方法无法被编译器正确内联优化问题咨询
Rust Clippy范围写法优化遗漏问题解答
核心结论
- 这个问题和借用规则无关:
contains(&value)里的临时不可变引用没有任何别名冲突,rustc完全可以确定value不会被修改,引用会在编译期直接消除,不会影响优化。 - 这是当前
rustc搭配LLVM后端的特定场景优化缺陷:触发条件刚好是你测试的情况:1..=9范围判断后紧跟和范围下界相邻的value == 0判断,两个条件可以合并为value <=9,但当前的优化pass在处理RangeInclusive::contains调用生成的中间IR时,没能正确合并这两个相邻条件,导致生成了冗余的汇编指令。 - 你补充的测试场景已经验证了这个结论:当删除特殊值判断、或是特殊值和范围不相邻时,不存在可以合并的条件,优化pass就能正常处理
contains调用,三个版本生成的汇编完全一致。 - C++侧的表现也符合这个逻辑:Clang后端同样没有覆盖这个特殊场景的合并优化,而GCC的优化pass覆盖了该场景,所以两种写法都能得到最优汇编。
应对方案
- 如果该函数属于性能敏感路径,可以保留手写比较的
version1写法,添加#[allow(clippy::manual_range_contains)]属性规避Clippy的 lint 提醒,同时加注释说明是为了规避当前编译器的优化遗漏。 - 非性能敏感场景直接使用Clippy推荐的
version2写法即可,可读性更高,性能差异可以忽略不计,后续编译器版本修复该优化缺陷后会自动生成最优代码。
附录:相关代码参考
原Clippy推荐前写法
const SPECIAL_VALUE: u8 = 0; // 后续可能会调整 pub fn version1(value: u8) -> bool { (value >= 1 && value <= 9) || value == SPECIAL_VALUE }
Clippy推荐写法
pub fn version2(value: u8) -> bool { (1..=9).contains(&value) || value == SPECIAL_VALUE }
手动内联等价写法
pub fn manually_inlined(value: u8) -> bool { (1 <= value && value <= 9) || value == SPECIAL_VALUE }
内容的提问来源于stack exchange,提问作者senevoldsen
相关产品推荐
相关产品推荐

