From 9766ee0b2040d93c7ff4af237c3c839d54adf8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jannis=20Christopher=20K=C3=B6hl?= Date: Wed, 9 Nov 2022 18:21:42 +0100 Subject: [PATCH] Fix struct field tracking and add tests for it --- .../rustc_mir_dataflow/src/value_analysis.rs | 14 ++--- .../src/dataflow_const_prop.rs | 4 +- .../enum.main.DataflowConstProp.diff | 61 +++++++++++++++++++ src/test/mir-opt/dataflow-const-prop/enum.rs | 13 ++++ .../struct.main.DataflowConstProp.diff | 52 ++++++++++++++++ .../mir-opt/dataflow-const-prop/struct.rs | 11 ++++ 6 files changed, 145 insertions(+), 10 deletions(-) create mode 100644 src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/enum.rs create mode 100644 src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff create mode 100644 src/test/mir-opt/dataflow-const-prop/struct.rs diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index f428cd5ee822..17d349fb5269 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -151,9 +151,7 @@ pub trait ValueAnalysis<'tcx> { ) -> ValueOrPlace { match rvalue { Rvalue::Use(operand) => self.handle_operand(operand, state), - Rvalue::CopyForDeref(place) => { - self.handle_operand(&Operand::Copy(*place), state) - } + Rvalue::CopyForDeref(place) => self.handle_operand(&Operand::Copy(*place), state), Rvalue::Ref(..) | Rvalue::AddressOf(..) => { // We don't track such places. ValueOrPlace::top() @@ -638,9 +636,7 @@ impl Map { return; } projection.push(PlaceElem::Field(field, ty)); - self.register_with_filter_rec( - tcx, local, projection, ty, filter, exclude, - ); + self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude); projection.pop(); }); } @@ -842,13 +838,17 @@ fn iter_fields<'tcx>( } } ty::Adt(def, substs) => { + if def.is_union() { + return; + } for (v_index, v_def) in def.variants().iter_enumerated() { + let variant = if def.is_struct() { None } else { Some(v_index) }; for (f_index, f_def) in v_def.fields.iter().enumerate() { let field_ty = f_def.ty(tcx, substs); let field_ty = tcx .try_normalize_erasing_regions(ty::ParamEnv::reveal_all(), field_ty) .unwrap_or(field_ty); - f(Some(v_index), f_index.into(), field_ty); + f(variant, f_index.into(), field_ty); } } } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index e88125777f14..e1c7b6ab1803 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -7,9 +7,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::visit::{MutVisitor, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_mir_dataflow::value_analysis::{ - Map, State, TrackElem, ValueAnalysis, ValueOrPlace, -}; +use rustc_mir_dataflow::value_analysis::{Map, State, TrackElem, ValueAnalysis, ValueOrPlace}; use rustc_mir_dataflow::{lattice::FlatSet, Analysis, ResultsVisitor, SwitchIntEdgeEffects}; use rustc_span::DUMMY_SP; diff --git a/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff new file mode 100644 index 000000000000..2ced794e628f --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff @@ -0,0 +1,61 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/enum.rs:+0:11: +0:11 + let _1: E; // in scope 0 at $DIR/enum.rs:+1:9: +1:10 + let mut _3: isize; // in scope 0 at $DIR/enum.rs:+2:23: +2:31 + scope 1 { + debug e => _1; // in scope 1 at $DIR/enum.rs:+1:9: +1:10 + let _2: i32; // in scope 1 at $DIR/enum.rs:+2:9: +2:10 + let _4: i32; // in scope 1 at $DIR/enum.rs:+2:29: +2:30 + let _5: i32; // in scope 1 at $DIR/enum.rs:+2:44: +2:45 + scope 2 { + debug x => _2; // in scope 2 at $DIR/enum.rs:+2:9: +2:10 + } + scope 3 { + debug x => _4; // in scope 3 at $DIR/enum.rs:+2:29: +2:30 + } + scope 4 { + debug x => _5; // in scope 4 at $DIR/enum.rs:+2:44: +2:45 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/enum.rs:+1:9: +1:10 + Deinit(_1); // scope 0 at $DIR/enum.rs:+1:13: +1:21 + ((_1 as V1).0: i32) = const 0_i32; // scope 0 at $DIR/enum.rs:+1:13: +1:21 + discriminant(_1) = 0; // scope 0 at $DIR/enum.rs:+1:13: +1:21 + StorageLive(_2); // scope 1 at $DIR/enum.rs:+2:9: +2:10 + _3 = discriminant(_1); // scope 1 at $DIR/enum.rs:+2:19: +2:20 + switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20 + } + + bb1: { + StorageLive(_5); // scope 1 at $DIR/enum.rs:+2:44: +2:45 + _5 = ((_1 as V2).0: i32); // scope 1 at $DIR/enum.rs:+2:44: +2:45 + _2 = _5; // scope 4 at $DIR/enum.rs:+2:50: +2:51 + StorageDead(_5); // scope 1 at $DIR/enum.rs:+2:50: +2:51 + goto -> bb4; // scope 1 at $DIR/enum.rs:+2:50: +2:51 + } + + bb2: { + unreachable; // scope 1 at $DIR/enum.rs:+2:19: +2:20 + } + + bb3: { + StorageLive(_4); // scope 1 at $DIR/enum.rs:+2:29: +2:30 + _4 = ((_1 as V1).0: i32); // scope 1 at $DIR/enum.rs:+2:29: +2:30 + _2 = _4; // scope 3 at $DIR/enum.rs:+2:35: +2:36 + StorageDead(_4); // scope 1 at $DIR/enum.rs:+2:35: +2:36 + goto -> bb4; // scope 1 at $DIR/enum.rs:+2:35: +2:36 + } + + bb4: { + _0 = const (); // scope 0 at $DIR/enum.rs:+0:11: +3:2 + StorageDead(_2); // scope 1 at $DIR/enum.rs:+3:1: +3:2 + StorageDead(_1); // scope 0 at $DIR/enum.rs:+3:1: +3:2 + return; // scope 0 at $DIR/enum.rs:+3:2: +3:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/enum.rs b/src/test/mir-opt/dataflow-const-prop/enum.rs new file mode 100644 index 000000000000..13288577dea3 --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/enum.rs @@ -0,0 +1,13 @@ +// unit-test: DataflowConstProp + +// Not trackable, because variants could be aliased. +enum E { + V1(i32), + V2(i32) +} + +// EMIT_MIR enum.main.DataflowConstProp.diff +fn main() { + let e = E::V1(0); + let x = match e { E::V1(x) => x, E::V2(x) => x }; +} diff --git a/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff new file mode 100644 index 000000000000..cfb2706c167c --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.diff @@ -0,0 +1,52 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/struct.rs:+0:11: +0:11 + let mut _1: S; // in scope 0 at $DIR/struct.rs:+1:9: +1:14 + let mut _3: i32; // in scope 0 at $DIR/struct.rs:+2:13: +2:16 + let mut _5: i32; // in scope 0 at $DIR/struct.rs:+4:13: +4:14 + let mut _6: i32; // in scope 0 at $DIR/struct.rs:+4:17: +4:20 + scope 1 { + debug s => _1; // in scope 1 at $DIR/struct.rs:+1:9: +1:14 + let _2: i32; // in scope 1 at $DIR/struct.rs:+2:9: +2:10 + scope 2 { + debug a => _2; // in scope 2 at $DIR/struct.rs:+2:9: +2:10 + let _4: i32; // in scope 2 at $DIR/struct.rs:+4:9: +4:10 + scope 3 { + debug b => _4; // in scope 3 at $DIR/struct.rs:+4:9: +4:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/struct.rs:+1:9: +1:14 + Deinit(_1); // scope 0 at $DIR/struct.rs:+1:17: +1:21 + (_1.0: i32) = const 1_i32; // scope 0 at $DIR/struct.rs:+1:17: +1:21 + StorageLive(_2); // scope 1 at $DIR/struct.rs:+2:9: +2:10 + StorageLive(_3); // scope 1 at $DIR/struct.rs:+2:13: +2:16 +- _3 = (_1.0: i32); // scope 1 at $DIR/struct.rs:+2:13: +2:16 +- _2 = Add(move _3, const 2_i32); // scope 1 at $DIR/struct.rs:+2:13: +2:20 ++ _3 = const 1_i32; // scope 1 at $DIR/struct.rs:+2:13: +2:16 ++ _2 = const 3_i32; // scope 1 at $DIR/struct.rs:+2:13: +2:20 + StorageDead(_3); // scope 1 at $DIR/struct.rs:+2:19: +2:20 + (_1.0: i32) = const 3_i32; // scope 2 at $DIR/struct.rs:+3:5: +3:12 + StorageLive(_4); // scope 2 at $DIR/struct.rs:+4:9: +4:10 + StorageLive(_5); // scope 2 at $DIR/struct.rs:+4:13: +4:14 +- _5 = _2; // scope 2 at $DIR/struct.rs:+4:13: +4:14 ++ _5 = const 3_i32; // scope 2 at $DIR/struct.rs:+4:13: +4:14 + StorageLive(_6); // scope 2 at $DIR/struct.rs:+4:17: +4:20 +- _6 = (_1.0: i32); // scope 2 at $DIR/struct.rs:+4:17: +4:20 +- _4 = Add(move _5, move _6); // scope 2 at $DIR/struct.rs:+4:13: +4:20 ++ _6 = const 3_i32; // scope 2 at $DIR/struct.rs:+4:17: +4:20 ++ _4 = const 6_i32; // scope 2 at $DIR/struct.rs:+4:13: +4:20 + StorageDead(_6); // scope 2 at $DIR/struct.rs:+4:19: +4:20 + StorageDead(_5); // scope 2 at $DIR/struct.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/struct.rs:+0:11: +5:2 + StorageDead(_4); // scope 2 at $DIR/struct.rs:+5:1: +5:2 + StorageDead(_2); // scope 1 at $DIR/struct.rs:+5:1: +5:2 + StorageDead(_1); // scope 0 at $DIR/struct.rs:+5:1: +5:2 + return; // scope 0 at $DIR/struct.rs:+5:2: +5:2 + } + } + diff --git a/src/test/mir-opt/dataflow-const-prop/struct.rs b/src/test/mir-opt/dataflow-const-prop/struct.rs new file mode 100644 index 000000000000..841b279e03ee --- /dev/null +++ b/src/test/mir-opt/dataflow-const-prop/struct.rs @@ -0,0 +1,11 @@ +// unit-test: DataflowConstProp + +struct S(i32); + +// EMIT_MIR struct.main.DataflowConstProp.diff +fn main() { + let mut s = S(1); + let a = s.0 + 2; + s.0 = 3; + let b = a + s.0; +}