Skip to content
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

Online def-use analysis for copy propagation pass #76569

Closed
wants to merge 4 commits into from

Conversation

tmiasko
Copy link
Contributor

@tmiasko tmiasko commented Sep 10, 2020

Implement an online def-use analysis for the copy propagation pass. The
analysis is updated in an incremental fashion as changes are made to the
MIR body instead of being recomputed from scratch after each change.

The analysis is intended to be functionally equivalent to the previous
one, but it also offers a new methods to: remove specific statement,
remove storage markers, and replace the uses of a local with another
local or a constant, all while keeping the analysis up-to date.

There are two functional changes to the copy propagation pass, but they
should have no effect in practice:

  • Each locals is examined only once as a potential destination for copy
    propagation, since propagation does not introduce new optimization
    opportunities.

  • The code for self-assignment elimination has been removed, since it
    not necessary (assignments that are used for the propagation are
    removed separately).

For def-use analysis changes, I would recommend reading the new version and the
old version separately, rather than examining the diff. For the copy propagation
changes, I would recommend looking at the diff that ignores whitespace during
comparison.

Closes #36673.
Closes #73717.

@rust-highfive
Copy link
Collaborator

r? @eddyb

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Sep 10, 2020
@wesleywiser
Copy link
Member

cc @rust-lang/wg-mir-opt

@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 11, 2020

I also noticed that the previous implementation had a bug where a failure to
completely propagate a constant would inhibit propagation attempts for any
additional locals.

I reorganized the changes so that this issue is fixed in separate commit (and
this is the only commit that is supposed to introduce any functional changes).

@jonas-schievink
Copy link
Contributor

I was planning to remove this pass entirely once my destination propagation pass lands

@oli-obk
Copy link
Contributor

oli-obk commented Sep 11, 2020

We're not running this pass except in mir-opt-level 2 anyway, so noone is depending on it. We could just remove it entirely even without a replacement.

@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 11, 2020

@jonas-schievink did you have a chance to compare those two approaches, e.g., the total number of propagations made when build the standard library? (I was looking at this at some point, but the destination propagation PR fails at runtime after a rebase, and I am yet to investigate that further).

@jonas-schievink
Copy link
Contributor

No, but I've noticed that almost none of the copy-propagation tests are actually testing any propagation (they have an empty diff). I'll try to get the dest-prop PR rebased. IIRC @eddyb is pretty convinced that dest-prop is a better approach than copy-prop.

@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 11, 2020

Thanks, it would be nice to compare the two. For the copy propagation, based on logging that is part of this PR, I have the following stats:

  • Total number of propagations: 57277
  • Propagated locals: 47762
  • Propagated constants: 9515

The maximum is for evaluate_one_operation from gimli with 428 propagations.

$ cargo new --bin empty
$ cd empty
$ env \
  RUSTFLAGS=-Zmir-opt-level=2\
  RUSTC_LOG=rustc_mir::transform::copy_prop=info\
  cargo +stage1 -Zbuild-std build --target x86_64-unknown-linux-gnu

@jonas-schievink
Copy link
Contributor

I've rebased #72632 and fixed the assertion failures

@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 12, 2020

For destination propagation there are 57672 propagations when rebuilding the standard library, but there are still 21793 copy propagations afterwards.

@jonas-schievink
Copy link
Contributor

Interesting result!

@@ -30,177 +29,151 @@ use rustc_middle::ty::TyCtxt;
pub struct CopyPropagation;

impl<'tcx> MirPass<'tcx> for CopyPropagation {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) {
fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
// We only run when the MIR optimization level is > 1.
// This avoids a slow pass, and messing up debug info.
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you change this to

Suggested change
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
if tcx.sess.opts.debugging_opts.mir_opt_level <= 0 {

we can perf-test this if you want

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, lets try it. Later we could measure the old version for comparison.

@jonas-schievink
Copy link
Contributor

@bors try @rust-timer queue

@rust-timer
Copy link
Collaborator

Awaiting bors try build completion

@bors
Copy link
Contributor

bors commented Sep 14, 2020

⌛ Trying commit 48fba1f7ed0e26b866d867e37b92cd75eca7e094 with merge 0e80e09f88ec0293bdc27db9c8cc0b283a4f75b3...

@rust-log-analyzer
Copy link
Collaborator

The job dist-x86_64-linux of your PR failed (pretty log, raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
Documenting stage2 std (x86_64-unknown-linux-gnu)
Uplifting stage1 std (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
Copying stage2 std from stage1 (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu / x86_64-unknown-linux-gnu)
 Documenting core v0.0.0 (/checkout/library/core)
error[E0046]: not all trait items implemented, missing: `bitor`
    |
    |
123 |               impl BitOr for $Ty {
    |               ^^^^^^^^^^^^^^^^^^ missing `bitor` in implementation
...
180 | / nonzero_integers! {
181 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
182 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
183 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
...   |
192 | |     #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
    | |_- in this macro invocation
    | 
   ::: library/core/src/ops/bit.rs:240:5
    |
    |
240 |       fn bitor(self, rhs: Rhs) -> Self::Output;
    |       ----------------------------------------- `bitor` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `bitor`
    |
    |
134 |               impl BitOr<$Int> for $Ty {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^ missing `bitor` in implementation
...
180 | / nonzero_integers! {
181 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
182 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
183 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
...   |
192 | |     #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
    | |_- in this macro invocation
    | 
   ::: library/core/src/ops/bit.rs:240:5
    |
    |
240 |       fn bitor(self, rhs: Rhs) -> Self::Output;
    |       ----------------------------------------- `bitor` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `bitor`
    |
    |
146 |               impl BitOr<$Ty> for $Int {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^ missing `bitor` in implementation
...
180 | / nonzero_integers! {
181 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
182 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
183 | |     #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
...   |
192 | |     #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
    | |_- in this macro invocation
    | 
   ::: library/core/src/ops/bit.rs:240:5
    |
    |
240 |       fn bitor(self, rhs: Rhs) -> Self::Output;
    |       ----------------------------------------- `bitor` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `from_str`
   --> library/core/src/num/mod.rs:198:9
   --> library/core/src/num/mod.rs:198:9
    |
198 |           impl FromStr for $t {
    |           ^^^^^^^^^^^^^^^^^^^ missing `from_str` in implementation
...
210 | / from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
211 | | NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
    | |_____________________________________________________________________- in this macro invocation
   ::: library/core/src/str/mod.rs:105:5
    |
    |
105 |       fn from_str(s: &str) -> Result<Self, Self::Err>;
    |       ------------------------------------------------ `from_str` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `from_str`
    --> library/core/src/num/mod.rs:5121:9
    --> library/core/src/num/mod.rs:5121:9
     |
5121 |         impl FromStr for $t {
     |         ^^^^^^^^^^^^^^^^^^^ missing `from_str` in implementation
...
5129 | from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
     | 
    ::: library/core/src/str/mod.rs:105:5
     |
     |
105  |     fn from_str(s: &str) -> Result<Self, Self::Err>;
     |     ------------------------------------------------ `from_str` from trait
     = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `max_value`, `from_u32`, `checked_mul`, `checked_sub`, `checked_add`
     |
5176 |     fn max_value() -> Self;
5176 |     fn max_value() -> Self;
     |     ----------------------- `max_value` from trait
5177 |     fn from_u32(u: u32) -> Self;
     |     ---------------------------- `from_u32` from trait
5178 |     fn checked_mul(&self, other: u32) -> Option<Self>;
     |     -------------------------------------------------- `checked_mul` from trait
5179 |     fn checked_sub(&self, other: u32) -> Option<Self>;
     |     -------------------------------------------------- `checked_sub` from trait
5180 |     fn checked_add(&self, other: u32) -> Option<Self>;
     |     -------------------------------------------------- `checked_add` from trait
...
5184 |     ($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
     |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `max_value`, `from_u32`, `checked_mul`, `checked_sub`, `checked_add` in implementation
...
5205 | doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
     |
     = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `full_mul`, `full_mul_add`, `full_div_rem`
  --> library/core/src/num/bignum.rs:48:13
   |
33 |       fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self);
   |       ------------------------------------------------------------------------ `full_mul` from trait
...
37 |       fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self);
   |       ------------------------------------------------------------------------------------------ `full_mul_add` from trait
...
41 | /     fn full_div_rem(self, other: Self, borrow: Self)
42 | |     -> (Self /* quotient */, Self /* remainder */);
   | |___________________________________________________- `full_div_rem` from trait
...
48 |               impl FullOps for $ty {
   |               ^^^^^^^^^^^^^^^^^^^^ missing `full_mul`, `full_mul_add`, `full_div_rem` in implementation
...
88 | / impl_full_ops! {
89 | |     u8:  add(intrinsics::u8_add_with_overflow),  mul/div(u16);
90 | |     u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
91 | |     u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
92 | |     // See RFC #521 for enabling this.
93 | |     // u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
   | |_- in this macro invocation
   |
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `from_str`
   --> library/core/src/num/dec2flt/mod.rs:104:9
    |
104 |         impl FromStr for $t {
    |         ^^^^^^^^^^^^^^^^^^^ missing `from_str` in implementation
...
162 | from_str_float_impl!(f32);
    | 
   ::: library/core/src/str/mod.rs:105:5
    |
    |
105 |     fn from_str(s: &str) -> Result<Self, Self::Err>;
    |     ------------------------------------------------ `from_str` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `from_str`
error[E0046]: not all trait items implemented, missing: `from_str`
   --> library/core/src/num/dec2flt/mod.rs:104:9
    |
104 |         impl FromStr for $t {
    |         ^^^^^^^^^^^^^^^^^^^ missing `from_str` in implementation
...
163 | from_str_float_impl!(f64);
    | 
   ::: library/core/src/str/mod.rs:105:5
    |
    |
105 |     fn from_str(s: &str) -> Result<Self, Self::Err>;
    |     ------------------------------------------------ `from_str` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)


error[E0046]: not all trait items implemented, missing: `NAN`, `ZERO`, `Bits`, `to_bits`, `from_bits`, `classify`, `integer_decode`, `unpack`, `from_int`, `short_fast_pow10`, `CEIL_LOG5_OF_MAX_SIG`, `MAX_NORMAL_DIGITS`, `INF_CUTOFF`, `ZERO_CUTOFF`, `EXP_BITS`, `SIG_BITS`, `EXPLICIT_SIG_BITS`, `MAX_EXP`, `MIN_EXP`, `MAX_EXP_INT`, `MAX_ENCODED_EXP`, `MIN_EXP_INT`, `MAX_SIG`, `MIN_SIG`
   --> library/core/src/num/dec2flt/rawfp.rs:145:1
    |
51  |     const NAN: Self;
    |     ---------------- `NAN` from trait
52  |     const ZERO: Self;
    |     ----------------- `ZERO` from trait
...
55  |     type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
    |     -------------------------------------------------------------- `Bits` from trait
...
58  |     fn to_bits(self) -> Self::Bits;
    |     ------------------------------- `to_bits` from trait
...
61  |     fn from_bits(v: Self::Bits) -> Self;
    |     ------------------------------------ `from_bits` from trait
...
64  |     fn classify(self) -> FpCategory;
    |     -------------------------------- `classify` from trait
...
67  |     fn integer_decode(self) -> (u64, i16, i8);
    |     ------------------------------------------ `integer_decode` from trait
...
70  |     fn unpack(self) -> Unpacked;
    |     ---------------------------- `unpack` from trait
...
74  |     fn from_int(x: u64) -> Self;
    |     ---------------------------- `from_int` from trait
...
78  |     fn short_fast_pow10(e: usize) -> Self;
    |     -------------------------------------- `short_fast_pow10` from trait
...
82  |     const CEIL_LOG5_OF_MAX_SIG: i16;
    |     -------------------------------- `CEIL_LOG5_OF_MAX_SIG` from trait
86  |     const MAX_NORMAL_DIGITS: usize;
86  |     const MAX_NORMAL_DIGITS: usize;
    |     ------------------------------- `MAX_NORMAL_DIGITS` from trait
...
90  |     const INF_CUTOFF: i64;
    |     ---------------------- `INF_CUTOFF` from trait
...
94  |     const ZERO_CUTOFF: i64;
    |     ----------------------- `ZERO_CUTOFF` from trait
...
97  |     const EXP_BITS: u8;
    |     ------------------- `EXP_BITS` from trait
...
100 |     const SIG_BITS: u8;
    |     ------------------- `SIG_BITS` from trait
...
103 |     const EXPLICIT_SIG_BITS: u8;
    |     ---------------------------- `EXPLICIT_SIG_BITS` from trait
106 |     const MAX_EXP: i16;
106 |     const MAX_EXP: i16;
    |     ------------------- `MAX_EXP` from trait
109 |     const MIN_EXP: i16;
109 |     const MIN_EXP: i16;
    |     ------------------- `MIN_EXP` from trait
112 |     const MAX_EXP_INT: i16;
112 |     const MAX_EXP_INT: i16;
    |     ----------------------- `MAX_EXP_INT` from trait
...
115 |     const MAX_ENCODED_EXP: i16;
    |     --------------------------- `MAX_ENCODED_EXP` from trait
118 |     const MIN_EXP_INT: i16;
118 |     const MIN_EXP_INT: i16;
    |     ----------------------- `MIN_EXP_INT` from trait
...
121 |     const MAX_SIG: u64;
    |     ------------------- `MAX_SIG` from trait
124 |     const MIN_SIG: u64;
124 |     const MIN_SIG: u64;
    |     ------------------- `MIN_SIG` from trait
...
145 | impl RawFloat for f32 {
    | ^^^^^^^^^^^^^^^^^^^^^ missing `NAN`, `ZERO`, `Bits`, `to_bits`, `from_bits`, `classify`, `integer_decode`, `unpack`, `from_int`, `short_fast_pow10`, `CEIL_LOG5_OF_MAX_SIG`, `MAX_NORMAL_DIGITS`, `INF_CUTOFF`, `ZERO_CUTOFF`, `EXP_BITS`, `SIG_BITS`, `EXPLICIT_SIG_BITS`, `MAX_EXP`, `MIN_EXP`, `MAX_EXP_INT`, `MAX_ENCODED_EXP`, `MIN_EXP_INT`, `MAX_SIG`, `MIN_SIG` in implementation

error[E0046]: not all trait items implemented, missing: `NAN`, `ZERO`, `Bits`, `to_bits`, `from_bits`, `classify`, `integer_decode`, `unpack`, `from_int`, `short_fast_pow10`, `CEIL_LOG5_OF_MAX_SIG`, `MAX_NORMAL_DIGITS`, `INF_CUTOFF`, `ZERO_CUTOFF`, `EXP_BITS`, `SIG_BITS`, `EXPLICIT_SIG_BITS`, `MAX_EXP`, `MIN_EXP`, `MAX_EXP_INT`, `MAX_ENCODED_EXP`, `MIN_EXP_INT`, `MAX_SIG`, `MIN_SIG`
   --> library/core/src/num/dec2flt/rawfp.rs:194:1
    |
51  |     const NAN: Self;
    |     ---------------- `NAN` from trait
52  |     const ZERO: Self;
    |     ----------------- `ZERO` from trait
...
55  |     type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
    |     -------------------------------------------------------------- `Bits` from trait
...
58  |     fn to_bits(self) -> Self::Bits;
    |     ------------------------------- `to_bits` from trait
...
61  |     fn from_bits(v: Self::Bits) -> Self;
    |     ------------------------------------ `from_bits` from trait
...
64  |     fn classify(self) -> FpCategory;
    |     -------------------------------- `classify` from trait
...
67  |     fn integer_decode(self) -> (u64, i16, i8);
    |     ------------------------------------------ `integer_decode` from trait
...
70  |     fn unpack(self) -> Unpacked;
    |     ---------------------------- `unpack` from trait
...
74  |     fn from_int(x: u64) -> Self;
    |     ---------------------------- `from_int` from trait
...
78  |     fn short_fast_pow10(e: usize) -> Self;
    |     -------------------------------------- `short_fast_pow10` from trait
...
82  |     const CEIL_LOG5_OF_MAX_SIG: i16;
    |     -------------------------------- `CEIL_LOG5_OF_MAX_SIG` from trait
86  |     const MAX_NORMAL_DIGITS: usize;
86  |     const MAX_NORMAL_DIGITS: usize;
    |     ------------------------------- `MAX_NORMAL_DIGITS` from trait
...
90  |     const INF_CUTOFF: i64;
    |     ---------------------- `INF_CUTOFF` from trait
...
94  |     const ZERO_CUTOFF: i64;
    |     ----------------------- `ZERO_CUTOFF` from trait
...
97  |     const EXP_BITS: u8;
    |     ------------------- `EXP_BITS` from trait
...
100 |     const SIG_BITS: u8;
    |     ------------------- `SIG_BITS` from trait
...
103 |     const EXPLICIT_SIG_BITS: u8;
    |     ---------------------------- `EXPLICIT_SIG_BITS` from trait
106 |     const MAX_EXP: i16;
106 |     const MAX_EXP: i16;
    |     ------------------- `MAX_EXP` from trait
109 |     const MIN_EXP: i16;
109 |     const MIN_EXP: i16;
    |     ------------------- `MIN_EXP` from trait
112 |     const MAX_EXP_INT: i16;
112 |     const MAX_EXP_INT: i16;
    |     ----------------------- `MAX_EXP_INT` from trait
...
115 |     const MAX_ENCODED_EXP: i16;
    |     --------------------------- `MAX_ENCODED_EXP` from trait
118 |     const MIN_EXP_INT: i16;
118 |     const MIN_EXP_INT: i16;
    |     ----------------------- `MIN_EXP_INT` from trait
...
121 |     const MAX_SIG: u64;
    |     ------------------- `MAX_SIG` from trait
124 |     const MIN_SIG: u64;
124 |     const MIN_SIG: u64;
    |     ------------------- `MIN_SIG` from trait
...
194 | impl RawFloat for f64 {
    | ^^^^^^^^^^^^^^^^^^^^^ missing `NAN`, `ZERO`, `Bits`, `to_bits`, `from_bits`, `classify`, `integer_decode`, `unpack`, `from_int`, `short_fast_pow10`, `CEIL_LOG5_OF_MAX_SIG`, `MAX_NORMAL_DIGITS`, `INF_CUTOFF`, `ZERO_CUTOFF`, `EXP_BITS`, `SIG_BITS`, `EXPLICIT_SIG_BITS`, `MAX_EXP`, `MIN_EXP`, `MAX_EXP_INT`, `MAX_ENCODED_EXP`, `MIN_EXP_INT`, `MAX_SIG`, `MIN_SIG` in implementation
error[E0046]: not all trait items implemented, missing: `shl`
   --> library/core/src/num/wrapping.rs:63:9
    |
    |
63  |         impl Shl<$f> for Wrapping<$t> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shl` in implementation
...
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    | 
   ::: library/core/src/ops/bit.rs:435:5
    |
    |
435 |     fn shl(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shl` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shr`
   --> library/core/src/num/wrapping.rs:84:9
   --> library/core/src/num/wrapping.rs:84:9
    |
84  |         impl Shr<$f> for Wrapping<$t> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shr` in implementation
...
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    | 
   ::: library/core/src/ops/bit.rs:553:5
    |
    |
553 |     fn shr(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shr` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shl`
   --> library/core/src/internal_macros.rs:30:9
   --> library/core/src/internal_macros.rs:30:9
    |
30  |         impl<'a> $imp<$u> for &'a $t {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shl` in implementation
   ::: library/core/src/ops/bit.rs:435:5
    |
    |
435 |     fn shl(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shl` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shl`
error[E0046]: not all trait items implemented, missing: `shl`
   --> library/core/src/internal_macros.rs:40:9
    |
40  |         impl $imp<&$u> for $t {
    |         ^^^^^^^^^^^^^^^^^^^^^ missing `shl` in implementation
   ::: library/core/src/ops/bit.rs:435:5
    |
    |
435 |     fn shl(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shl` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shl`
error[E0046]: not all trait items implemented, missing: `shl`
   --> library/core/src/internal_macros.rs:50:9
    |
50  |         impl $imp<&$u> for &$t {
    |         ^^^^^^^^^^^^^^^^^^^^^^ missing `shl` in implementation
   ::: library/core/src/ops/bit.rs:435:5
    |
    |
435 |     fn shl(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shl` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shr`
error[E0046]: not all trait items implemented, missing: `shr`
   --> library/core/src/internal_macros.rs:30:9
    |
30  |         impl<'a> $imp<$u> for &'a $t {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shr` in implementation
   ::: library/core/src/ops/bit.rs:553:5
    |
    |
553 |     fn shr(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shr` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shr`
error[E0046]: not all trait items implemented, missing: `shr`
   --> library/core/src/internal_macros.rs:40:9
    |
40  |         impl $imp<&$u> for $t {
    |         ^^^^^^^^^^^^^^^^^^^^^ missing `shr` in implementation
   ::: library/core/src/ops/bit.rs:553:5
    |
    |
553 |     fn shr(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shr` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shr`
error[E0046]: not all trait items implemented, missing: `shr`
   --> library/core/src/internal_macros.rs:50:9
    |
50  |         impl $imp<&$u> for &$t {
    |         ^^^^^^^^^^^^^^^^^^^^^^ missing `shr` in implementation
   ::: library/core/src/ops/bit.rs:553:5
    |
    |
553 |     fn shr(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shr` from trait
   ::: library/core/src/num/wrapping.rs:125:1
    |
    |
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shl`
error[E0046]: not all trait items implemented, missing: `shl`
   --> library/core/src/num/wrapping.rs:63:9
    |
63  |         impl Shl<$f> for Wrapping<$t> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shl` in implementation
...
125 | sh_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
    | 
   ::: library/core/src/ops/bit.rs:435:5
    |
    |
435 |     fn shl(self, rhs: Rhs) -> Self::Output;
    |     --------------------------------------- `shl` from trait
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0046]: not all trait items implemented, missing: `shr`
   --> library/core/src/num/wrapping.rs:84:9
   --> library/core/src/num/wrapping.rs:84:9
    |
84  |         impl Shr<$f> for Wrapping<$t> {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `shr` in implementation
...

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 @rust-lang/infra. (Feature Requests)

@bors
Copy link
Contributor

bors commented Sep 14, 2020

💔 Test failed - checks-actions

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 14, 2020
@jonas-schievink
Copy link
Contributor

Hmm, miscompilation?

Currently a failure to completely propagate a constant inhibits propagation of
any subsequent locals. Add a test case demonstrating the problem before
resolving it.
The copy propagation as currently implemented does not introduce new copy
propagation opportunities. Examine each local for possible optimization only
once.

Additionally, this also fixes the issue where copy propagation optimization
would stop without examining all locals after failing to completely propagate a
constant.
The assignments that are starting point for the copy propagation are removed
separately. The copy propagation does not introduce self-assignments otherwise,
so the code for self-assignments elimination is functionally inert. Remove it.

No functional changes intended.
Implement an online def-use analysis for the copy propagation pass.  The
analysis is updated in an incremental fashion as changes are made to the
MIR body instead of being recomputed from scratch after each change.

The analysis is intended to be equivalent to the previous one, but it
also offers a new methods to: remove specific statement, remove storage
markers, and replace the uses of a local with another local or a
constant, all while keeping the analysis up-to date.

No functional changes intended.
@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 15, 2020

There is a pre-existing issue in the copy propagation pass, I opened #76740 to track it.

@jonas-schievink regarding those copy propagations performed after destination propagation, my notes show that roughly 12000 of those were arguments (they could be propagated by dest-prop if it was a little bit more flexible with regards to propagation direction, I suppose?). There were also substantial number of constant propagated as noted before.

Given that copy propagation pass is working incorrectly right now and has a candidate for a replacement, I am going to close this now.

@tmiasko tmiasko closed this Sep 15, 2020
@tmiasko tmiasko deleted the online-copy-prop branch September 15, 2020 14:34
@jonas-schievink
Copy link
Contributor

roughly 12000 of those were arguments (they could be propagated by dest-prop if it was a little bit more flexible with regards to propagation direction, I suppose?)

Ah, that makes sense. I could see dest prop becoming a more general bidirectional place propagation, but it will probably take some work until that happens.

There were also substantial number of constant propagated as noted before.

Does the existing const prop pass handle those propagations? If not, maybe that would be the right place to improve (this pass shouldn't cause any miscompilations as it already runs by default).

@tmiasko
Copy link
Contributor Author

tmiasko commented Sep 15, 2020

Does the existing const prop pass handle those propagations?

Last time I looked into it, I was under the impression that constant propagation is in a large part a lint, and has to be quite conservative to avoid introducing spurious warnings, e.g., in a code that is otherwise unreachable.

bors added a commit to rust-lang-ci/rust that referenced this pull request Oct 17, 2020
…i-obk

Remove the old copy propagation pass

This pass was added a long time ago, and has not really seen much improvement since (apart from some great work in rust-lang#76569 that unfortunately ran into preexisting soundness issues). It is slow and unsound, and we now have a destination propagation pass that performs a related optimization and could be extended.

Closes rust-lang#36673
Closes rust-lang#73717
Closes rust-lang#76740
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Compile-time regression with mir-opt-level=2 MIR CopyPropagation is slow
9 participants