-
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
Preserve unused pointer to address casts #97597
Conversation
Some changes occured to rustc_codegen_cranelift cc @bjorn3 Some changes occurred in src/tools/clippy. cc @rust-lang/clippy Some changes occured to the CTFE / Miri engine cc @rust-lang/miri |
r? @cjgillot (rust-highfive has picked a reviewer for you, use r? to override) |
b6ddebf
to
63f6324
Compare
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html> | ||
Rvalue::Cast(CastKind::PointerAddress, _, _) => true, | ||
|
||
Rvalue::Use(_) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use
can potentially mutate memory if it uses an Operand::Move
(which is proposed to de-initialize the memory it reads from).
Removing a Move
with unused result is still okay (the optimized program simply has more defined memory than the unoptimized program), but e.g. reordering it with other reads/writes is not if they might overlap. So depending on what the caller cares about, Move
needs to be considered effectful.
compiler/rustc_middle/src/mir/mod.rs
Outdated
#[inline] | ||
pub fn is_pointer_int_cast(&self) -> bool { | ||
matches!(self, Rvalue::Cast(CastKind::PointerAddress, _, _)) | ||
pub fn may_have_side_effects(&self) -> bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please define precisely which side-effects this is talking about. Rust code has a lot of possible effects that can prevent reordering and/or treating code as 'dead' and removing it:
- Mutating memory (or other machine state)
- Reading from memory (or other mutable machine state)
- panicking
- looping forever
- causing UB
- making a non-deterministic choice
The easiest to define condition is whether code is entirely "pure", which means it does none of these things. Pure stuff can be reordered arbitrarily, hoisted out of conditionals/loops, removed if the result is unused -- all the good stuff. But then we have to exclude many operation (including e.g. division). The second easiest is "pure or UB", but that already lets you do fewer optimizations.
compiler/rustc_middle/src/mir/mod.rs
Outdated
| Rvalue::ThreadLocalRef(_) | ||
| Rvalue::AddressOf(_, _) | ||
| Rvalue::Len(_) | ||
| Rvalue::Cast(CastKind::Misc | CastKind::Pointer(_), _, _) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Int-to-ptr casts should be considered as making a non-deterministic choice (angelically) and reading mutable machine state (namely the set of exposed provenances), which can prevent them from being reordered with other operations.
Though I assume reads from mutable machine state are fine here since otherwise Use
would also be out entirely. So my guess is the property you care about here is "can this rvalue be removed if we don't care about the result of the computation"? That would be "no mutating, no panicking, no looping forever" (and also "no angelic choice unless we can prove there exists a possible choice", but the angelic choice in int-to-ptr casts always has a trivially possible choice if the created pointer is unused so that is fine).
63f6324
to
62f9c2d
Compare
Thanks, LGTM. :) (But I can't tell if the use sites make sense since I am not familiar with those MIR transformations.) |
☔ The latest upstream changes (presumably #97632) made this pull request unmergeable. Please resolve the merge conflicts. |
62f9c2d
to
d140d05
Compare
r? @RalfJung |
I'm happy with the 'general' part of this PR, but cannot say if the specific changes in 3 optimizations/analyses are correct, or if they need a different notion of 'no side-effect'. The changes in liveness and DSE are obviously not changing behavior (so at least I am sure they are not making anything less correct than it was before), but I have no idea what the |
Fwiw lgtm too, but no r+ so will still need someone else to review |
Thanks for review @RalfJung, @JakobDegen. @bors r=RalfJung,JakobDegen |
📌 Commit d140d05 has been approved by |
…s, r=RalfJung,JakobDegen Preserve unused pointer to address casts Fixes rust-lang#97421. cc `@RalfJung`
d140d05
to
6277c3a
Compare
Rebased and updated match pattern to cover recently added cast kind. @bors r=RalfJung,JakobDegen |
📌 Commit 6277c3a has been approved by |
Rollup of 5 pull requests Successful merges: - rust-lang#97595 (Remove unwrap from get_vtable) - rust-lang#97597 (Preserve unused pointer to address casts) - rust-lang#97819 (Recover `import` instead of `use` in item) - rust-lang#97823 (Recover missing comma after match arm) - rust-lang#97851 (Use repr(C) when depending on struct layout in ptr tests) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
Fixes #97421.
cc @RalfJung