【问题标题】:Rust Range.contains failed to be inlined/optimizedRust Range.contains 未能内联/优化
【发布时间】: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


【解决方案1】:

这确实是一个错失的优化机会,现已在 LLVM 中得到纠正。 https://github.com/rust-lang/rust/issues/90609#issuecomment-1046037263.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    相关资源
    最近更新 更多