如何动态地向Rust编译器发出一个给定变量为非零的信号?

wf82jlnq  于 2022-12-04  发布在  其他
关注(0)|答案(2)|浏览(144)

我想消除对Rust生成的代码的边界检查。我有一些变量很少为零,我的代码路径确保它们不会遇到麻烦。但因为它们可能为零,所以我不能使用NonZeroU64。当我确定它们为非零时,我如何向编译器发出信号呢?
例如,如果我有following function,我知道它将是非零的。我能告诉编译器这一点吗?还是我必须进行不必要的检查?

pub fn f(n:u64) -> u32 {
    n.trailing_zeros()
}

我可以在确定的情况下用NonZeroU64 Package 数字,但这样我就已经产生了支票,这就违背了目的...

2w2cym1i

2w2cym1i1#

通常可以优化单个函数体中的冗余检查。因此,您只需在调用trailing_zeros()之前将数字转换为NonZeroU64,并依靠编译器来优化边界检查。

use std::num::NonZeroU64;

pub fn g(n: NonZeroU64) -> u32 {
    n.trailing_zeros()
}

pub fn other_fun(n: u64) -> u32 {
    if n != 0 {
        println!("Do something with non-zero!");
        let n = NonZeroU64::new(n).unwrap();
        g(n)
    } else {
        42
    }
}

在上面的代码中,if n != 0确保在块中n不能为零,并且编译器足够聪明地删除了unwrap调用,使NonZeroU64::new(n).unwrap()成为一个零成本操作。

oymdgrw7

oymdgrw72#

core::intrinsics::assume
通知优化程序某个条件始终为真。如果条件为假,则未定义行为。
不会为此内在函数生成任何代码,但优化程序将尝试在两次传递之间保留它(及其条件),这可能会干扰周围代码得优化并降低性能.如果优化程序可以自己发现不变变量,或者它不启用任何重要得优化,则不应使用它.
这个内建函数没有稳定的Map。

相关问题