-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Branch elimination not performed on dead store / failure to introduce a spurious store #114886
Comments
Sweet! cc @RalfJung I assume you've already thought about this case, but I noticed that the PR says tree borrows won't allow this optimization which is a bit of a bummer. |
That's far from clear. Allowing the compiler to introduce such stores has major negative consequences and makes tons of code UB. For instance: let mut array = [0, 0];
std::ptr::copy(array.as_ptr(), array.as_mut_ptr().add(1), 1); Note that We really don't want that code to be UB, so I think we have to disallow spurious stores. |
Ok, the number of issues does seem unpleasant. Do we know what the performance loss is? And is there any way to get it back? I.e. maybe enable stacked borrows locally for some function (with the safety assumption that all code executed within the enabled context must adhere to stacked borrows). Though this specific issue's optimization is a spurious store which writes the same value that's already there. I agree that the general case where you can write whatever and then undo it as long as that's not visible won't work, but why can't we allow writing the same value as before. Granted, that class of optimizations probably isn't that useful. |
In the AM, i.e. in MIR, and even in LLVM IR, this does not just store the value that's already there: if the memory is partially uninit/poison, then the "plus 0" leads to UB (in MIR) or to a fully poison value (on LLVM).
I didn't try to define an aliasing model where storing the value that is already there does not count as mutation for shared references. The aliasing model is much easier to reason about when values don't matter. Also LLVM noalias does not let us ignore the values.
|
I tried this code:
I expected to see this happen:
Instead, this happened:
The missed branch is going to be much more expansive than throwing something in a store buffer. Maybe you could argue the compiler thinks n=0 is going to be common, but I find that unlikely.
I'm pretty sure Rust's ownership system allows inserting stores that didn't exist because an
&mut
can't be used on another thread.The text was updated successfully, but these errors were encountered: