Rust 是否会针对计算范围内的循环进行优化?

Jak*_*kub 3 optimization micro-optimization rust

作为练习,我尝试对 Rust 1.3.0 中的代码进行微优化。我在数组上有一个循环。像这样的东西:

loop {
    for i in 0..arr.len() {
        // something happens here
    }
}
Run Code Online (Sandbox Code Playgroud)

由于 Rust 中的数组大小是固定的,编译器是否会通过arr.len()仅计算一次并重用该值来优化代码,还是会在顶层循环的每次传递中计算表达式?这个问题可以扩展到除了arr.len().

换句话说,上面的代码是否等同于:

let arr_len = arr.len();

loop {
    for i in 0..arr_len {
        // something happens here
    }
}
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 5

..一个范围运算符,它形成一个Range<Idx>对象(或导数:RangeFromRangeFullRangeTo)。这些对象仅包含索引(Idx类型),因此您可以放心,它.len()仅被评估一次。


一般来说,检查 LLVM IR 是个好主意。如果你有一个综合的例子,你可以很容易地使用游乐场。例如:

// A black-box prevents optimization, and its calls are easy to spot.
extern {
    fn doit(i: i32) -> ();
}

fn main() {
    let arr = [1, 2, 3, 4, 5];

    for i in 0..arr.len() {
        unsafe { doit(arr[i]); }
    }
}
Run Code Online (Sandbox Code Playgroud)

产生以下函数:

; Function Attrs: uwtable
define internal void @_ZN4main20hd87dea49c835fe43laaE() unnamed_addr #1 {
entry-block:
  tail call void @doit(i32 1)
  tail call void @doit(i32 2)
  tail call void @doit(i32 3)
  tail call void @doit(i32 4)
  tail call void @doit(i32 5)
  ret void
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,由于长度固定,根本不存在循环:它已展开。