Description
Taken from #534:
// use a mutable reference to prevent the MIR opt from happening
#[no_mangle]
pub fn src(x: &mut &u8) -> impl Sized {
let y = **x;
let mut z = Box::new(0);
// a bunch of code that operates on the `Box`, however,
// nothing else can potentially access the underlying `u8`
// that's behind the double reference besides the `__rust_alloc` call.
// optimizable to `true`?
**x == y
}
Currently, LLVM doesn't do the second optimization. However, it does perform it if you manually set System
to be the global allocator: https://rust.godbolt.org/z/a77PWjeKE 1. This is due to this line, which is used by their GVN pass.
There are clearly special magic rules applying specifically for malloc
that mean that its memory must be truly fresh for the Abstract Machine, and cannot be part of any previously existing stack/heap/other allocation. This is "fine" as long as malloc
is called via FFI and all the state it works in is completely hidden from the current compilation unit. It becomes rather incoherent if there is ever a chance of malloc
itself being inlined into surrounding code, or exchanging data with surrounding code via global state -- so we better have rules in place against things like that. I think we should say that malloc
is reserved to be provided by the underlying runtime system, and it must be called via FFI in a way that no inlining is possible.
Note that this is separate from Rust's #[global_allocator]
attribute, which does not get all the same magic that malloc
gets. See #442 for discussion of the semantics of that attribute.