From 837c29b7a0196bc6b38abdfa9b21718699dfb016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Wed, 22 Apr 2020 21:39:47 -0400 Subject: [PATCH 1/7] Added regression test for literal propagation and for scalar pair propagation --- .../const_prop/tuple_literal_propagation.rs | 11 ++++ .../32bit/rustc.main.ConstProp.diff | 56 +++++++++++++++++++ .../64bit/rustc.main.ConstProp.diff | 56 +++++++++++++++++++ .../const_prop/usize_literal_propagation.rs | 10 ++++ .../32bit/rustc.main.ConstProp.diff | 48 ++++++++++++++++ .../64bit/rustc.main.ConstProp.diff | 48 ++++++++++++++++ 6 files changed, 229 insertions(+) create mode 100644 src/test/mir-opt/const_prop/tuple_literal_propagation.rs create mode 100644 src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/usize_literal_propagation.rs create mode 100644 src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation.rs b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs new file mode 100644 index 0000000000000..58b3a45a09ec2 --- /dev/null +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation.rs @@ -0,0 +1,11 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let x = (1, 2); + + consume(x); +} + +#[inline(never)] +fn consume(_: (usize, usize)) { } diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff new file mode 100644 index 0000000000000..083b290eb82de --- /dev/null +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/tuple_literal_propagation.rs:4:11: 4:11 + let _1: (usize, usize); // in scope 0 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + let _2: (); // in scope 0 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + let mut _3: (usize, usize); // in scope 0 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + _1 = (const 1usize, const 2usize); // bb0[1]: scope 0 at $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000001)) + // mir::Constant +- // + span: $DIR/tuple_literal_propagation.rs:5:14: 5:15 ++ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000002)) + // mir::Constant +- // + span: $DIR/tuple_literal_propagation.rs:5:17: 5:18 ++ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } + StorageLive(_2); // bb0[2]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + StorageLive(_3); // bb0[3]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + // ty::Const + // + ty: fn((usize, usize)) {consume} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:7:5: 7:12 + // + literal: Const { ty: fn((usize, usize)) {consume}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // bb1[0]: scope 1 at $DIR/tuple_literal_propagation.rs:7:14: 7:15 + StorageDead(_2); // bb1[1]: scope 1 at $DIR/tuple_literal_propagation.rs:7:15: 7:16 + _0 = const (); // bb1[2]: scope 0 at $DIR/tuple_literal_propagation.rs:4:11: 8:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:4:11: 8:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb1[3]: scope 0 at $DIR/tuple_literal_propagation.rs:8:1: 8:2 + return; // bb1[4]: scope 0 at $DIR/tuple_literal_propagation.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff new file mode 100644 index 0000000000000..bc5c6d219dad8 --- /dev/null +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff @@ -0,0 +1,56 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/tuple_literal_propagation.rs:4:11: 4:11 + let _1: (usize, usize); // in scope 0 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + let _2: (); // in scope 0 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + let mut _3: (usize, usize); // in scope 0 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/tuple_literal_propagation.rs:5:9: 5:10 + _1 = (const 1usize, const 2usize); // bb0[1]: scope 0 at $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000001)) + // mir::Constant +- // + span: $DIR/tuple_literal_propagation.rs:5:14: 5:15 ++ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000002)) + // mir::Constant +- // + span: $DIR/tuple_literal_propagation.rs:5:17: 5:18 ++ // + span: $DIR/tuple_literal_propagation.rs:5:13: 5:19 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } + StorageLive(_2); // bb0[2]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + StorageLive(_3); // bb0[3]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 + _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 + // ty::Const + // + ty: fn((usize, usize)) {consume} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:7:5: 7:12 + // + literal: Const { ty: fn((usize, usize)) {consume}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // bb1[0]: scope 1 at $DIR/tuple_literal_propagation.rs:7:14: 7:15 + StorageDead(_2); // bb1[1]: scope 1 at $DIR/tuple_literal_propagation.rs:7:15: 7:16 + _0 = const (); // bb1[2]: scope 0 at $DIR/tuple_literal_propagation.rs:4:11: 8:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/tuple_literal_propagation.rs:4:11: 8:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb1[3]: scope 0 at $DIR/tuple_literal_propagation.rs:8:1: 8:2 + return; // bb1[4]: scope 0 at $DIR/tuple_literal_propagation.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation.rs b/src/test/mir-opt/const_prop/usize_literal_propagation.rs new file mode 100644 index 0000000000000..e79f8348827b1 --- /dev/null +++ b/src/test/mir-opt/const_prop/usize_literal_propagation.rs @@ -0,0 +1,10 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let x = 1; + consume(x); +} + +#[inline(never)] +fn consume(_: usize) { } diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff new file mode 100644 index 0000000000000..61c12404e84f9 --- /dev/null +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff @@ -0,0 +1,48 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/usize_literal_propagation.rs:4:11: 4:11 + let _1: usize; // in scope 0 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + let _2: (); // in scope 0 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + let mut _3: usize; // in scope 0 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + _1 = const 1usize; // bb0[1]: scope 0 at $DIR/usize_literal_propagation.rs:5:13: 5:14 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:5:13: 5:14 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } + StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + // ty::Const + // + ty: fn(usize) {consume} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:6:5: 6:12 + // + literal: Const { ty: fn(usize) {consume}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // bb1[0]: scope 1 at $DIR/usize_literal_propagation.rs:6:14: 6:15 + StorageDead(_2); // bb1[1]: scope 1 at $DIR/usize_literal_propagation.rs:6:15: 6:16 + _0 = const (); // bb1[2]: scope 0 at $DIR/usize_literal_propagation.rs:4:11: 7:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:4:11: 7:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb1[3]: scope 0 at $DIR/usize_literal_propagation.rs:7:1: 7:2 + return; // bb1[4]: scope 0 at $DIR/usize_literal_propagation.rs:7:2: 7:2 + } + } + diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff new file mode 100644 index 0000000000000..96a230c8ddc0e --- /dev/null +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff @@ -0,0 +1,48 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/usize_literal_propagation.rs:4:11: 4:11 + let _1: usize; // in scope 0 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + let _2: (); // in scope 0 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + let mut _3: usize; // in scope 0 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/usize_literal_propagation.rs:5:9: 5:10 + _1 = const 1usize; // bb0[1]: scope 0 at $DIR/usize_literal_propagation.rs:5:13: 5:14 + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000001)) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:5:13: 5:14 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } + StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 + _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + // ty::Const + // + ty: fn(usize) {consume} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:6:5: 6:12 + // + literal: Const { ty: fn(usize) {consume}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // bb1[0]: scope 1 at $DIR/usize_literal_propagation.rs:6:14: 6:15 + StorageDead(_2); // bb1[1]: scope 1 at $DIR/usize_literal_propagation.rs:6:15: 6:16 + _0 = const (); // bb1[2]: scope 0 at $DIR/usize_literal_propagation.rs:4:11: 7:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:4:11: 7:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb1[3]: scope 0 at $DIR/usize_literal_propagation.rs:7:1: 7:2 + return; // bb1[4]: scope 0 at $DIR/usize_literal_propagation.rs:7:2: 7:2 + } + } + From faa3fbbeea202c09d10e7d2db75736f2e4cbcbe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Wed, 22 Apr 2020 21:53:51 -0400 Subject: [PATCH 2/7] Blocked `MutatingUseContext::Projection` for all locals of kind `LocalKind::Temp`. Added a cache of `LocalKind`s to `CanConstProp` --- src/librustc_mir/transform/const_prop.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 271c746aa0fef..b272c0c35fd6e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -777,6 +777,8 @@ struct CanConstProp { can_const_prop: IndexVec, // false at the beginning, once set, there are not allowed to be any more assignments found_assignment: BitSet, + // Cache of locals' information + local_kinds: IndexVec, } impl CanConstProp { @@ -785,6 +787,10 @@ impl CanConstProp { let mut cpv = CanConstProp { can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls), found_assignment: BitSet::new_empty(body.local_decls.len()), + local_kinds: IndexVec::from_fn_n( + |local| body.local_kind(local), + body.local_decls.len(), + ), }; for (local, val) in cpv.can_const_prop.iter_enumerated_mut() { // cannot use args at all @@ -792,9 +798,8 @@ impl CanConstProp { // lint for x != y // FIXME(oli-obk): lint variables until they are used in a condition // FIXME(oli-obk): lint if return value is constant - let local_kind = body.local_kind(local); - - if local_kind == LocalKind::Arg || local_kind == LocalKind::Var { + if cpv.local_kinds[local] == LocalKind::Arg || cpv.local_kinds[local] == LocalKind::Var + { *val = ConstPropMode::OnlyPropagateInto; trace!("local {:?} can't be const propagated because it's not a temporary", local); } @@ -822,8 +827,12 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { | NonMutatingUse(NonMutatingUseContext::Move) | NonMutatingUse(NonMutatingUseContext::Inspect) | NonMutatingUse(NonMutatingUseContext::Projection) - | MutatingUse(MutatingUseContext::Projection) | NonUse(_) => {} + MutatingUse(MutatingUseContext::Projection) => { + if self.local_kinds[local] != LocalKind::Temp { + self.can_const_prop[local] = ConstPropMode::NoPropagation; + } + } _ => { trace!("local {:?} can't be propagaged because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; From e541d817b3d43357e2e747d40cfc4170318b8052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Thu, 23 Apr 2020 12:25:28 -0400 Subject: [PATCH 3/7] Allow Locals to be propagated into and from, but restricted to their own block --- src/librustc_mir/transform/const_prop.rs | 54 +++++++++++--- .../32bit/rustc.main.ConstProp.diff | 15 +++- .../64bit/rustc.main.ConstProp.diff | 15 +++- .../32bit/rustc.main.ConstProp.diff | 9 ++- .../64bit/rustc.main.ConstProp.diff | 9 ++- src/test/mir-opt/simplify-arm-identity.rs | 1 + .../32bit/rustc.main.SimplifyArmIdentity.diff | 53 ++++++++++++++ .../64bit/rustc.main.SimplifyArmIdentity.diff | 53 ++++++++++++++ .../rustc.main.SimplifyArmIdentity.diff | 71 ------------------- ...main.SimplifyBranches-after-copy-prop.diff | 33 +++++---- src/test/run-fail/divide-by-zero.rs | 2 +- src/test/run-fail/dst-raw-slice.rs | 2 +- src/test/run-fail/mod-zero.rs | 2 +- 13 files changed, 218 insertions(+), 101 deletions(-) create mode 100644 src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff create mode 100644 src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff delete mode 100644 src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b272c0c35fd6e..0b174a8e8475b 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -334,6 +334,8 @@ struct ConstPropagator<'mir, 'tcx> { // Because we have `MutVisitor` we can't obtain the `SourceInfo` from a `Location`. So we store // the last known `SourceInfo` here and just keep revisiting it. source_info: Option, + // Locals we need to forget at the end of the current block + locals_of_current_block: BitSet, } impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> { @@ -404,6 +406,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { local_decls: body.local_decls.clone(), ret: ret.map(Into::into), source_info: None, + locals_of_current_block: BitSet::new_empty(body.local_decls.len()), } } @@ -767,6 +770,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { enum ConstPropMode { /// The `Local` can be propagated into and reads of this `Local` can also be propagated. FullConstProp, + /// The `Local` can only be propagated into and from its own block. + OnlyInsideOwnBlock, /// The `Local` can be propagated into but reads cannot be propagated. OnlyPropagateInto, /// No propagation is allowed at all. @@ -798,10 +803,18 @@ impl CanConstProp { // lint for x != y // FIXME(oli-obk): lint variables until they are used in a condition // FIXME(oli-obk): lint if return value is constant - if cpv.local_kinds[local] == LocalKind::Arg || cpv.local_kinds[local] == LocalKind::Var - { + if cpv.local_kinds[local] == LocalKind::Arg { *val = ConstPropMode::OnlyPropagateInto; - trace!("local {:?} can't be const propagated because it's not a temporary", local); + trace!( + "local {:?} can't be const propagated because it's a function argument", + local + ); + } else if cpv.local_kinds[local] == LocalKind::Var { + *val = ConstPropMode::OnlyInsideOwnBlock; + trace!( + "local {:?} will only be propagated inside its block, because it's a user variable", + local + ); } } cpv.visit_body(&body); @@ -863,22 +876,32 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if let Some(local) = place.as_local() { let can_const_prop = self.can_const_prop[local]; if let Some(()) = self.const_prop(rval, place_layout, source_info, place) { - if can_const_prop == ConstPropMode::FullConstProp - || can_const_prop == ConstPropMode::OnlyPropagateInto - { + if can_const_prop != ConstPropMode::NoPropagation { + // This will return None for Locals that are from other blocks, + // so it should be okay to propagate from here on down. if let Some(value) = self.get_const(local) { if self.should_const_prop(value) { trace!("replacing {:?} with {:?}", rval, value); self.replace_with_const(rval, value, statement.source_info); - - if can_const_prop == ConstPropMode::FullConstProp { + if can_const_prop == ConstPropMode::FullConstProp + || can_const_prop == ConstPropMode::OnlyInsideOwnBlock + { trace!("propagated into {:?}", local); } } + if can_const_prop == ConstPropMode::OnlyInsideOwnBlock { + trace!( + "found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}", + local + ); + self.locals_of_current_block.insert(local); + } } } } - if self.can_const_prop[local] != ConstPropMode::FullConstProp { + if self.can_const_prop[local] == ConstPropMode::OnlyPropagateInto + || self.can_const_prop[local] == ConstPropMode::NoPropagation + { trace!("can't propagate into {:?}", local); if local != RETURN_PLACE { self.remove_const(local); @@ -997,5 +1020,18 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { //FIXME(wesleywiser) Call does have Operands that could be const-propagated TerminatorKind::Call { .. } => {} } + // We remove all Locals which are restricted in propagation to their containing blocks. + // We wouldn't need to clone, but the borrow checker can't see that we're not aliasing + // the locals_of_current_block field, so we need to clone it first. + for local in self.locals_of_current_block.clone().iter() { + trace!( + "removing local {:?} from const-prop, since it's restricted to just its own block.", + local + ); + self.remove_const(local); + } + // Before moving on to the next block, we must forget all restricted locals, because we + // have already removed them from the `const` pool + self.locals_of_current_block.clear(); } } diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff index 083b290eb82de..4de769b44b403 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation/32bit/rustc.main.ConstProp.diff @@ -29,7 +29,20 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } StorageLive(_2); // bb0[2]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 +- _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ _3 = (const 1usize, const 2usize); // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000001)) ++ // mir::Constant ++ // + span: $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000002)) ++ // mir::Constant ++ // + span: $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000002)) } _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 // ty::Const // + ty: fn((usize, usize)) {consume} diff --git a/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff index bc5c6d219dad8..9203aefcc6f47 100644 --- a/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/tuple_literal_propagation/64bit/rustc.main.ConstProp.diff @@ -29,7 +29,20 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } StorageLive(_2); // bb0[2]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 +- _3 = _1; // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ _3 = (const 1usize, const 2usize); // bb0[4]: scope 1 at $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000001)) ++ // mir::Constant ++ // + span: $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000002)) ++ // mir::Constant ++ // + span: $DIR/tuple_literal_propagation.rs:7:13: 7:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000002)) } _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/tuple_literal_propagation.rs:7:5: 7:15 // ty::Const // + ty: fn((usize, usize)) {consume} diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff index 61c12404e84f9..133d50c2b4b9b 100644 --- a/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff @@ -21,7 +21,14 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 +- _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ _3 = const 1usize; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000001)) ++ // mir::Constant ++ // + span: $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 // ty::Const // + ty: fn(usize) {consume} diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff index 96a230c8ddc0e..2d0f2cb5b3bf6 100644 --- a/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff @@ -21,7 +21,14 @@ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 +- _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ _3 = const 1usize; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000001)) ++ // mir::Constant ++ // + span: $DIR/usize_literal_propagation.rs:6:13: 6:14 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 // ty::Const // + ty: fn(usize) {consume} diff --git a/src/test/mir-opt/simplify-arm-identity.rs b/src/test/mir-opt/simplify-arm-identity.rs index cc6aab7523f00..24e91b3ff611c 100644 --- a/src/test/mir-opt/simplify-arm-identity.rs +++ b/src/test/mir-opt/simplify-arm-identity.rs @@ -2,6 +2,7 @@ // Regression test for issue #66856. // // compile-flags: -Zmir-opt-level=2 +// EMIT_MIR_FOR_EACH_BIT_WIDTH enum Src { Foo(u8), diff --git a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff new file mode 100644 index 0000000000000..305fda61cce48 --- /dev/null +++ b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before SimplifyArmIdentity ++ // MIR for `main` after SimplifyArmIdentity + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:17:11: 17:11 + let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + scope 1 { + debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + scope 2 { + } + scope 3 { + debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + } + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + ((_1 as Foo).0: u8) = const 0u8; // bb0[1]: scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29 + // ty::Const + // + ty: u8 + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:18:27: 18:28 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_1) = 0; // bb0[2]: scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29 + StorageLive(_2); // bb0[3]: scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + _3 = const 0isize; // bb0[4]: scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x00000000)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:20:9: 20:20 + // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) } + _4 = ((_1 as Foo).0: u8); // bb0[5]: scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + ((_2 as Foo).0: u8) = move _4; // bb0[6]: scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + discriminant(_2) = 0; // bb0[7]: scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageDead(_2); // bb0[8]: scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 + _0 = const (); // bb0[9]: scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:17:11: 23:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb0[10]: scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2 + return; // bb0[11]: scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff new file mode 100644 index 0000000000000..de51248e1fbc8 --- /dev/null +++ b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before SimplifyArmIdentity ++ // MIR for `main` after SimplifyArmIdentity + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:17:11: 17:11 + let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + scope 1 { + debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + scope 2 { + } + scope 3 { + debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + } + } + + bb0: { + StorageLive(_1); // bb0[0]: scope 0 at $DIR/simplify-arm-identity.rs:18:9: 18:10 + ((_1 as Foo).0: u8) = const 0u8; // bb0[1]: scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29 + // ty::Const + // + ty: u8 + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:18:27: 18:28 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_1) = 0; // bb0[2]: scope 0 at $DIR/simplify-arm-identity.rs:18:18: 18:29 + StorageLive(_2); // bb0[3]: scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + _3 = const 0isize; // bb0[4]: scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + // ty::Const + // + ty: isize + // + val: Value(Scalar(0x0000000000000000)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:20:9: 20:20 + // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) } + _4 = ((_1 as Foo).0: u8); // bb0[5]: scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 + ((_2 as Foo).0: u8) = move _4; // bb0[6]: scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + discriminant(_2) = 0; // bb0[7]: scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageDead(_2); // bb0[8]: scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 + _0 = const (); // bb0[9]: scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:17:11: 23:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_1); // bb0[10]: scope 0 at $DIR/simplify-arm-identity.rs:23:1: 23:2 + return; // bb0[11]: scope 0 at $DIR/simplify-arm-identity.rs:23:2: 23:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff deleted file mode 100644 index 2caa6235d54c0..0000000000000 --- a/src/test/mir-opt/simplify-arm-identity/rustc.main.SimplifyArmIdentity.diff +++ /dev/null @@ -1,71 +0,0 @@ -- // MIR for `main` before SimplifyArmIdentity -+ // MIR for `main` after SimplifyArmIdentity - - fn main() -> () { - let mut _0: (); // return place in scope 0 at $DIR/simplify-arm-identity.rs:16:11: 16:11 - let _1: Src as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/simplify-arm-identity.rs:17:9: 17:10 - let mut _2: Dst; // in scope 0 at $DIR/simplify-arm-identity.rs:18:18: 21:6 - let mut _3: isize; // in scope 0 at $DIR/simplify-arm-identity.rs:19:9: 19:20 - let mut _5: u8; // in scope 0 at $DIR/simplify-arm-identity.rs:19:33: 19:34 - scope 1 { - debug e => _1; // in scope 1 at $DIR/simplify-arm-identity.rs:17:9: 17:10 - let _4: u8; // in scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:19 - scope 2 { - } - scope 3 { - debug x => _4; // in scope 3 at $DIR/simplify-arm-identity.rs:19:18: 19:19 - } - } - - bb0: { - StorageLive(_1); // bb0[0]: scope 0 at $DIR/simplify-arm-identity.rs:17:9: 17:10 - ((_1 as Foo).0: u8) = const 0u8; // bb0[1]: scope 0 at $DIR/simplify-arm-identity.rs:17:18: 17:29 - // ty::Const - // + ty: u8 - // + val: Value(Scalar(0x00)) - // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:17:27: 17:28 - // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } - discriminant(_1) = 0; // bb0[2]: scope 0 at $DIR/simplify-arm-identity.rs:17:18: 17:29 - StorageLive(_2); // bb0[3]: scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6 - _3 = discriminant(_1); // bb0[4]: scope 1 at $DIR/simplify-arm-identity.rs:19:9: 19:20 - switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // bb0[5]: scope 1 at $DIR/simplify-arm-identity.rs:19:9: 19:20 - } - - bb1: { - ((_2 as Foo).0: u8) = const 0u8; // bb1[0]: scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32 - // ty::Const - // + ty: u8 - // + val: Value(Scalar(0x00)) - // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:20:30: 20:31 - // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } - discriminant(_2) = 0; // bb1[1]: scope 1 at $DIR/simplify-arm-identity.rs:20:21: 20:32 - goto -> bb4; // bb1[2]: scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6 - } - - bb2: { - unreachable; // bb2[0]: scope 1 at $DIR/simplify-arm-identity.rs:18:24: 18:25 - } - - bb3: { - _4 = ((_1 as Foo).0: u8); // bb3[0]: scope 1 at $DIR/simplify-arm-identity.rs:19:18: 19:19 - ((_2 as Foo).0: u8) = move _4; // bb3[1]: scope 3 at $DIR/simplify-arm-identity.rs:19:24: 19:35 - discriminant(_2) = 0; // bb3[2]: scope 3 at $DIR/simplify-arm-identity.rs:19:24: 19:35 - goto -> bb4; // bb3[3]: scope 1 at $DIR/simplify-arm-identity.rs:18:18: 21:6 - } - - bb4: { - StorageDead(_2); // bb4[0]: scope 1 at $DIR/simplify-arm-identity.rs:21:6: 21:7 - _0 = const (); // bb4[1]: scope 0 at $DIR/simplify-arm-identity.rs:16:11: 22:2 - // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/simplify-arm-identity.rs:16:11: 22:2 - // + literal: Const { ty: (), val: Value(Scalar()) } - StorageDead(_1); // bb4[2]: scope 0 at $DIR/simplify-arm-identity.rs:22:1: 22:2 - return; // bb4[3]: scope 0 at $DIR/simplify-arm-identity.rs:22:2: 22:2 - } - } - diff --git a/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff b/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff index 1c83bb13425de..9b87763060194 100644 --- a/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff +++ b/src/test/mir-opt/simplify_match/rustc.main.SimplifyBranches-after-copy-prop.diff @@ -10,19 +10,24 @@ } bb0: { - nop; // bb0[0]: scope 0 at $DIR/simplify_match.rs:6:11: 6:31 - nop; // bb0[1]: scope 0 at $DIR/simplify_match.rs:6:17: 6:18 - nop; // bb0[2]: scope 0 at $DIR/simplify_match.rs:6:21: 6:26 - nop; // bb0[3]: scope 1 at $DIR/simplify_match.rs:6:28: 6:29 - nop; // bb0[4]: scope 0 at $DIR/simplify_match.rs:6:30: 6:31 -- switchInt(const false) -> [false: bb1, otherwise: bb2]; // bb0[5]: scope 0 at $DIR/simplify_match.rs:7:9: 7:13 -- // ty::Const -- // + ty: bool -- // + val: Value(Scalar(0x00)) -- // mir::Constant -- // + span: $DIR/simplify_match.rs:6:21: 6:26 -- // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } -+ goto -> bb1; // bb0[5]: scope 0 at $DIR/simplify_match.rs:7:9: 7:13 + StorageLive(_1); // bb0[0]: scope 0 at $DIR/simplify_match.rs:6:11: 6:31 + StorageLive(_2); // bb0[1]: scope 0 at $DIR/simplify_match.rs:6:17: 6:18 + _2 = const false; // bb0[2]: scope 0 at $DIR/simplify_match.rs:6:21: 6:26 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify_match.rs:6:21: 6:26 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + _1 = const false; // bb0[3]: scope 1 at $DIR/simplify_match.rs:6:28: 6:29 + // ty::Const + // + ty: bool + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify_match.rs:6:28: 6:29 + // + literal: Const { ty: bool, val: Value(Scalar(0x00)) } + StorageDead(_2); // bb0[4]: scope 0 at $DIR/simplify_match.rs:6:30: 6:31 + goto -> bb1; // bb0[5]: scope 0 at $DIR/simplify_match.rs:7:9: 7:13 } bb1: { @@ -47,7 +52,7 @@ } bb3: { - nop; // bb3[0]: scope 0 at $DIR/simplify_match.rs:10:1: 10:2 + StorageDead(_1); // bb3[0]: scope 0 at $DIR/simplify_match.rs:10:1: 10:2 return; // bb3[1]: scope 0 at $DIR/simplify_match.rs:10:2: 10:2 } } diff --git a/src/test/run-fail/divide-by-zero.rs b/src/test/run-fail/divide-by-zero.rs index fdb3f4842e50a..ba93563154a3b 100644 --- a/src/test/run-fail/divide-by-zero.rs +++ b/src/test/run-fail/divide-by-zero.rs @@ -1,5 +1,5 @@ // error-pattern:attempt to divide by zero - +#[allow(unconditional_panic)] fn main() { let y = 0; let _z = 1 / y; diff --git a/src/test/run-fail/dst-raw-slice.rs b/src/test/run-fail/dst-raw-slice.rs index 561b1fb42ed06..2575de7cc5833 100644 --- a/src/test/run-fail/dst-raw-slice.rs +++ b/src/test/run-fail/dst-raw-slice.rs @@ -1,6 +1,6 @@ // Test bounds checking for DST raw slices // error-pattern:index out of bounds - +#[allow(unconditional_panic)] fn main() { let a: *const [_] = &[1, 2, 3]; unsafe { diff --git a/src/test/run-fail/mod-zero.rs b/src/test/run-fail/mod-zero.rs index ac2959fcd3853..f70b3ac920c61 100644 --- a/src/test/run-fail/mod-zero.rs +++ b/src/test/run-fail/mod-zero.rs @@ -1,5 +1,5 @@ // error-pattern:attempt to calculate the remainder with a divisor of zero - +#[allow(unconditional_panic)] fn main() { let y = 0; let _z = 1 % y; From f64a0e41488c9380ff0a0384e56f1d059e13fb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Thu, 23 Apr 2020 12:35:36 -0400 Subject: [PATCH 4/7] Allow constant propagation into function call arguments --- src/librustc_mir/transform/const_prop.rs | 36 ++++++++++- .../switch_int/rustc.main.ConstProp.diff | 6 +- ...ain.SimplifyBranches-after-const-prop.diff | 4 +- .../32bit/rustc.main.ConstProp.diff | 13 +++- .../64bit/rustc.main.ConstProp.diff | 13 +++- .../rustc.main.SimplifyLocals.diff | 60 ++++++++++++------- 6 files changed, 99 insertions(+), 33 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0b174a8e8475b..6a8a23748e4fb 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1017,8 +1017,40 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => {} - //FIXME(wesleywiser) Call does have Operands that could be const-propagated - TerminatorKind::Call { .. } => {} + TerminatorKind::Call { ref mut args, .. } => { + // Every argument in our function calls can be const propagated. + // We try to, before exiting. + for opr in args { + // We see if the operand can be evaluated, and if so, we continue. + if let Some(op_ty) = self.eval_operand(&opr, source_info) { + trace!("OpTy of the place: {:?}", &op_ty); + // We must also ask if it *should* be evaluated. + if self.should_const_prop(op_ty) { + if let interpret::Operand::Immediate(immediate) = *op_ty { + // Only Immediate from here on + // FIXME(felix91gr): The code only works for Immediate. Investigate + // if it could be made to work for Indirect as well. + trace!("Immediate of the OpTy: {:?}", &immediate); + if let interpret::Immediate::Scalar(scalar_mu) = immediate { + // FIXME(felix91gr): This only works for Scalar + // Could probably be expanded for Scalar Tuples (inside the Immediate) + trace!("ScalarMaybeUndef of the OpTy: {:?}", &scalar_mu); + if let ScalarMaybeUndef::Scalar(scalar) = scalar_mu { + trace!("Scalar of the ScalarMU: {:?}", &scalar); + let operand_type = opr.ty(&self.local_decls, self.tcx); + trace!("Type of the OpTy: {:?}", &operand_type); + *opr = self.operand_from_scalar( + scalar, + operand_type, + source_info.span, + ); + } + } + } + } + } + } + } } // We remove all Locals which are restricted in propagation to their containing blocks. // We wouldn't need to clone, but the borrow checker can't see that we're not aliasing diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff index 92b14309bf2b7..9853acd9e780b 100644 --- a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff @@ -36,7 +36,8 @@ // + ty: i32 // + val: Value(Scalar(0xffffffff)) // mir::Constant - // + span: $DIR/switch_int.rs:9:18: 9:20 +- // + span: $DIR/switch_int.rs:9:18: 9:20 ++ // + span: $DIR/switch_int.rs:9:14: 9:21 // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) } } @@ -52,7 +53,8 @@ // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant - // + span: $DIR/switch_int.rs:8:18: 8:19 +- // + span: $DIR/switch_int.rs:8:18: 8:19 ++ // + span: $DIR/switch_int.rs:8:14: 8:20 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } } diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff index e1805cc57311d..5a9fc5ce01e0f 100644 --- a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff @@ -36,7 +36,7 @@ // + ty: i32 // + val: Value(Scalar(0xffffffff)) // mir::Constant - // + span: $DIR/switch_int.rs:9:18: 9:20 + // + span: $DIR/switch_int.rs:9:14: 9:21 // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) } } @@ -52,7 +52,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant - // + span: $DIR/switch_int.rs:8:18: 8:19 + // + span: $DIR/switch_int.rs:8:14: 8:20 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } } diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff index 133d50c2b4b9b..52b260ed2ee4d 100644 --- a/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/32bit/rustc.main.ConstProp.diff @@ -22,20 +22,27 @@ StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 +- _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + _3 = const 1usize; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 -+ // ty::Const + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x00000001)) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:6:13: 6:14 + // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } - _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 - // ty::Const ++ _2 = const consume(const 1usize) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 ++ // ty::Const // + ty: fn(usize) {consume} // + val: Value(Scalar()) // mir::Constant // + span: $DIR/usize_literal_propagation.rs:6:5: 6:12 // + literal: Const { ty: fn(usize) {consume}, val: Value(Scalar()) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x00000001)) ++ // mir::Constant ++ // + span: $DIR/usize_literal_propagation.rs:6:5: 6:15 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x00000001)) } } bb1: { diff --git a/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff index 2d0f2cb5b3bf6..60c8e8b8aa8cd 100644 --- a/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/usize_literal_propagation/64bit/rustc.main.ConstProp.diff @@ -22,20 +22,27 @@ StorageLive(_2); // bb0[2]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 StorageLive(_3); // bb0[3]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 - _3 = _1; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 +- _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 + _3 = const 1usize; // bb0[4]: scope 1 at $DIR/usize_literal_propagation.rs:6:13: 6:14 -+ // ty::Const + // ty::Const + // + ty: usize + // + val: Value(Scalar(0x0000000000000001)) + // mir::Constant + // + span: $DIR/usize_literal_propagation.rs:6:13: 6:14 + // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } - _2 = const consume(move _3) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 - // ty::Const ++ _2 = const consume(const 1usize) -> bb1; // bb0[5]: scope 1 at $DIR/usize_literal_propagation.rs:6:5: 6:15 ++ // ty::Const // + ty: fn(usize) {consume} // + val: Value(Scalar()) // mir::Constant // + span: $DIR/usize_literal_propagation.rs:6:5: 6:12 // + literal: Const { ty: fn(usize) {consume}, val: Value(Scalar()) } ++ // ty::Const ++ // + ty: usize ++ // + val: Value(Scalar(0x0000000000000001)) ++ // mir::Constant ++ // + span: $DIR/usize_literal_propagation.rs:6:5: 6:15 ++ // + literal: Const { ty: usize, val: Value(Scalar(0x0000000000000001)) } } bb1: { diff --git a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff index 855ead7ea0554..84532a731ab55 100644 --- a/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff +++ b/src/test/mir-opt/simplify-locals-removes-unused-consts/rustc.main.SimplifyLocals.diff @@ -50,25 +50,33 @@ - StorageDead(_2); // bb0[7]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:27: 13:28 - StorageDead(_1); // bb0[8]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:13:28: 13:29 - StorageLive(_4); // bb0[9]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 -- StorageLive(_6); // bb0[10]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 -- _6 = const (); // bb0[11]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 +- StorageLive(_5); // bb0[10]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 +- StorageLive(_6); // bb0[11]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 +- _6 = const (); // bb0[12]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 - // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:14: 14:16 - // + literal: Const { ty: (), val: Value(Scalar()) } -- StorageLive(_7); // bb0[12]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 -- _7 = const (); // bb0[13]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 +- StorageLive(_7); // bb0[13]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 +- _7 = const (); // bb0[14]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 - // ty::Const - // + ty: () - // + val: Value(Scalar()) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:18: 14:20 - // + literal: Const { ty: (), val: Value(Scalar()) } -- StorageDead(_7); // bb0[14]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 -- StorageDead(_6); // bb0[15]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 -- _4 = const use_zst(const ((), ())) -> bb1; // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 +- _5 = const ((), ()); // bb0[15]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 +- // ty::Const +- // + ty: ((), ()) +- // + val: Value(Scalar()) +- // mir::Constant +- // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 +- // + literal: Const { ty: ((), ()), val: Value(Scalar()) } +- StorageDead(_7); // bb0[16]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 +- StorageDead(_6); // bb0[17]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:20: 14:21 +- _4 = const use_zst(const ((), ())) -> bb1; // bb0[18]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 - // ty::Const // + ty: fn(((), ())) {use_zst} // + val: Value(Scalar()) @@ -79,16 +87,18 @@ // + ty: ((), ()) // + val: Value(Scalar()) // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:13: 14:21 + // + span: $DIR/simplify-locals-removes-unused-consts.rs:14:5: 14:22 // + literal: Const { ty: ((), ()), val: Value(Scalar()) } } bb1: { -- StorageDead(_4); // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23 -- StorageLive(_8); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 -- StorageLive(_10); // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 -- StorageLive(_11); // bb1[3]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 -- _11 = const Temp { x: 40u8 }; // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 +- StorageDead(_5); // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:21: 14:22 +- StorageDead(_4); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23 +- StorageLive(_8); // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 +- StorageLive(_9); // bb1[3]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 +- StorageLive(_10); // bb1[4]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 +- StorageLive(_11); // bb1[5]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 +- _11 = const Temp { x: 40u8 }; // bb1[6]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 + StorageDead(_1); // bb1[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:14:22: 14:23 + StorageLive(_2); // bb1[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 + _2 = const use_u8(const 42u8) -> bb2; // bb1[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 @@ -98,15 +108,22 @@ - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:28 - // + literal: Const { ty: Temp, val: Value(Scalar(0x28)) } -- _10 = const 40u8; // bb1[5]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 +- _10 = const 40u8; // bb1[7]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - // ty::Const - // + ty: u8 - // + val: Value(Scalar(0x28)) - // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:30 - // + literal: Const { ty: u8, val: Value(Scalar(0x28)) } -- StorageDead(_10); // bb1[6]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:33: 16:34 -- _8 = const use_u8(const 42u8) -> bb2; // bb1[7]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 +- _9 = const 42u8; // bb1[8]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 +- // ty::Const +- // + ty: u8 +- // + val: Value(Scalar(0x2a)) +- // mir::Constant +- // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 +- // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) } +- StorageDead(_10); // bb1[9]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:33: 16:34 +- _8 = const use_u8(const 42u8) -> bb2; // bb1[10]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 - // ty::Const // + ty: fn(u8) {use_u8} // + val: Value(Scalar()) @@ -117,14 +134,15 @@ // + ty: u8 // + val: Value(Scalar(0x2a)) // mir::Constant - // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:12: 16:34 + // + span: $DIR/simplify-locals-removes-unused-consts.rs:16:5: 16:35 // + literal: Const { ty: u8, val: Value(Scalar(0x2a)) } } bb2: { -- StorageDead(_11); // bb2[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 -- StorageDead(_8); // bb2[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 -- _0 = const (); // bb2[2]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:12:11: 17:2 +- StorageDead(_9); // bb2[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:34: 16:35 +- StorageDead(_11); // bb2[1]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 +- StorageDead(_8); // bb2[2]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 +- _0 = const (); // bb2[3]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:12:11: 17:2 + StorageDead(_2); // bb2[0]: scope 1 at $DIR/simplify-locals-removes-unused-consts.rs:16:35: 16:36 + _0 = const (); // bb2[1]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:12:11: 17:2 // ty::Const @@ -133,7 +151,7 @@ // mir::Constant // + span: $DIR/simplify-locals-removes-unused-consts.rs:12:11: 17:2 // + literal: Const { ty: (), val: Value(Scalar()) } -- return; // bb2[3]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:17:2: 17:2 +- return; // bb2[4]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:17:2: 17:2 + return; // bb2[2]: scope 0 at $DIR/simplify-locals-removes-unused-consts.rs:17:2: 17:2 } } From 45f1775988989996b1512f289953ec82888e09fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Wed, 22 Apr 2020 22:43:52 -0400 Subject: [PATCH 5/7] Polished documentation, removed not-so-useful-anymore traces, and added some doc comments in `mir/transform/const_prop.rs` --- src/librustc_mir/transform/const_prop.rs | 26 ++++++++++++++---------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 6a8a23748e4fb..a222abe9d3446 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -423,6 +423,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { self.ecx.access_local(self.ecx.frame(), local, None).ok() } + /// Remove `local` from the pool of `Locals`. Allows writing to them, + /// but not reading from them anymore. fn remove_const(&mut self, local: Local) { self.ecx.frame_mut().locals[local] = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) }; @@ -455,6 +457,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } + /// Returns the value, if any, of evaluating `c`. fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option> { // FIXME we need to revisit this for #67176 if c.needs_subst() { @@ -495,11 +498,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } + /// Returns the value, if any, of evaluating `place`. fn eval_place(&mut self, place: Place<'tcx>) -> Option> { trace!("eval_place(place={:?})", place); self.use_ecx(|this| this.ecx.eval_place_to_op(place, None)) } + /// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant` + /// or `eval_place`, depending on the variant of `Operand` used. fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { match *op { Operand::Constant(ref c) => self.eval_constant(c, source_info), @@ -658,6 +664,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { }) } + /// Creates a new `Operand::Constant` from a `Scalar` value fn operand_from_scalar(&self, scalar: Scalar, ty: Ty<'tcx>, span: Span) -> Operand<'tcx> { Operand::Constant(Box::new(Constant { span, @@ -703,6 +710,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Found a value represented as a pair. For now only do cont-prop if type of // Rvalue is also a pair with two scalars. The more general case is more // complicated to implement so we'll do it later. + // FIXME: implement the general case stated above ^. let ty = &value.layout.ty.kind; // Only do it for tuples if let ty::Tuple(substs) = ty { @@ -739,6 +747,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } + /// Returns `true` if and only if this `op` should be const-propagated into. fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool { let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level; @@ -780,14 +789,14 @@ enum ConstPropMode { struct CanConstProp { can_const_prop: IndexVec, - // false at the beginning, once set, there are not allowed to be any more assignments + // False at the beginning. Once set, no more assignments are allowed to that local. found_assignment: BitSet, // Cache of locals' information local_kinds: IndexVec, } impl CanConstProp { - /// returns true if `local` can be propagated + /// Returns true if `local` can be propagated fn check(body: &Body<'_>) -> IndexVec { let mut cpv = CanConstProp { can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp, &body.local_decls), @@ -798,8 +807,8 @@ impl CanConstProp { ), }; for (local, val) in cpv.can_const_prop.iter_enumerated_mut() { - // cannot use args at all - // cannot use locals because if x < y { y - x } else { x - y } would + // Cannot use args at all + // Cannot use locals because if x < y { y - x } else { x - y } would // lint for x != y // FIXME(oli-obk): lint variables until they are used in a condition // FIXME(oli-obk): lint if return value is constant @@ -939,7 +948,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected)); let value_const = self.ecx.read_scalar(value).unwrap(); if expected != value_const { - // poison all places this operand references so that further code + // Poison all places this operand references so that further code // doesn't use the invalid value match cond { Operand::Move(ref place) | Operand::Copy(ref place) => { @@ -1005,7 +1014,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } } } - //none of these have Operands to const-propagate + // None of these have Operands to const-propagate TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort @@ -1023,22 +1032,17 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { for opr in args { // We see if the operand can be evaluated, and if so, we continue. if let Some(op_ty) = self.eval_operand(&opr, source_info) { - trace!("OpTy of the place: {:?}", &op_ty); // We must also ask if it *should* be evaluated. if self.should_const_prop(op_ty) { if let interpret::Operand::Immediate(immediate) = *op_ty { // Only Immediate from here on // FIXME(felix91gr): The code only works for Immediate. Investigate // if it could be made to work for Indirect as well. - trace!("Immediate of the OpTy: {:?}", &immediate); if let interpret::Immediate::Scalar(scalar_mu) = immediate { // FIXME(felix91gr): This only works for Scalar // Could probably be expanded for Scalar Tuples (inside the Immediate) - trace!("ScalarMaybeUndef of the OpTy: {:?}", &scalar_mu); if let ScalarMaybeUndef::Scalar(scalar) = scalar_mu { - trace!("Scalar of the ScalarMU: {:?}", &scalar); let operand_type = opr.ty(&self.local_decls, self.tcx); - trace!("Type of the OpTy: {:?}", &operand_type); *opr = self.operand_from_scalar( scalar, operand_type, From 8a8c8c9b715c2f178860d3a09996fe8bf35c3544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Sat, 25 Apr 2020 21:48:22 -0400 Subject: [PATCH 6/7] Remove unnecessary `.clone()`, by making `remove_const` not alias with `locals_of_current_block` --- src/librustc_mir/transform/const_prop.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a222abe9d3446..ae1fa90bfe3fe 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -425,8 +425,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { /// Remove `local` from the pool of `Locals`. Allows writing to them, /// but not reading from them anymore. - fn remove_const(&mut self, local: Local) { - self.ecx.frame_mut().locals[local] = + fn remove_const(ecx: &mut InterpCx<'mir, 'tcx, ConstPropMachine<'mir, 'tcx>>, local: Local) { + ecx.frame_mut().locals[local] = LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) }; } @@ -913,7 +913,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { { trace!("can't propagate into {:?}", local); if local != RETURN_PLACE { - self.remove_const(local); + Self::remove_const(&mut self.ecx, local); } } } @@ -952,7 +952,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // doesn't use the invalid value match cond { Operand::Move(ref place) | Operand::Copy(ref place) => { - self.remove_const(place.local); + Self::remove_const(&mut self.ecx, place.local); } Operand::Constant(_) => {} } @@ -1064,7 +1064,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { "removing local {:?} from const-prop, since it's restricted to just its own block.", local ); - self.remove_const(local); + Self::remove_const(&mut self.ecx, local); } // Before moving on to the next block, we must forget all restricted locals, because we // have already removed them from the `const` pool From 6e586b8ea57fd1ff57c63876da2980e6dc11d166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Fischer?= Date: Sat, 25 Apr 2020 22:00:29 -0400 Subject: [PATCH 7/7] Simplify fn call const propagation (by wesleywiser) --- src/librustc_mir/transform/const_prop.rs | 32 ++++++++----------- .../switch_int/rustc.main.ConstProp.diff | 6 ++-- ...ain.SimplifyBranches-after-const-prop.diff | 4 +-- 3 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ae1fa90bfe3fe..f347f3847c49e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -1031,24 +1031,20 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // We try to, before exiting. for opr in args { // We see if the operand can be evaluated, and if so, we continue. - if let Some(op_ty) = self.eval_operand(&opr, source_info) { - // We must also ask if it *should* be evaluated. - if self.should_const_prop(op_ty) { - if let interpret::Operand::Immediate(immediate) = *op_ty { - // Only Immediate from here on - // FIXME(felix91gr): The code only works for Immediate. Investigate - // if it could be made to work for Indirect as well. - if let interpret::Immediate::Scalar(scalar_mu) = immediate { - // FIXME(felix91gr): This only works for Scalar - // Could probably be expanded for Scalar Tuples (inside the Immediate) - if let ScalarMaybeUndef::Scalar(scalar) = scalar_mu { - let operand_type = opr.ty(&self.local_decls, self.tcx); - *opr = self.operand_from_scalar( - scalar, - operand_type, - source_info.span, - ); - } + if let Some(l) = opr.place().and_then(|p| p.as_local()) { + if let Some(value) = self.get_const(l) { + if self.should_const_prop(value) { + if let interpret::Operand::Immediate( + interpret::Immediate::Scalar( + interpret::ScalarMaybeUndef::Scalar(scalar), + ), + ) = *value + { + *opr = self.operand_from_scalar( + scalar, + value.layout.ty, + source_info.span, + ); } } } diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff index 9853acd9e780b..92b14309bf2b7 100644 --- a/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/switch_int/rustc.main.ConstProp.diff @@ -36,8 +36,7 @@ // + ty: i32 // + val: Value(Scalar(0xffffffff)) // mir::Constant -- // + span: $DIR/switch_int.rs:9:18: 9:20 -+ // + span: $DIR/switch_int.rs:9:14: 9:21 + // + span: $DIR/switch_int.rs:9:18: 9:20 // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) } } @@ -53,8 +52,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant -- // + span: $DIR/switch_int.rs:8:18: 8:19 -+ // + span: $DIR/switch_int.rs:8:14: 8:20 + // + span: $DIR/switch_int.rs:8:18: 8:19 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } } diff --git a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff index 5a9fc5ce01e0f..e1805cc57311d 100644 --- a/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff +++ b/src/test/mir-opt/const_prop/switch_int/rustc.main.SimplifyBranches-after-const-prop.diff @@ -36,7 +36,7 @@ // + ty: i32 // + val: Value(Scalar(0xffffffff)) // mir::Constant - // + span: $DIR/switch_int.rs:9:14: 9:21 + // + span: $DIR/switch_int.rs:9:18: 9:20 // + literal: Const { ty: i32, val: Value(Scalar(0xffffffff)) } } @@ -52,7 +52,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000000)) // mir::Constant - // + span: $DIR/switch_int.rs:8:14: 8:20 + // + span: $DIR/switch_int.rs:8:18: 8:19 // + literal: Const { ty: i32, val: Value(Scalar(0x00000000)) } }