Jakub
Jakub

Reputation: 822

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

Upvotes: 3

Views: 1173

Answers (2)

Matthieu M.
Matthieu M.

Reputation: 300399

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.

Upvotes: 5

Jerry Coffin
Jerry Coffin

Reputation: 490713

At least in a quick check with using arr.len() nested inside another loop, no code seems to be generated for the "call" to arr.len() at all. In the generated code, the size of the array is simply hard-coded into the output.

In other words, I would not expect your second snippet to execute any faster than the first one.

Upvotes: 3

Related Questions