3
votes

I bumped into the following observation:

pub fn xx(mut x: Option<usize>) -> usize {
    let y = x.take();
    //print!("{:?}", x);
    if let Some(x) = x {
        x
    } else {
        0
    }
}

This code (with print! being commented out) gets optimized to "nothing":

xorl    %eax, %eax
retq

Once I uncomment the print!, it can no longer optimize out the if let Some(x) = x anymore. I went ahead and expanded the macro (using rustc +nightly --pretty=expanded -Z unstable-options main.rs) and stripped minimized the code down to a minimal compilable example:

#![feature(print_internals)]
#![feature(fmt_internals)]

pub fn xx(mut x: Option<usize>) -> usize {
    let y = x.take();

    std::io::_print(
        ::std::fmt::Arguments::new_v1_formatted(
            &[""],
            &[::std::fmt::ArgumentV1::new(&x, ::std::fmt::Debug::fmt)],
            &[]
        )
    );

    if let Some(x) = x {
        x
    } else {
        0
    }
}

As far as I can see, we only reference x once, and it is a non-mutable reference, so nothing should prevent the optimizer from assuming it is None (since we take() it) and just constantly return 0 as in the first snippet.

Here are the snippets in the Compiler Explorer

1

1 Answers

4
votes

The optimizer is only allowed to make changes to the program that do not change the runtime behavior. By printing the Option, you have changed the runtime behavior and thus the optimizer is now more restricted.

By adding the print statement, you are making the address of the variable visible and important to the code:

&[::std::fmt::ArgumentV1::new(&x, ::std::fmt::Debug::fmt)],
//                            ^^

This means that the optimizer can no longer skip generating a memory location for the value or manipulating the value stored in it. Once you've added all the gunk about dynamic dispatch and IO, one extra if isn't going to add appreciable overhead.


Your real answer is going to be to go read the LLVM source code. Optimizations are non-trivial and they apply and don't apply for esoteric reasons.