rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.61k stars 12.48k forks source link

noalias on a Box doesn't seem to have an impact when compiling without `-C panic=abort` #95323

Open jrmuizel opened 2 years ago

jrmuizel commented 2 years ago

I tried this code:

struct Foo {
    x: i32
}
#[inline(never)]
fn function2() { println!("foo"); }

#[inline(never)]
fn function1() -> Box<Foo> { Box::new(Foo { x: 4}) }

pub fn foo() {
    let foo: Box<_> = function1();
    let value1 = foo.x;
    function2();
    let value2 = foo.x;
    assert_eq!(value1, value2);
}

I expect the assert_eq! to be compiled away. However, this only happens with -C panic=abort.

I'm using rustc 1.61.0-nightly (c84f39e6c 2022-03-20)

RalfJung commented 2 years ago

Possibly related: https://github.com/rust-lang/rust/issues/46515

ldm0 commented 2 years ago

Cannot reproduce with nightly rust: https://godbolt.org/z/M5vvsbGnK

RalfJung commented 2 years ago

Cc @Nilstrieb

nikic commented 2 years ago

This always worked with -C opt-level=3 but failed (and still fails) with -C opt-level=2.

Noratrieb commented 2 years ago

I think LLVM inlined the function anyways and that's why it's not reproducible anymore (even with -Zbox-noalias=no). Interestingly, if the function is made truly opaque my passing a function pointer instead, the assert is not optimized away with -Zbox-noalias=no, but it is optimized away with -Zbox-noalias=yes. So this indeed seems like a case where noalias on box improves codegen.

Edit: It's obviously not inlined for codegen as the assembly shows the call, but there seems to be some smarter analysis going on.

nikic commented 2 years ago

@Nilstrieb Yes, LLVM infers that the return value is noalias in this case (noinline does not affect IPO inference passes).