Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Rust optimize for loops over calculated ranges?

As an exercise I'm trying to micro-optimize code in Rust 1.3.0. I have a loop of a loop over an array. Something like this:

loop {
    for i in 0..arr.len() {
        // something happens here
    }
}

Since arrays are fixed size in Rust, will the compiler optimize the code by evaluating arr.len() just once and reusing the value, or will the expression be evaluated with each pass of the top-level loop? The question can be expanded to more calculation-heavy functions without side-effects, other than arr.len().

In other words, would the above code be equivalent to this:

let arr_len = arr.len();

loop {
    for i in 0..arr_len {
        // something happens here
    }
}
like image 395
Jakub Avatar asked Feb 21 '26 18:02

Jakub


1 Answers

The .. is a range operator, which forms a Range<Idx> object (or a derivative: RangeFrom, RangeFull or RangeTo). Those objects only contain indexes (the Idx type), so you can rest assured that .len() is only evaluated once.


In general, it is a good idea to inspect the LLVM IR. If you have a synthetic example, you can use the playground easily enough. For example:

// 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]); }
    }
}

Yields the following function:

; 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
}

In this case, with a fixed length, there is no loop at all: it has been unrolled.

like image 180
Matthieu M. Avatar answered Feb 23 '26 08:02

Matthieu M.