-
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
Optimize away BitAnd and BitOr when possible #74491
Conversation
r? @estebank (rust_highfive has picked a reviewer for you, use r? to override) |
self.eval_rvalue_with_identities(rvalue, place) | ||
} | ||
|
||
// Attempts to use algebraic identities to |
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.
I think you a word.
36b1716
to
918bfb0
Compare
The code looks fine but I can't take a good look right now. r? @oli-obk for final review. |
918bfb0
to
8f6d14d
Compare
8f6d14d
to
8f3d684
Compare
f52e125
to
7894f9f
Compare
I don't understand why CI is failing:
I have no idea what to do about this? It doesn't seem related to my changes but it's also not flakiness from what I can tell |
@xldenis can you try rebasing on top of a recent master? This doesn't seem like something caused by your PR and doing that might be enough to get CI to pass. Otherwise you might be introducing a bug in this PR and it's triggered in |
|
7894f9f
to
438a794
Compare
it seems to work now on CI, you just need to |
438a794
to
da6cfb8
Compare
da6cfb8
to
6614c00
Compare
this optimization causes a failure for a testcase, that I am unsure how to handle:
previously it seems like this code would compile. What is the correct behavior here? Remove the optimization for multiplication? Or should this code not compile because it was a EDIT: that test was supposed to fail, my opt just changes where the error is raised. I fixed the test output. |
aa4b013
to
060c9ee
Compare
@@ -9,11 +9,12 @@ struct PrintName<T>(T); | |||
impl<T> PrintName<T> { | |||
const VOID: ! = { let x = 0 * std::mem::size_of::<T>(); [][x] }; | |||
//~^ WARN any use of this value will cause an error | |||
//~| ERROR this operation will panic at runtime [unconditional_panic] |
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 add #![warn(unconditional_panic)]
to this file so we test the original thing again. This line can the be changed to
//~| ERROR this operation will panic at runtime [unconditional_panic] | |
//~| WARN this operation will panic at runtime [unconditional_panic] |
cc @lcnr this will make things worse for "some functions that depend on CTFE will evaluate successfully if that generic thing is not needed/used". We already have this situation elsewhere, but we may need to be more aggressive in putting things into the "unevaluated const" list. Right now it's just about generic constants, but after this PR we may need to put function calls of generic functions into it, too. |
@xldenis this is not a blocker for this PR in general, We may should probably just move your optimization under mir-opt-level 3 until we have the scheme for function calls. What do you think? |
@oli-obk because now So the main problem here is probably something like fn test<T>() {
let _ = [0; SOME_MONOMORPHIC_CONST * std::mem::size_of::<T>()];
} That means we can't really fix this by just not looking into It's probably cleaner to add a flag to mir which indicates if it depends on type parameters (during mir_built), so we don't have to care about this while optimizing 🤔 |
💔 Test failed - checks-actions |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
@bors retry |
@bors rollup=iffy may have perf implications |
it doesn't do anything unless |
@bors rollup- Okay, thanks. @nnethercote we don't perf-check mir-opt=3, yes? |
|
Optimize away BitAnd and BitOr when possible This PR lets `const_prop` optimize away `a | true == true` , `a & false == false` and `a * 0 = 0`. While I was writing this I've realized that constant propagation misses a lot of opportunities. For example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2a4b45e772f214210a36749b27223bb0 Constant propagation doesn't seem to... propagate constants, additionally the way constant propagation is currently setup makes it tricky to add cases like `a | false == a`. I tried to organize `eval_rvalue_with_identities` to make the pattern of the optimizations easier to see but it still obscurs what should be a simple peephole optmization. cc @oli-obk
…arth Rollup of 8 pull requests Successful merges: - rust-lang#72954 (revise RwLock for HermitCore) - rust-lang#74367 (Rearrange the pipeline of `pow` to gain efficiency) - rust-lang#74491 (Optimize away BitAnd and BitOr when possible) - rust-lang#74639 (Downgrade glibc to 2.11.1 for ppc, ppc64 and s390x) - rust-lang#74661 (Refactor `region_name`: add `RegionNameHighlight`) - rust-lang#74692 (delay_span_bug instead of silent ignore) - rust-lang#74698 (fixed error reporting for mismatched traits) - rust-lang#74715 (Add a system for creating diffs across multiple mir optimizations.) Failed merges: r? @ghost
@nnethercote is there anyway to specify flags for a perf run? I'm curious how much |
Perf runs just do regular try builds, so I don't think that's possible. You could, however, edit the CI files to use a different set of flags, you just have to do it twice to get the "before" test results. |
…li-obk make `ConstEvaluatable` more strict relevant zulip discussion: https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/.60ConstEvaluatable.60.20generic.20functions/near/204125452 Let's see how much this impacts. Depending on how this goes this should probably be a future compat warning. Short explanation: we currently forbid anonymous constants which depend on generic types, e.g. `[0; std::mem::size_of::<T>]` currently errors. We previously checked this by evaluating the constant and returned an error if that failed. This however allows things like ```rust const fn foo<T>() -> usize { if std::mem::size_of::<*mut T>() < 8 { // size of *mut T does not depend on T std::mem::size_of::<T>() } else { 8 } } fn test<T>() { let _ = [0; foo::<T>()]; } ``` which is a backwards compatibility hazard. This also has worrying interactions with mir optimizations (rust-lang#74491 (comment)) and intrinsics (rust-lang#74538). r? `@oli-obk` `@eddyb`
Always permit ConstProp to exploit arithmetic identities Fixes rust-lang#72751 Initially, I thought I would need to enable operand propagation then do something else, but actually rust-lang#74491 already has the fix for the issue in question! It looks like this optimization was put under MIR opt level 3 due to possible soundness/stability implications, then demoted further to MIR opt level 4 when MIR opt level 2 became associated with `--release`. Perhaps in the past we were doing CTFE on optimized MIR? We aren't anymore, so this optimization has no stability implications. r? `@oli-obk`
Always permit ConstProp to exploit arithmetic identities Fixes rust-lang/rust#72751 Initially, I thought I would need to enable operand propagation then do something else, but actually rust-lang/rust#74491 already has the fix for the issue in question! It looks like this optimization was put under MIR opt level 3 due to possible soundness/stability implications, then demoted further to MIR opt level 4 when MIR opt level 2 became associated with `--release`. Perhaps in the past we were doing CTFE on optimized MIR? We aren't anymore, so this optimization has no stability implications. r? `@oli-obk`
This PR lets
const_prop
optimize awaya | true == true
,a & false == false
anda * 0 = 0
. While I was writing this I've realized that constant propagation misses a lot of opportunities. For example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=2a4b45e772f214210a36749b27223bb0Constant propagation doesn't seem to... propagate constants, additionally the way constant propagation is currently setup makes it tricky to add cases like
a | false == a
.I tried to organize
eval_rvalue_with_identities
to make the pattern of the optimizations easier to see but it still obscurs what should be a simple peephole optmization.cc @oli-obk