Почему компилятор Rust не может оптимизировать Option :: take и "if let", если вы выводите значение? - PullRequest
0 голосов
/ 01 июля 2018

Я наткнулся на следующее наблюдение:

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

Этот код (с print! закомментированным) оптимизируется до "ничего":

xorl    %eax, %eax
retq

Как только я раскомментирую print!, он больше не сможет оптимизировать if let Some(x) = x. Я расширил макрос (используя rustc +nightly --pretty=expanded -Z unstable-options main.rs) и сократил код до минимально скомпилированного примера:

#![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
    }
}

Насколько я вижу, мы ссылаемся на x только один раз, и это не изменяемая ссылка, поэтому ничто не должно помешать оптимизатору предположить, что это None (так как мы take() это) и просто постоянно возвращайте 0 как в первом фрагменте.

Вот фрагменты в компиляторе

1 Ответ

0 голосов
/ 01 июля 2018

Оптимизатору разрешено только вносить изменения в программу, которые не изменяют поведение во время выполнения. Распечатав Option, , вы изменили поведение во время выполнения и, таким образом, оптимизатор теперь более ограничен.

Добавляя оператор печати, вы делаете адрес переменной видимым и важным для кода:

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

Это означает, что оптимизатор больше не может пропускать создание области памяти для значения или манипулировать значением, хранящимся в нем. После того, как вы добавили весь ганк о динамической диспетчеризации и вводе-выводе, один дополнительный if не добавит значительных накладных расходов.


Ваш реальный ответ будет идти читать исходный код LLVM. Оптимизации нетривиальны, они применяются и не применяются по эзотерическим причинам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...