Skip to content

MIR optimization produces worse code by losing provenance information #146844

@nbdd0121

Description

@nbdd0121

I tried this code:

unsafe extern "C" {
    safe fn foo();
}

pub fn example() {
    let x = 1;
    println!("{x}");
    if x != 1 {
        foo();
    }
}

With -O, the foo() call cannot be optimized away. It can be optimized away however, if I use -Zmir-opt-level=0.

https://godbolt.org/z/c5qE7Tvsf

My hypothesis is that:

  • format_args takes x by reference
  • This x is annotated as noalias when passing to relevant Argument constructors
  • If inlining is done by LLVM, it makes use of this information and correctly deduce that x cannot change during std::io::stdio::_print
  • If inlining is done by Rust at MIR level, this information is lost, and all LLVM sees is that a pointer is put into Argument and this Argument is passed to std::io::stdio::_print, and hence it has to assume conservatively that the value may change.

This was affecting Rust-for-Linux as we have a build_assert! which performs build-time assertions by requiring calls to be optimized away (Rust equivalent of C's BUILD_BUG_ON), and @joelagnel discovered that adding a print can cause such assertion to trip up.

@rustbot label: +A-rust-for-linux +I-slow +I-heavy

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.A-rust-for-linuxRelevant for the Rust-for-Linux projectC-bugCategory: This is a bug.I-heavyIssue: Problems and improvements with respect to binary size of generated code.I-slowIssue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions