Skip to content

Rust cannot move some of loop invariants out from loop at opt-level=2 #46542

Closed
@upsuper

Description

@upsuper

For example the following test code:

extern "C" {
fn random_bool() -> bool;
fn random_usize() -> usize;
fn output(_: usize);
}

#[no_mangle]
pub fn test() {
    let condition = unsafe { random_bool() };
    let num = unsafe { random_usize() };
    for i in 0..num {
        if !condition {
            break;
        }
        unsafe { output(i) };
    }
}

In assembly generated by rustc, it can be seen that the check of condition is inside the loop, while it should be considered a loop invariant, and be pulled out from the loop.

Note that Clang is able to do this optimization with an equivalent C++ code:

#include <cstddef>

bool random_bool();
size_t random_size();
void output(size_t n);

void test() {
    auto condition = random_bool();
    auto count = random_size();
    for (size_t i = 0; i < count; i++) {
        if (!condition) {
            break;
        }
        output(i);
    }
}

so it seems either this is something should be done in compiler frontend, or we are missing some optimization from LLVM.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-MIRArea: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlC-enhancementCategory: An issue proposing an enhancement or a PR with one.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions