Generated assembly code of loops

I stumbled over this blog post about code size in rust.
It says, that a simple for-loop like this

for x in 0..10 {
    // do code
}

generates more assembly code than this loop:

let x = 0;
loop{
    // do code
    x += 1;
    if i == 10 {
        break;
    }
}

Why is that so and is this a bug?

You could write that code and use cargo asm to find out for yourself: https://github.com/gnzlbg/cargo-asm

Is it a bug? Who knows? It's not beyond the bounds of possibility that the version with more asm runs faster. You could check that for yourself with "cargo bench": https://doc.rust-lang.org/cargo/commands/cargo-bench.html

Let us know what you find.

Rust will generally optimize for speed, not for filesize like the article talks about. To optimize for size, you can use the following.

[profile.release]
opt-level = 'z'

You can read more here.

Actually the z-flag has been used.

The naïve version of a for loop over a range needs to include an initial check that the range is empty, and thus that the loop body should not ever be executed (i.e., a Pascal while loop). That requires the naïve generated code to include a conditional forward branch over the loop body as well as an unconditional backward branch at the end of the loop.

The second version is similar to a Pascal until loop, with a termination check only at the end. That requires only a conditional backward branch at the end of the loop.

Of course a decent optimizer will note that the range is constant and non-empty, so generate the identical code for both cases.

This is not a bug, because these two loops do different things (assuming 10 is not constant, but a variable like len).

The loop {} construct always runs at least once, and is not correct if iteration count is 0.

2 Likes

There's also the difference that loop {} together with labeled break and continue can be used as a safe version of GOTO i.e. it can be used to manipulate local control flow. For most cases this usage of loop {} should be discouraged, but recently I can into a case myself where that was the easiest way to solve the problem so I thought I'd at least mention it.

I can't seem to reproduce this (at least for the simple case given in the blog post), you can see here that the assembly generated is identical whether written using for, loop or while.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.