-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Add new MIR constant propagation based on dataflow analysis #101168
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @compiler-errors (or someone else) soon. Please see the contribution instructions for more information. |
@rustbot label +A-mir-opt |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
648fc1a
to
77d6fad
Compare
This comment has been minimized.
This comment has been minimized.
r? @oli-obk since you know about const prop |
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.
Thank you for doing this! This is impressive work, and looks to be exactly the direction that I think we should be going. For now, I've only focused on correctness in the review. Once we're confident with that, we can work on everything else.
Besides the one bug I pointed out below, there is a part of the logic here that I am very suspicious of: The place expressions that are tracked might in general be overlapping each other. This can happen either in two cases:
-
Enums. Assuming that the layouts work out, the below MIR is DB and would be miscompiled by this pass, if I am reading the code correctly:
(_2 as Foo).0 = 5; (_2 as Bar).0 = 5; _0 = (_2 as Foo).0; return
It is not possible to generate this kind of MIR from Rust (I am working on something to be able to write it in tests at least), but it is nonetheless a part of the semantics of MIR.
-
Pointer aliasing. This is the complicated one. The place values that we care about might in general be aliased by pointers, and we also const prop through pointers in the logic here. There is a lot of subtlety to this. For example, this code is "miscompiled:"
#[inline(never)] fn foo() -> usize { let mut x = 0; let p = core::ptr::addr_of_mut!(x); x = 1; unsafe { *p = 2 }; x } fn main() { dbg!(foo()); }
Miri does indeed report UB for this. Putting aside for a minute the issue of whether or not we're ok miscompiling this, there needs to be a comment in the code somewhere that states what assumptions we are making about the aliasing model that are broken by the above code.
Speaking somewhat more generally, the code that is currently responsible for handling writes needs to explain why its behavior is correct not just for the "obvious" target but for all other possibly overlapping places.
This is unexpected, but I guess it can make sense to allow such writes to inactive variants. If we don't want to deal with layouts, we could flood all other variants with
The analysis relies on some properties of Stacked Borrows. I agree that the assumptions should be clearly documented. I'm also not quite convinced yet that the way that taking a mutable reference/pointer is handled is sound (it just floods the place with |
src/test/mir-opt/dataflow-const-prop/cell.main.DataflowConstProp.diff
Outdated
Show resolved
Hide resolved
src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff
Outdated
Show resolved
Hide resolved
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.
Is if x { y = 42; }
handled to not expose the 42
after the if
block is left, by relying on the regular dataflow lattice merger erasing such information?
This is absolutely awesome. I would propose leaving anything that current const prop does not support (mut refs, dead branch handling, ...) to future PRs. Basically only add "new features" where it falls out of the current work anyway. Do you know of anything that old const prop supports that the dataflow const propagator does not yet support? |
Yes, exactly! Let's use the visualization provided by the dataflow analysis framework and the fn foo(x: bool, mut y: i32) -> i32 {
if x {
y = 42;
}
y
} |
Thank you for the kind words! :)
I agree. Unless there are low-hanging fruits (proper dead branch handling might be easy, I might want to take a look at that).
I did not really investigate that yet. However, there is algebraic simplification, also mentioned here, which is not currently done by this analysis. Although this should be an easy addition if we want it. |
There are currently many open questions. However, I feel like if this approach turns out to be unsound, it most likely is due to the handling of references and aliasing (this was also brought up by @JakobDegen here). I am not aware of any formal proofs for other MIR optimizations (if you are, please let me know, it might help!), but then again, their correctness is perhaps a little bit more intuitive. Also, an actual formal proof might be infeasible. However, I think with some theory from Abstract Interpretation, we might at least put this analysis on solid ground. With this commit, I began a semi-formal argument for why this analysis is sound. There is still a lot to cover there, but the current summary is basically: Whenever mutable access to a tracked place escapes the analysis, the tracked place must be assigned to top and stay that way for the duration of possible access. Since something like |
I resolved the issue with the overlapping storage of enum variants by rejecting the registration of places that contain downcast projections. This is of course not an optimal solution and could be improved in the future. |
This comment has been minimized.
This comment has been minimized.
I'll review this again hopefully tonight, otherwise over the weekend.
I just want to clarify quickly though that I did not mean to imply that I wanted to see a full proof of soundness for the optimization. You are right that those don't exist right now (as far as I know anyway). I mostly just want to move us to a point where we are reasonable comfortable saying that if someone were to try and write such a proof, they would not hit any huge surprises of the form "it turns out this optimization depends on a whole bunch of assumptions that are not mentioned anywhere." |
Adding the ability to track unreachability was not too hard (resolves #81605). fn f() -> usize {
1 + if true { 1 } else { 2 }
} |
☔ The latest upstream changes (presumably #101318) made this pull request unmergeable. Please resolve the merge conflicts. |
ce0c101
to
b4b1347
Compare
⌛ Testing commit 24d2e90 with merge c87998c5e3348d870792b272b21f3cf827ab3cd9... |
The job Click to see the possible cause of the failure (guessed by this bot)
|
💔 Test failed - checks-actions |
Same failure as here: #104399 (comment) |
☀️ Test successful - checks-actions |
Finished benchmarking commit (357f660): comparison URL. Overall result: ❌ regressions - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesThis benchmark run did not return any relevant results for this metric. |
Add new MIR constant propagation based on dataflow analysis The current constant propagation in `rustc_mir_transform/src/const_prop.rs` fails to handle many cases that would be expected from a constant propagation optimization. For example: ```rust let x = if true { 0 } else { 0 }; ``` This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations. Closes #80038. Closes #81605. ## Todo ### Essential - [x] [Writes to inactive enum variants](rust-lang/rust#101168 (review)). Resolved by rejecting the registration of places with downcast projections for now. Could be improved by flooding other variants if mutable access to a variant is observed. - [X] Handle [`StatementKind::CopyNonOverlapping`](rust-lang/rust#101168 (comment)). Resolved by flooding the destination. - [x] Handle `UnsafeCell` / `!Freeze` correctly. - [X] Overflow propagation of `CheckedBinaryOp`: Decided to not propagate if overflow flag is `true` (`false` will still be propagated) - [x] More documentation in general. - [x] Arguments for correctness, documentation of necessary assumptions. - [x] Better performance, or alternatively, require `-Zmir-opt-level=3` for now. ### Extra - [x] Add explicit unreachability, i.e. upgrading the lattice from $\mathbb{P} \to \mathbb{V}$ to $\set{\bot} \cup (\mathbb{P} \to \mathbb{V})$. - [x] Use storage statements to improve precision. - [ ] Consider opening issue for duplicate diagnostics: rust-lang/rust#101168 (comment) - [ ] Flood moved-from places with $\bot$ (requires some changes for places with tracked projections). - [ ] Add downcast projections back in. - [ ] [Algebraic simplifications](rust-lang/rust#101168 (comment)) (possibly with a shared API; done by old const prop). - [ ] Propagation through slices / arrays. - [ ] Find other optimizations that are done by old `const_prop.rs`, but not by this one.
Pkgsrc changes: * Adjust patches and cargo checksums to new versions, but also one strange "mips" conditional. Upstream changes: Version 1.67.0 (2023-01-26) ========================== Language -------- - [Make `Sized` predicates coinductive, allowing cycles.] (rust-lang/rust#100386) - [`#[must_use]` annotations on `async fn` also affect the `Future::Output`.] (rust-lang/rust#100633) - [Elaborate supertrait obligations when deducing closure signatures.] (rust-lang/rust#101834) - [Invalid literals are no longer an error under `cfg(FALSE)`.] (rust-lang/rust#102944) - [Unreserve braced enum variants in value namespace.] (rust-lang/rust#103578) Compiler -------- - [Enable varargs support for calling conventions other than `C` or `cdecl`.] (rust-lang/rust#97971) - [Add new MIR constant propagation based on dataflow analysis.] (rust-lang/rust#101168) - [Optimize field ordering by grouping m\*2^n-sized fields with equivalently aligned ones.] (rust-lang/rust#102750) - [Stabilize native library modifier `verbatim`.] (rust-lang/rust#104360) Added and removed targets: - [Add a tier 3 target for PowerPC on AIX] (rust-lang/rust#102293), `powerpc64-ibm-aix`. - [Add a tier 3 target for the Sony PlayStation 1] (rust-lang/rust#102689), `mipsel-sony-psx`. - [Add tier 3 `no_std` targets for the QNX Neutrino RTOS] (rust-lang/rust#102701), `aarch64-unknown-nto-qnx710` and `x86_64-pc-nto-qnx710`. - [Remove tier 3 `linuxkernel` targets] (rust-lang/rust#104015) (not used by the actual kernel). Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Merge `crossbeam-channel` into `std::sync::mpsc`.] (rust-lang/rust#93563) - [Fix inconsistent rounding of 0.5 when formatted to 0 decimal places.] (rust-lang/rust#102935) - [Derive `Eq` and `Hash` for `ControlFlow`.] (rust-lang/rust#103084) - [Don't build `compiler_builtins` with `-C panic=abort`.] (rust-lang/rust#103786) Stabilized APIs --------------- - [`{integer}::checked_ilog`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog) - [`{integer}::checked_ilog2`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog2) - [`{integer}::checked_ilog10`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog10) - [`{integer}::ilog`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog) - [`{integer}::ilog2`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog2) - [`{integer}::ilog10`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog10) - [`NonZeroU*::ilog2`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#method.ilog2) - [`NonZeroU*::ilog10`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#method.ilog10) - [`NonZero*::BITS`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#associatedconstant.BITS) These APIs are now stable in const contexts: - [`char::from_u32`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.from_u32) - [`char::from_digit`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.from_digit) - [`char::to_digit`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.to_digit) - [`core::char::from_u32`] (https://doc.rust-lang.org/stable/core/char/fn.from_u32.html) - [`core::char::from_digit`] (https://doc.rust-lang.org/stable/core/char/fn.from_digit.html) Compatibility Notes ------------------- - [The layout of `repr(Rust)` types now groups m\*2^n-sized fields with equivalently aligned ones.] (rust-lang/rust#102750) This is intended to be an optimization, but it is also known to increase type sizes in a few cases for the placement of enum tags. As a reminder, the layout of `repr(Rust)` types is an implementation detail, subject to change. - [0.5 now rounds to 0 when formatted to 0 decimal places.] (rust-lang/rust#102935) This makes it consistent with the rest of floating point formatting that rounds ties toward even digits. - [Chains of `&&` and `||` will now drop temporaries from their sub-expressions in evaluation order, left-to-right.] (rust-lang/rust#103293) Previously, it was "twisted" such that the _first_ expression dropped its temporaries _last_, after all of the other expressions dropped in order. - [Underscore suffixes on string literals are now a hard error.] (rust-lang/rust#103914) This has been a future-compatibility warning since 1.20.0. - [Stop passing `-export-dynamic` to `wasm-ld`.] (rust-lang/rust#105405) - [`main` is now mangled as `__main_void` on `wasm32-wasi`.] (rust-lang/rust#105468) - [Cargo now emits an error if there are multiple registries in the configuration with the same index URL.] (rust-lang/cargo#10592) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Rewrite LLVM's archive writer in Rust.] (rust-lang/rust#97485)
Pkgsrc changes: * Adjust patches (add & remove) and cargo checksums to new versions. * It's conceivable that the workaround for LLVM based NetBSD works even less in this version (ref. PKGSRC_HAVE_LIBCPP not having a corresponding patch anymore). Upstream changes: Version 1.68.2 (2023-03-28) =========================== - [Update the GitHub RSA host key bundled within Cargo] (rust-lang/cargo#11883). The key was [rotated by GitHub] (https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/) on 2023-03-24 after the old one leaked. - [Mark the old GitHub RSA host key as revoked] (rust-lang/cargo#11889). This will prevent Cargo from accepting the leaked key even when trusted by the system. - [Add support for `@revoked` and a better error message for `@cert-authority` in Cargo's SSH host key verification] (rust-lang/cargo#11635) Version 1.68.1 (2023-03-23) =========================== - [Fix miscompilation in produced Windows MSVC artifacts] (rust-lang/rust#109094) This was introduced by enabling ThinLTO for the distributed rustc which led to miscompilations in the resulting binary. Currently this is believed to be limited to the -Zdylib-lto flag used for rustc compilation, rather than a general bug in ThinLTO, so only rustc artifacts should be affected. - [Fix --enable-local-rust builds] (rust-lang/rust#109111) - [Treat `$prefix-clang` as `clang` in linker detection code] (rust-lang/rust#109156) - [Fix panic in compiler code] (rust-lang/rust#108162) Version 1.68.0 (2023-03-09) =========================== Language -------- - [Stabilize default_alloc_error_handler] (rust-lang/rust#102318) This allows usage of `alloc` on stable without requiring the definition of a handler for allocation failure. Defining custom handlers is still unstable. - [Stabilize `efiapi` calling convention.] (rust-lang/rust#105795) - [Remove implicit promotion for types with drop glue] (rust-lang/rust#105085) Compiler -------- - [Change `bindings_with_variant_name` to deny-by-default] (rust-lang/rust#104154) - [Allow .. to be parsed as let initializer] (rust-lang/rust#105701) - [Add `armv7-sony-vita-newlibeabihf` as a tier 3 target] (rust-lang/rust#105712) - [Always check alignment during compile-time const evaluation] (rust-lang/rust#104616) - [Disable "split dwarf inlining" by default.] (rust-lang/rust#106709) - [Add vendor to Fuchsia's target triple] (rust-lang/rust#106429) - [Enable sanitizers for s390x-linux] (rust-lang/rust#107127) Libraries --------- - [Loosen the bound on the Debug implementation of Weak.] (rust-lang/rust#90291) - [Make `std::task::Context` !Send and !Sync] (rust-lang/rust#95985) - [PhantomData layout guarantees] (rust-lang/rust#104081) - [Don't derive Debug for `OnceWith` & `RepeatWith`] (rust-lang/rust#104163) - [Implement DerefMut for PathBuf] (rust-lang/rust#105018) - [Add O(1) `Vec -> VecDeque` conversion guarantee] (rust-lang/rust#105128) - [Leak amplification for peek_mut() to ensure BinaryHeap's invariant is always met] (rust-lang/rust#105851) Stabilized APIs --------------- - [`{core,std}::pin::pin!`] (https://doc.rust-lang.org/stable/std/pin/macro.pin.html) - [`impl From<bool> for {f32,f64}`] (https://doc.rust-lang.org/stable/std/primitive.f32.html#impl-From%3Cbool%3E-for-f32) - [`std::path::MAIN_SEPARATOR_STR`] (https://doc.rust-lang.org/stable/std/path/constant.MAIN_SEPARATOR_STR.html) - [`impl DerefMut for PathBuf`] (https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#impl-DerefMut-for-PathBuf) These APIs are now stable in const contexts: - [`VecDeque::new`] (https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.new) Cargo ----- - [Stabilize sparse registry support for crates.io] (rust-lang/cargo#11224) - [`cargo build --verbose` tells you more about why it recompiles.] (rust-lang/cargo#11407) - [Show progress of crates.io index update even `net.git-fetch-with-cli` option enabled] (rust-lang/cargo#11579) Misc ---- Compatibility Notes ------------------- - [Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report] (rust-lang/rust#103418) - [Only specify `--target` by default for `-Zgcc-ld=lld` on wasm] (rust-lang/rust#101792) - [Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow] (rust-lang/rust#106465) - [`std::task::Context` no longer implements Send and Sync] (rust-lang/rust#95985) nternal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Encode spans relative to the enclosing item] (rust-lang/rust#84762) - [Don't normalize in AstConv] (rust-lang/rust#101947) - [Find the right lower bound region in the scenario of partial order relations] (rust-lang/rust#104765) - [Fix impl block in const expr] (rust-lang/rust#104889) - [Check ADT fields for copy implementations considering regions] (rust-lang/rust#105102) - [rustdoc: simplify JS search routine by not messing with lev distance] (rust-lang/rust#105796) - [Enable ThinLTO for rustc on `x86_64-pc-windows-msvc`] (rust-lang/rust#103591) - [Enable ThinLTO for rustc on `x86_64-apple-darwin`] (rust-lang/rust#103647) Version 1.67.0 (2023-01-26) ========================== Language -------- - [Make `Sized` predicates coinductive, allowing cycles.] (rust-lang/rust#100386) - [`#[must_use]` annotations on `async fn` also affect the `Future::Output`.] (rust-lang/rust#100633) - [Elaborate supertrait obligations when deducing closure signatures.] (rust-lang/rust#101834) - [Invalid literals are no longer an error under `cfg(FALSE)`.] (rust-lang/rust#102944) - [Unreserve braced enum variants in value namespace.] (rust-lang/rust#103578) Compiler -------- - [Enable varargs support for calling conventions other than `C` or `cdecl`.] (rust-lang/rust#97971) - [Add new MIR constant propagation based on dataflow analysis.] (rust-lang/rust#101168) - [Optimize field ordering by grouping m\*2^n-sized fields with equivalently aligned ones.] (rust-lang/rust#102750) - [Stabilize native library modifier `verbatim`.] (rust-lang/rust#104360) Added and removed targets: - [Add a tier 3 target for PowerPC on AIX] (rust-lang/rust#102293), `powerpc64-ibm-aix`. - [Add a tier 3 target for the Sony PlayStation 1] (rust-lang/rust#102689), `mipsel-sony-psx`. - [Add tier 3 `no_std` targets for the QNX Neutrino RTOS] (rust-lang/rust#102701), `aarch64-unknown-nto-qnx710` and `x86_64-pc-nto-qnx710`. - [Remove tier 3 `linuxkernel` targets] (rust-lang/rust#104015) (not used by the actual kernel). Refer to Rust's [platform support page][platform-support-doc] for more information on Rust's tiered platform support. Libraries --------- - [Merge `crossbeam-channel` into `std::sync::mpsc`.] (rust-lang/rust#93563) - [Fix inconsistent rounding of 0.5 when formatted to 0 decimal places.] (rust-lang/rust#102935) - [Derive `Eq` and `Hash` for `ControlFlow`.] (rust-lang/rust#103084) - [Don't build `compiler_builtins` with `-C panic=abort`.] (rust-lang/rust#103786) Stabilized APIs --------------- - [`{integer}::checked_ilog`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog) - [`{integer}::checked_ilog2`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog2) - [`{integer}::checked_ilog10`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.checked_ilog10) - [`{integer}::ilog`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog) - [`{integer}::ilog2`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog2) - [`{integer}::ilog10`] (https://doc.rust-lang.org/stable/std/primitive.i32.html#method.ilog10) - [`NonZeroU*::ilog2`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#method.ilog2) - [`NonZeroU*::ilog10`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#method.ilog10) - [`NonZero*::BITS`] (https://doc.rust-lang.org/stable/std/num/struct.NonZeroU32.html#associatedconstant.BITS) These APIs are now stable in const contexts: - [`char::from_u32`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.from_u32) - [`char::from_digit`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.from_digit) - [`char::to_digit`] (https://doc.rust-lang.org/stable/std/primitive.char.html#method.to_digit) - [`core::char::from_u32`] (https://doc.rust-lang.org/stable/core/char/fn.from_u32.html) - [`core::char::from_digit`] (https://doc.rust-lang.org/stable/core/char/fn.from_digit.html) Compatibility Notes ------------------- - [The layout of `repr(Rust)` types now groups m\*2^n-sized fields with equivalently aligned ones.] (rust-lang/rust#102750) This is intended to be an optimization, but it is also known to increase type sizes in a few cases for the placement of enum tags. As a reminder, the layout of `repr(Rust)` types is an implementation detail, subject to change. - [0.5 now rounds to 0 when formatted to 0 decimal places.] (rust-lang/rust#102935) This makes it consistent with the rest of floating point formatting that rounds ties toward even digits. - [Chains of `&&` and `||` will now drop temporaries from their sub-expressions in evaluation order, left-to-right.] (rust-lang/rust#103293) Previously, it was "twisted" such that the _first_ expression dropped its temporaries _last_, after all of the other expressions dropped in order. - [Underscore suffixes on string literals are now a hard error.] (rust-lang/rust#103914) This has been a future-compatibility warning since 1.20.0. - [Stop passing `-export-dynamic` to `wasm-ld`.] (rust-lang/rust#105405) - [`main` is now mangled as `__main_void` on `wasm32-wasi`.] (rust-lang/rust#105468) - [Cargo now emits an error if there are multiple registries in the configuration with the same index URL.] (rust-lang/cargo#10592) Internal Changes ---------------- These changes do not affect any public interfaces of Rust, but they represent significant improvements to the performance or internals of rustc and related tools. - [Rewrite LLVM's archive writer in Rust.] (rust-lang/rust#97485)
Add new MIR constant propagation based on dataflow analysis The current constant propagation in `rustc_mir_transform/src/const_prop.rs` fails to handle many cases that would be expected from a constant propagation optimization. For example: ```rust let x = if true { 0 } else { 0 }; ``` This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations. Closes #80038. Closes #81605. ## Todo ### Essential - [x] [Writes to inactive enum variants](rust-lang/rust#101168 (review)). Resolved by rejecting the registration of places with downcast projections for now. Could be improved by flooding other variants if mutable access to a variant is observed. - [X] Handle [`StatementKind::CopyNonOverlapping`](rust-lang/rust#101168 (comment)). Resolved by flooding the destination. - [x] Handle `UnsafeCell` / `!Freeze` correctly. - [X] Overflow propagation of `CheckedBinaryOp`: Decided to not propagate if overflow flag is `true` (`false` will still be propagated) - [x] More documentation in general. - [x] Arguments for correctness, documentation of necessary assumptions. - [x] Better performance, or alternatively, require `-Zmir-opt-level=3` for now. ### Extra - [x] Add explicit unreachability, i.e. upgrading the lattice from $\mathbb{P} \to \mathbb{V}$ to $\set{\bot} \cup (\mathbb{P} \to \mathbb{V})$. - [x] Use storage statements to improve precision. - [ ] Consider opening issue for duplicate diagnostics: rust-lang/rust#101168 (comment) - [ ] Flood moved-from places with $\bot$ (requires some changes for places with tracked projections). - [ ] Add downcast projections back in. - [ ] [Algebraic simplifications](rust-lang/rust#101168 (comment)) (possibly with a shared API; done by old const prop). - [ ] Propagation through slices / arrays. - [ ] Find other optimizations that are done by old `const_prop.rs`, but not by this one.
Add new MIR constant propagation based on dataflow analysis The current constant propagation in `rustc_mir_transform/src/const_prop.rs` fails to handle many cases that would be expected from a constant propagation optimization. For example: ```rust let x = if true { 0 } else { 0 }; ``` This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations. Closes #80038. Closes #81605. ## Todo ### Essential - [x] [Writes to inactive enum variants](rust-lang/rust#101168 (review)). Resolved by rejecting the registration of places with downcast projections for now. Could be improved by flooding other variants if mutable access to a variant is observed. - [X] Handle [`StatementKind::CopyNonOverlapping`](rust-lang/rust#101168 (comment)). Resolved by flooding the destination. - [x] Handle `UnsafeCell` / `!Freeze` correctly. - [X] Overflow propagation of `CheckedBinaryOp`: Decided to not propagate if overflow flag is `true` (`false` will still be propagated) - [x] More documentation in general. - [x] Arguments for correctness, documentation of necessary assumptions. - [x] Better performance, or alternatively, require `-Zmir-opt-level=3` for now. ### Extra - [x] Add explicit unreachability, i.e. upgrading the lattice from $\mathbb{P} \to \mathbb{V}$ to $\set{\bot} \cup (\mathbb{P} \to \mathbb{V})$. - [x] Use storage statements to improve precision. - [ ] Consider opening issue for duplicate diagnostics: rust-lang/rust#101168 (comment) - [ ] Flood moved-from places with $\bot$ (requires some changes for places with tracked projections). - [ ] Add downcast projections back in. - [ ] [Algebraic simplifications](rust-lang/rust#101168 (comment)) (possibly with a shared API; done by old const prop). - [ ] Propagation through slices / arrays. - [ ] Find other optimizations that are done by old `const_prop.rs`, but not by this one.
Add new MIR constant propagation based on dataflow analysis The current constant propagation in `rustc_mir_transform/src/const_prop.rs` fails to handle many cases that would be expected from a constant propagation optimization. For example: ```rust let x = if true { 0 } else { 0 }; ``` This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations. Closes #80038. Closes #81605. ## Todo ### Essential - [x] [Writes to inactive enum variants](rust-lang/rust#101168 (review)). Resolved by rejecting the registration of places with downcast projections for now. Could be improved by flooding other variants if mutable access to a variant is observed. - [X] Handle [`StatementKind::CopyNonOverlapping`](rust-lang/rust#101168 (comment)). Resolved by flooding the destination. - [x] Handle `UnsafeCell` / `!Freeze` correctly. - [X] Overflow propagation of `CheckedBinaryOp`: Decided to not propagate if overflow flag is `true` (`false` will still be propagated) - [x] More documentation in general. - [x] Arguments for correctness, documentation of necessary assumptions. - [x] Better performance, or alternatively, require `-Zmir-opt-level=3` for now. ### Extra - [x] Add explicit unreachability, i.e. upgrading the lattice from $\mathbb{P} \to \mathbb{V}$ to $\set{\bot} \cup (\mathbb{P} \to \mathbb{V})$. - [x] Use storage statements to improve precision. - [ ] Consider opening issue for duplicate diagnostics: rust-lang/rust#101168 (comment) - [ ] Flood moved-from places with $\bot$ (requires some changes for places with tracked projections). - [ ] Add downcast projections back in. - [ ] [Algebraic simplifications](rust-lang/rust#101168 (comment)) (possibly with a shared API; done by old const prop). - [ ] Propagation through slices / arrays. - [ ] Find other optimizations that are done by old `const_prop.rs`, but not by this one.
The current constant propagation in
rustc_mir_transform/src/const_prop.rs
fails to handle many cases that would be expected from a constant propagation optimization. For example:This pull request adds a new constant propagation MIR optimization pass based on the existing dataflow analysis framework. Since most of the analysis is not unique to constant propagation, a generic framework has been extracted. It works on top of the existing framework and could be reused for other optimzations.
Closes #80038. Closes #81605.
Todo
Essential
StatementKind::CopyNonOverlapping
. Resolved by flooding the destination.UnsafeCell
/!Freeze
correctly.CheckedBinaryOp
: Decided to not propagate if overflow flag istrue
(false
will still be propagated)-Zmir-opt-level=3
for now.Extra
const_prop.rs
, but not by this one.