From c74c6486023899e0e2a1669fa4e32b8f62e1f97f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 22 Jul 2020 10:29:37 +0200 Subject: [PATCH 1/3] const prop into operands --- src/librustc_mir/transform/const_prop.rs | 112 ++++++++---------- .../32bit/rustc.main.ConstProp.diff | 14 ++- .../64bit/rustc.main.ConstProp.diff | 14 ++- .../rustc.main.ConstProp.diff | 32 ++++- .../rustc.main.ConstProp.diff | 32 ++++- .../32bit/rustc.main.ConstProp.diff | 18 ++- .../64bit/rustc.main.ConstProp.diff | 18 ++- .../32bit/rustc.main.ConstProp.diff | 9 +- .../64bit/rustc.main.ConstProp.diff | 9 +- .../indirect/rustc.main.ConstProp.diff | 8 +- .../32bit/rustc.main.ConstProp.diff | 14 ++- .../64bit/rustc.main.ConstProp.diff | 14 ++- .../repeat/32bit/rustc.main.ConstProp.diff | 14 ++- .../repeat/64bit/rustc.main.ConstProp.diff | 14 ++- .../slice_len/32bit/rustc.main.ConstProp.diff | 14 ++- .../slice_len/64bit/rustc.main.ConstProp.diff | 14 ++- 16 files changed, 261 insertions(+), 89 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 3073bf53afd78..44c68abd24988 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -582,6 +582,34 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Some(()) } + fn propagate_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + match *operand { + Operand::Copy(l) | Operand::Move(l) => { + if let Some(value) = self.get_const(l) { + if self.should_const_prop(value) { + // FIXME(felix91gr): this code only handles `Scalar` cases. + // For now, we're not handling `ScalarPair` cases because + // doing so here would require a lot of code duplication. + // We should hopefully generalize `Operand` handling into a fn, + // and use it to do const-prop here and everywhere else + // where it makes sense. + if let interpret::Operand::Immediate(interpret::Immediate::Scalar( + ScalarMaybeUninit::Scalar(scalar), + )) = *value + { + *operand = self.operand_from_scalar( + scalar, + value.layout.ty, + self.source_info.unwrap().span, + ); + } + } + } + } + Operand::Constant(ref mut ct) => self.visit_constant(ct, location), + } + } + fn const_prop( &mut self, rvalue: &Rvalue<'tcx>, @@ -905,6 +933,16 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } } + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + // Only const prop copies and moves on `mir_opt_level=3` as doing so + // currently increases compile time. + if self.tcx.sess.opts.debugging_opts.mir_opt_level < 3 { + self.super_operand(operand, location) + } else { + self.propagate_operand(operand, location) + } + } + fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) { trace!("visit_constant: {:?}", constant); self.super_constant(constant, location); @@ -1072,18 +1110,13 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } } } - TerminatorKind::SwitchInt { ref mut discr, switch_ty, .. } => { - if let Some(value) = self.eval_operand(&discr, source_info) { - if self.should_const_prop(value) { - if let ScalarMaybeUninit::Scalar(scalar) = - self.ecx.read_scalar(value).unwrap() - { - *discr = self.operand_from_scalar(scalar, switch_ty, source_info.span); - } - } - } + TerminatorKind::SwitchInt { ref mut discr, .. } => { + // FIXME: This is currently redundant with `visit_operand`, but sadly + // always visiting operands currently causes a perf regression, so + // `visit_operand` currently only runs for propagates places for `mir_opt_level=3`. + self.propagate_operand(discr, location) } - // None of these have Operands to const-propagate + // None of these have Operands to const-propagate. TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort @@ -1096,61 +1129,16 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } => {} - // Every argument in our function calls can be const propagated. - TerminatorKind::Call { ref mut args, .. } => { - let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level; - // Constant Propagation into function call arguments is gated - // under mir-opt-level 2, because LLVM codegen gives performance - // regressions with it. - if mir_opt_level >= 2 { - for opr in args { - /* - The following code would appear to be incomplete, because - the function `Operand::place()` returns `None` if the - `Operand` is of the variant `Operand::Constant`. In this - context however, that variant will never appear. This is why: - - When constructing the MIR, all function call arguments are - copied into `Locals` of `LocalKind::Temp`. At least, all arguments - that are not unsized (Less than 0.1% are unsized. See #71170 - to learn more about those). - - This means that, conversely, all `Operands` found as function call - arguments are of the variant `Operand::Copy`. This allows us to - simplify our handling of `Operands` in this case. - */ - if let Some(l) = opr.place() { - if let Some(value) = self.get_const(l) { - if self.should_const_prop(value) { - // FIXME(felix91gr): this code only handles `Scalar` cases. - // For now, we're not handling `ScalarPair` cases because - // doing so here would require a lot of code duplication. - // We should hopefully generalize `Operand` handling into a fn, - // and use it to do const-prop here and everywhere else - // where it makes sense. - if let interpret::Operand::Immediate( - interpret::Immediate::Scalar(ScalarMaybeUninit::Scalar( - scalar, - )), - ) = *value - { - *opr = self.operand_from_scalar( - scalar, - value.layout.ty, - source_info.span, - ); - } - } - } - } - } - } - } + // Every argument in our function calls have already been propagated in `visit_operand`. + // + // NOTE: because LLVM codegen gives performance regressions with it, so this is gated + // on `mir_opt_level=3`. + TerminatorKind::Call { .. } => {} } // We remove all Locals which are restricted in propagation to their containing blocks and // which were modified in the current block. - // Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const` + // Take it out of the ecx so we can get a mutable reference to the ecx for `remove_const`. let mut locals = std::mem::take(&mut self.ecx.machine.written_only_inside_own_block_locals); for &local in locals.iter() { Self::remove_const(&mut self.ecx, local); diff --git a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff index 48908479935d1..bbd6c8042f196 100644 --- a/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/array_index/32bit/rustc.main.ConstProp.diff @@ -64,13 +64,25 @@ + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000004)) ++ // mir::Constant ++ // + span: $DIR/array_index.rs:5:18: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000004)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000002)) ++ // mir::Constant ++ // + span: $DIR/array_index.rs:5:18: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff index fd662698a0fd4..d9096e5f3f13e 100644 --- a/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/array_index/64bit/rustc.main.ConstProp.diff @@ -64,13 +64,25 @@ + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:5:18: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/array_index.rs:5:18: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000004)) ++ // mir::Constant ++ // + span: $DIR/array_index.rs:5:18: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000004)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000002)) ++ // mir::Constant ++ // + span: $DIR/array_index.rs:5:18: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff index ed28678edb30d..4bd4bb0dd7dd4 100644 --- a/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero/rustc.main.ConstProp.diff @@ -38,15 +38,22 @@ - // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // + span: $DIR/bad_op_div_by_zero.rs:5:18: 5:19 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } +- assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + _4 = const true; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x01)) ++ // mir::Constant ++ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ assert(!const true, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } - assert(!move _4, "attempt to divide {} by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 - // ty::Const ++ // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant @@ -90,29 +97,42 @@ - _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 - assert(!move _7, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } -+ assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 -+ // ty::Const ++ assert(!const false, "attempt to compute `{} / {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } - // ty::Const ++ // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } } bb2: { - _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 +- _2 = Div(const 1_i32, move _3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 ++ _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:14: 5:19 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:15 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/bad_op_div_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } StorageDead(_3); // scope 1 at $DIR/bad_op_div_by_zero.rs:5:18: 5:19 _0 = const (); // scope 0 at $DIR/bad_op_div_by_zero.rs:3:11: 6:2 // ty::Const diff --git a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff index 8855df95aeab5..ecd030e32b4ee 100644 --- a/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_mod_by_zero/rustc.main.ConstProp.diff @@ -38,15 +38,22 @@ - // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // + span: $DIR/bad_op_mod_by_zero.rs:5:18: 5:19 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } +- assert(!move _4, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + _4 = const true; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x01)) ++ // mir::Constant ++ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ assert(!const true, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } - assert(!move _4, "attempt to calculate the remainder of {} with a divisor of zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 - // ty::Const ++ // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant @@ -90,29 +97,42 @@ - _7 = BitAnd(move _5, move _6); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 - assert(!move _7, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } -+ assert(!const false, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 -+ // ty::Const ++ assert(!const false, "attempt to compute the remainder of `{} % {}` which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } - // ty::Const ++ // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } } bb2: { - _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 +- _2 = Rem(const 1_i32, move _3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 ++ _2 = Rem(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 // ty::Const // + ty: i32 // + val: Value(Scalar(0x00000001)) // mir::Constant // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:15 // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000000)) ++ // mir::Constant ++ // + span: $DIR/bad_op_mod_by_zero.rs:5:14: 5:19 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } StorageDead(_3); // scope 1 at $DIR/bad_op_mod_by_zero.rs:5:18: 5:19 _0 = const (); // scope 0 at $DIR/bad_op_mod_by_zero.rs:3:11: 6:2 // ty::Const diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff index 0f9c81943eda9..2b5010759d750 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/32bit/rustc.main.ConstProp.diff @@ -47,8 +47,22 @@ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24 // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 - _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 - assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 +- assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000003)) ++ // mir::Constant ++ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } ++ assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000003)) ++ // mir::Constant ++ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff index da2c8dffb2411..301aaf2924761 100644 --- a/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/bad_op_unsafe_oob_for_slices/64bit/rustc.main.ConstProp.diff @@ -47,8 +47,22 @@ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:23: 7:24 // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } _7 = Len((*_1)); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 - _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 - assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 +- _8 = Lt(_6, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 +- assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ _8 = Lt(const 3_usize, _7); // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000003)) ++ // mir::Constant ++ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } ++ assert(move _8, "index out of bounds: the len is {} but the index is {}", move _7, const 3_usize) -> bb1; // scope 2 at $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000003)) ++ // mir::Constant ++ // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:7:18: 7:25 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff index 26010b43c922a..539a16f52dca2 100644 --- a/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/32bit/rustc.main.ConstProp.diff @@ -56,7 +56,14 @@ } bb2: { - switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 +- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 ++ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 ++ // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x01)) ++ // mir::Constant ++ // + span: $DIR/discriminant.rs:11:26: 11:30 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } } bb3: { diff --git a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff index b09c9c4766116..20875448eddc9 100644 --- a/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/discriminant/64bit/rustc.main.ConstProp.diff @@ -56,7 +56,14 @@ } bb2: { - switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 +- switchInt(((_3 as Some).0: bool)) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 ++ switchInt(const true) -> [false: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:26: 11:30 ++ // ty::Const ++ // + ty: bool ++ // + val: Value(Scalar(0x01)) ++ // mir::Constant ++ // + span: $DIR/discriminant.rs:11:26: 11:30 ++ // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } } bb3: { diff --git a/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff index 71980185fd5cd..57906b1cabddb 100644 --- a/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/indirect/rustc.main.ConstProp.diff @@ -43,7 +43,7 @@ + // mir::Constant + // + span: $DIR/indirect.rs:5:13: 5:29 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } -+ assert(!const false, "attempt to compute `{} + {}` which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29 ++ assert(!const false, "attempt to compute `{} + {}` which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:5:13: 5:29 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) @@ -52,6 +52,12 @@ + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + // ty::Const // + ty: u8 ++ // + val: Value(Scalar(0x02)) ++ // mir::Constant ++ // + span: $DIR/indirect.rs:5:13: 5:29 ++ // + literal: Const { ty: u8, val: Value(Scalar(0x02)) } ++ // ty::Const ++ // + ty: u8 // + val: Value(Scalar(0x01)) // mir::Constant // + span: $DIR/indirect.rs:5:28: 5:29 diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff index 4bfa50e9851f4..5312784bc8aae 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable/32bit/rustc.main.ConstProp.diff @@ -139,13 +139,25 @@ + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000006)) ++ // mir::Constant ++ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000006)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000003)) ++ // mir::Constant ++ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } } bb2: { diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff index 2d40567ce8da1..7af9984136667 100644 --- a/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/optimizes_into_variable/64bit/rustc.main.ConstProp.diff @@ -139,13 +139,25 @@ + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _6, _5) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 6_usize, const 3_usize) -> bb2; // scope 1 at $DIR/optimizes_into_variable.rs:13:13: 13:34 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000006)) ++ // mir::Constant ++ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000006)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000003)) ++ // mir::Constant ++ // + span: $DIR/optimizes_into_variable.rs:13:13: 13:34 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } } bb2: { diff --git a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff index 3046b2ca9b8a4..c30075bbb05fd 100644 --- a/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/repeat/32bit/rustc.main.ConstProp.diff @@ -48,13 +48,25 @@ + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000008)) ++ // mir::Constant ++ // + span: $DIR/repeat.rs:6:18: 6:28 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000008)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000002)) ++ // mir::Constant ++ // + span: $DIR/repeat.rs:6:18: 6:28 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff index c06ed33df24c1..cadce59cf954d 100644 --- a/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/repeat/64bit/rustc.main.ConstProp.diff @@ -48,13 +48,25 @@ + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _5, _4) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 8_usize, const 2_usize) -> bb1; // scope 0 at $DIR/repeat.rs:6:18: 6:28 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/repeat.rs:6:18: 6:28 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000008)) ++ // mir::Constant ++ // + span: $DIR/repeat.rs:6:18: 6:28 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000008)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000002)) ++ // mir::Constant ++ // + span: $DIR/repeat.rs:6:18: 6:28 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff index 6eb64f75ef17e..0a07a1a11f275 100644 --- a/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/slice_len/32bit/rustc.main.ConstProp.diff @@ -54,13 +54,25 @@ + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000003)) ++ // mir::Constant ++ // + span: $DIR/slice_len.rs:5:5: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000003)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000001)) ++ // mir::Constant ++ // + span: $DIR/slice_len.rs:5:5: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff index 2b641bef1d802..f8c6f29e854df 100644 --- a/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/slice_len/64bit/rustc.main.ConstProp.diff @@ -54,13 +54,25 @@ + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } -+ assert(const true, "index out of bounds: the len is {} but the index is {}", move _7, _6) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 ++ assert(const true, "index out of bounds: the len is {} but the index is {}", const 3_usize, const 1_usize) -> bb1; // scope 0 at $DIR/slice_len.rs:5:5: 5:33 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x01)) + // mir::Constant + // + span: $DIR/slice_len.rs:5:5: 5:33 + // + literal: Const { ty: bool, val: Value(Scalar(0x01)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000003)) ++ // mir::Constant ++ // + span: $DIR/slice_len.rs:5:5: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000003)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000001)) ++ // mir::Constant ++ // + span: $DIR/slice_len.rs:5:5: 5:33 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } } bb1: { From d257bacfea8a046c41d6841f897d17944f2f0e64 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 22 Jul 2020 12:32:02 +0200 Subject: [PATCH 2/3] note LLVM in fixme --- src/librustc_mir/transform/const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 44c68abd24988..2fa2167d5f896 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1112,7 +1112,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } TerminatorKind::SwitchInt { ref mut discr, .. } => { // FIXME: This is currently redundant with `visit_operand`, but sadly - // always visiting operands currently causes a perf regression, so + // always visiting operands currently causes a perf regression in LLVM codegen, so // `visit_operand` currently only runs for propagates places for `mir_opt_level=3`. self.propagate_operand(discr, location) } From 61a9ab8fe64484458059d630ab3d0938f7f34ccf Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Thu, 23 Jul 2020 17:58:54 +0200 Subject: [PATCH 3/3] slightly adapt const prop --- src/librustc_mir/transform/const_prop.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 2fa2167d5f896..024595466a231 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -582,7 +582,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Some(()) } - fn propagate_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + fn propagate_operand(&mut self, operand: &mut Operand<'tcx>) { match *operand { Operand::Copy(l) | Operand::Move(l) => { if let Some(value) = self.get_const(l) { @@ -606,7 +606,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } } - Operand::Constant(ref mut ct) => self.visit_constant(ct, location), + Operand::Constant(_) => (), } } @@ -934,12 +934,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + self.super_operand(operand, location); + // Only const prop copies and moves on `mir_opt_level=3` as doing so // currently increases compile time. - if self.tcx.sess.opts.debugging_opts.mir_opt_level < 3 { - self.super_operand(operand, location) - } else { - self.propagate_operand(operand, location) + if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 { + self.propagate_operand(operand) } } @@ -1114,7 +1114,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // FIXME: This is currently redundant with `visit_operand`, but sadly // always visiting operands currently causes a perf regression in LLVM codegen, so // `visit_operand` currently only runs for propagates places for `mir_opt_level=3`. - self.propagate_operand(discr, location) + self.propagate_operand(discr) } // None of these have Operands to const-propagate. TerminatorKind::Goto { .. }