From 31d101093c134e69a31ba58893e56647a5831299 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 12 Sep 2023 16:44:53 +0000 Subject: [PATCH 1/2] Generate ValTrees in DataflowConstProp. --- .../src/dataflow_const_prop.rs | 99 ++++++++++++++++++- .../const_debuginfo.main.ConstDebugInfo.diff | 5 +- ...ed.main.DataflowConstProp.panic-abort.diff | 4 +- ...d.main.DataflowConstProp.panic-unwind.diff | 4 +- .../enum.simple.DataflowConstProp.32bit.diff | 3 +- .../enum.simple.DataflowConstProp.64bit.diff | 3 +- .../enum.statics.DataflowConstProp.32bit.diff | 3 +- .../enum.statics.DataflowConstProp.64bit.diff | 3 +- ...ow.main.DataflowConstProp.panic-abort.diff | 2 +- ...w.main.DataflowConstProp.panic-unwind.diff | 2 +- ...pr_transparent.main.DataflowConstProp.diff | 5 +- .../struct.main.DataflowConstProp.32bit.diff | 59 ++++++++--- .../struct.main.DataflowConstProp.64bit.diff | 59 ++++++++--- tests/mir-opt/dataflow-const-prop/struct.rs | 2 + .../tuple.main.DataflowConstProp.diff | 29 +++++- tests/mir-opt/dataflow-const-prop/tuple.rs | 2 + 16 files changed, 234 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 85a0be8a44c4a..762f57ad29e18 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -557,11 +557,102 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> { state: &State>, map: &Map, ) -> Option> { - let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else { - return None; - }; let ty = place.ty(self.local_decls, self.patch.tcx).ty; - Some(Const::Val(ConstValue::Scalar(value.into()), ty)) + let place = map.find(place.as_ref())?; + if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { + Some(Const::Val(ConstValue::Scalar(value.into()), ty)) + } else { + let valtree = self.try_make_valtree(place, ty, state, map)?; + let constant = ty::Const::new_value(self.patch.tcx, valtree, ty); + Some(Const::Ty(constant)) + } + } + + fn try_make_valtree( + &self, + place: PlaceIndex, + ty: Ty<'tcx>, + state: &State>, + map: &Map, + ) -> Option> { + let tcx = self.patch.tcx; + match ty.kind() { + // ZSTs. + ty::FnDef(..) => Some(ty::ValTree::zst()), + + // Scalars. + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { + if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { + Some(ty::ValTree::Leaf(value)) + } else { + None + } + } + + // Unsupported for now. + ty::Array(_, _) => None, + + ty::Tuple(elem_tys) => { + let branches = elem_tys + .iter() + .enumerate() + .map(|(i, ty)| { + let field = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i)))?; + self.try_make_valtree(field, ty, state, map) + }) + .collect::>>()?; + Some(ty::ValTree::Branch(tcx.arena.alloc_from_iter(branches.into_iter()))) + } + + ty::Adt(def, args) => { + if def.is_union() { + return None; + } + + let (variant_idx, variant_def, variant_place) = if def.is_enum() { + let discr = map.apply(place, TrackElem::Discriminant)?; + let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { + return None; + }; + let discr_bits = discr.assert_bits(discr.size()); + let (variant, _) = + def.discriminants(tcx).find(|(_, var)| discr_bits == var.val)?; + let variant_place = map.apply(place, TrackElem::Variant(variant))?; + let variant_int = ty::ValTree::Leaf(variant.as_u32().into()); + (Some(variant_int), def.variant(variant), variant_place) + } else { + (None, def.non_enum_variant(), place) + }; + + let branches = variant_def + .fields + .iter_enumerated() + .map(|(i, field)| { + let ty = field.ty(tcx, args); + let field = map.apply(variant_place, TrackElem::Field(i))?; + self.try_make_valtree(field, ty, state, map) + }) + .collect::>>()?; + Some(ty::ValTree::Branch( + tcx.arena.alloc_from_iter(variant_idx.into_iter().chain(branches)), + )) + } + + // Do not attempt to support indirection in constants. + ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) => None, + + ty::Never + | ty::Foreign(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::Coroutine(..) + | ty::Dynamic(..) => None, + + ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), + } } } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index ed47baa67daba..0934ee3461744 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -41,7 +41,8 @@ + debug ((f: (bool, bool, u32)).2: u32) => const 123_u32; let _10: std::option::Option; scope 7 { - debug o => _10; +- debug o => _10; ++ debug o => const Option::::Some(99); let _17: u32; let _18: u32; scope 8 { @@ -81,7 +82,7 @@ _15 = const false; _16 = const 123_u32; StorageLive(_10); - _10 = Option::::Some(const 99_u16); + _10 = const Option::::Some(99); _17 = const 32_u32; _18 = const 32_u32; StorageLive(_11); diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 2f1a70f32d03a..111be450c7990 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable]; + _5 = const 2_i32; -+ _6 = CheckedAdd(const 1_i32, const 2_i32); ++ _6 = const (3, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable]; } @@ -60,7 +60,7 @@ - _10 = CheckedAdd(_9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable]; + _9 = const i32::MAX; -+ _10 = CheckedAdd(const i32::MAX, const 1_i32); ++ _10 = const (i32::MIN, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 0d8a9aca3d8c5..733100a889b63 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; -+ _6 = CheckedAdd(const 1_i32, const 2_i32); ++ _6 = const (3, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue]; } @@ -60,7 +60,7 @@ - _10 = CheckedAdd(_9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue]; + _9 = const i32::MAX; -+ _10 = CheckedAdd(const i32::MAX, const 1_i32); ++ _10 = const (i32::MIN, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 3946e7c7d96c1..1e7fdd3b1a0b4 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -23,7 +23,8 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); +- _1 = E::V1(const 0_i32); ++ _1 = const E::V1(0); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 3946e7c7d96c1..1e7fdd3b1a0b4 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -23,7 +23,8 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); +- _1 = E::V1(const 0_i32); ++ _1 = const E::V1(0); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index 1348b27933082..c5c95bc6cd185 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -44,7 +44,8 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); +- _1 = (*_2); ++ _1 = const E::V1(0); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 66929e886d3ca..48897b93e46c4 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -44,7 +44,8 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); +- _1 = (*_2); ++ _1 = const E::V1(0); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 87bb1454c9624..b5f7f2a472c4d 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; -+ _4 = CheckedAdd(const u8::MAX, const 1_u8); ++ _4 = const (0, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index b2f13640a4c05..e2e799650aa44 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; -+ _4 = CheckedAdd(const u8::MAX, const 1_u8); ++ _4 = const (0, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index 4b1a8d932c651..4530d8b627bd5 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -17,7 +17,8 @@ bb0: { StorageLive(_1); - _1 = I32(const 0_i32); +- _1 = I32(const 0_i32); ++ _1 = const I32(0); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -31,7 +32,7 @@ StorageDead(_5); StorageDead(_4); - _2 = I32(move _3); -+ _2 = I32(const 0_i32); ++ _2 = const I32(0); StorageDead(_3); _0 = const (); StorageDead(_2); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index e80f31ca9348a..8d277459d3bd8 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -9,11 +9,15 @@ let mut _6: i32; let mut _11: BigStruct; let mut _16: &&BigStruct; - let mut _17: &BigStruct; - let mut _18: &BigStruct; - let mut _19: &BigStruct; - let mut _20: &BigStruct; - let mut _21: &BigStruct; + let mut _18: S; + let mut _19: u8; + let mut _20: f32; + let mut _21: S; + let mut _22: &BigStruct; + let mut _23: &BigStruct; + let mut _24: &BigStruct; + let mut _25: &BigStruct; + let mut _26: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -40,6 +44,10 @@ debug b => _13; debug c => _14; debug d => _15; + let _17: BigStruct; + scope 6 { + debug bs => _17; + } } } } @@ -48,7 +56,8 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); +- _1 = S(const 1_i32); ++ _1 = const S(1); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -85,25 +94,45 @@ StorageDead(_11); StorageLive(_16); _16 = const {ALLOC1: &&BigStruct}; - _17 = deref_copy (*_16); + _22 = deref_copy (*_16); StorageLive(_12); - _18 = deref_copy (*_16); -- _12 = ((*_18).0: S); + _23 = deref_copy (*_16); +- _12 = ((*_23).0: S); + _12 = const S(1_i32); StorageLive(_13); - _19 = deref_copy (*_16); -- _13 = ((*_19).1: u8); + _24 = deref_copy (*_16); +- _13 = ((*_24).1: u8); + _13 = const 5_u8; StorageLive(_14); - _20 = deref_copy (*_16); -- _14 = ((*_20).2: f32); + _25 = deref_copy (*_16); +- _14 = ((*_25).2: f32); + _14 = const 7f32; StorageLive(_15); - _21 = deref_copy (*_16); -- _15 = ((*_21).3: S); + _26 = deref_copy (*_16); +- _15 = ((*_26).3: S); + _15 = const S(13_i32); StorageDead(_16); + StorageLive(_17); + StorageLive(_18); +- _18 = _12; ++ _18 = const S(1_i32); + StorageLive(_19); +- _19 = _13; ++ _19 = const 5_u8; + StorageLive(_20); +- _20 = _14; ++ _20 = const 7f32; + StorageLive(_21); +- _21 = _15; +- _17 = BigStruct(move _18, move _19, move _20, move _21); ++ _21 = const S(13_i32); ++ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); _0 = const (); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_13); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index de9cf19719978..fca94beb9ab53 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -9,11 +9,15 @@ let mut _6: i32; let mut _11: BigStruct; let mut _16: &&BigStruct; - let mut _17: &BigStruct; - let mut _18: &BigStruct; - let mut _19: &BigStruct; - let mut _20: &BigStruct; - let mut _21: &BigStruct; + let mut _18: S; + let mut _19: u8; + let mut _20: f32; + let mut _21: S; + let mut _22: &BigStruct; + let mut _23: &BigStruct; + let mut _24: &BigStruct; + let mut _25: &BigStruct; + let mut _26: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -40,6 +44,10 @@ debug b => _13; debug c => _14; debug d => _15; + let _17: BigStruct; + scope 6 { + debug bs => _17; + } } } } @@ -48,7 +56,8 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); +- _1 = S(const 1_i32); ++ _1 = const S(1); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -85,25 +94,45 @@ StorageDead(_11); StorageLive(_16); _16 = const {ALLOC1: &&BigStruct}; - _17 = deref_copy (*_16); + _22 = deref_copy (*_16); StorageLive(_12); - _18 = deref_copy (*_16); -- _12 = ((*_18).0: S); + _23 = deref_copy (*_16); +- _12 = ((*_23).0: S); + _12 = const S(1_i32); StorageLive(_13); - _19 = deref_copy (*_16); -- _13 = ((*_19).1: u8); + _24 = deref_copy (*_16); +- _13 = ((*_24).1: u8); + _13 = const 5_u8; StorageLive(_14); - _20 = deref_copy (*_16); -- _14 = ((*_20).2: f32); + _25 = deref_copy (*_16); +- _14 = ((*_25).2: f32); + _14 = const 7f32; StorageLive(_15); - _21 = deref_copy (*_16); -- _15 = ((*_21).3: S); + _26 = deref_copy (*_16); +- _15 = ((*_26).3: S); + _15 = const S(13_i32); StorageDead(_16); + StorageLive(_17); + StorageLive(_18); +- _18 = _12; ++ _18 = const S(1_i32); + StorageLive(_19); +- _19 = _13; ++ _19 = const 5_u8; + StorageLive(_20); +- _20 = _14; ++ _20 = const 7f32; + StorageLive(_21); +- _21 = _15; +- _17 = BigStruct(move _18, move _19, move _20, move _21); ++ _21 = const S(13_i32); ++ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); _0 = const (); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_13); diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 7b0646a535640..5c6edeb3866ef 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -20,4 +20,6 @@ fn main() { static STAT: &BigStruct = &BigStruct(S(1), 5, 7., S(13)); let BigStruct(a, b, c, d) = *STAT; + + let bs = BigStruct(a, b, c, d); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff index 5e385d21ec602..21c9b9d1eb96f 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff @@ -11,6 +11,9 @@ let mut _8: i32; let mut _9: i32; let mut _10: i32; + let mut _12: i32; + let mut _13: (i32, i32); + let mut _14: i32; scope 1 { debug a => _1; let _2: i32; @@ -19,13 +22,18 @@ let _6: i32; scope 3 { debug c => _6; + let _11: (i32, (i32, i32), i32); + scope 4 { + debug d => _11; + } } } } bb0: { StorageLive(_1); - _1 = (const 1_i32, const 2_i32); +- _1 = (const 1_i32, const 2_i32); ++ _1 = const (1, 2); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -41,7 +49,8 @@ - _2 = Add(move _3, const 3_i32); + _2 = const 6_i32; StorageDead(_3); - _1 = (const 2_i32, const 3_i32); +- _1 = (const 2_i32, const 3_i32); ++ _1 = const (2, 3); StorageLive(_6); StorageLive(_7); StorageLive(_8); @@ -61,7 +70,23 @@ + _6 = const 11_i32; StorageDead(_10); StorageDead(_7); + StorageLive(_11); + StorageLive(_12); +- _12 = _2; ++ _12 = const 6_i32; + StorageLive(_13); +- _13 = _1; ++ _13 = const (2, 3); + StorageLive(_14); +- _14 = _6; +- _11 = (move _12, move _13, move _14); ++ _14 = const 11_i32; ++ _11 = const (6, (2, 3), 11); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); _0 = const (); + StorageDead(_11); StorageDead(_6); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index c63ce8b140f87..7691bc8d7c504 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -7,4 +7,6 @@ fn main() { let b = a.0 + a.1 + 3; a = (2, 3); let c = a.0 + a.1 + b; + + let d = (b, a, c); } From 8c1b039d482149f643a88c6d7af526b18f56dd8f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 17 Sep 2023 09:35:06 +0000 Subject: [PATCH 2/2] Use a ConstValue instead. --- .../src/dataflow_const_prop.rs | 255 +++++++++++------- .../const_debuginfo.main.ConstDebugInfo.diff | 8 +- ...ed.main.DataflowConstProp.panic-abort.diff | 10 +- ...d.main.DataflowConstProp.panic-unwind.diff | 10 +- tests/mir-opt/dataflow-const-prop/checked.rs | 2 +- .../enum.simple.DataflowConstProp.32bit.diff | 6 +- .../enum.simple.DataflowConstProp.64bit.diff | 6 +- .../enum.statics.DataflowConstProp.32bit.diff | 6 +- .../enum.statics.DataflowConstProp.64bit.diff | 6 +- ...ow.main.DataflowConstProp.panic-abort.diff | 6 +- ...w.main.DataflowConstProp.panic-unwind.diff | 6 +- ...pr_transparent.main.DataflowConstProp.diff | 12 +- .../struct.main.DataflowConstProp.32bit.diff | 237 +++++++++++----- .../struct.main.DataflowConstProp.64bit.diff | 237 +++++++++++----- tests/mir-opt/dataflow-const-prop/struct.rs | 25 +- .../mir-opt/dataflow-const-prop/transmute.rs | 4 +- ...on_as_integer.DataflowConstProp.32bit.diff | 6 +- ...on_as_integer.DataflowConstProp.64bit.diff | 6 +- ...chable_direct.DataflowConstProp.32bit.diff | 6 +- ...chable_direct.DataflowConstProp.64bit.diff | 6 +- ...> tuple.main.DataflowConstProp.32bit.diff} | 24 +- .../tuple.main.DataflowConstProp.64bit.diff | 112 ++++++++ tests/mir-opt/dataflow-const-prop/tuple.rs | 1 + 23 files changed, 720 insertions(+), 277 deletions(-) rename tests/mir-opt/dataflow-const-prop/{tuple.main.DataflowConstProp.diff => tuple.main.DataflowConstProp.32bit.diff} (80%) create mode 100644 tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 762f57ad29e18..2c29978173ff5 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -2,13 +2,13 @@ //! //! Currently, this pass only propagates scalar values. -use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; +use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace, @@ -16,8 +16,9 @@ use rustc_mir_dataflow::value_analysis::{ use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor}; use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; -use rustc_target::abi::{FieldIdx, VariantIdx}; +use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT}; +use crate::const_prop::throw_machine_stop_str; use crate::MirPass; // These constants are somewhat random guesses and have not been optimized. @@ -553,107 +554,151 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> { fn try_make_constant( &self, + ecx: &mut InterpCx<'tcx, 'tcx, DummyMachine>, place: Place<'tcx>, state: &State>, map: &Map, ) -> Option> { let ty = place.ty(self.local_decls, self.patch.tcx).ty; + let layout = ecx.layout_of(ty).ok()?; + + if layout.is_zst() { + return Some(Const::zero_sized(ty)); + } + + if layout.is_unsized() { + return None; + } + let place = map.find(place.as_ref())?; - if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { - Some(Const::Val(ConstValue::Scalar(value.into()), ty)) - } else { - let valtree = self.try_make_valtree(place, ty, state, map)?; - let constant = ty::Const::new_value(self.patch.tcx, valtree, ty); - Some(Const::Ty(constant)) + if layout.abi.is_scalar() + && let Some(value) = propagatable_scalar(place, state, map) + { + return Some(Const::Val(ConstValue::Scalar(value), ty)); + } + + if matches!(layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { + let alloc_id = ecx + .intern_with_temp_alloc(layout, |ecx, dest| { + try_write_constant(ecx, dest, place, ty, state, map) + }) + .ok()?; + return Some(Const::Val(ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ty)); } + + None } +} - fn try_make_valtree( - &self, - place: PlaceIndex, - ty: Ty<'tcx>, - state: &State>, - map: &Map, - ) -> Option> { - let tcx = self.patch.tcx; - match ty.kind() { - // ZSTs. - ty::FnDef(..) => Some(ty::ValTree::zst()), - - // Scalars. - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { - if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { - Some(ty::ValTree::Leaf(value)) - } else { - None - } - } +fn propagatable_scalar( + place: PlaceIndex, + state: &State>, + map: &Map, +) -> Option { + if let FlatSet::Elem(value) = state.get_idx(place, map) && value.try_to_int().is_ok() { + // Do not attempt to propagate pointers, as we may fail to preserve their identity. + Some(value) + } else { + None + } +} - // Unsupported for now. - ty::Array(_, _) => None, - - ty::Tuple(elem_tys) => { - let branches = elem_tys - .iter() - .enumerate() - .map(|(i, ty)| { - let field = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i)))?; - self.try_make_valtree(field, ty, state, map) - }) - .collect::>>()?; - Some(ty::ValTree::Branch(tcx.arena.alloc_from_iter(branches.into_iter()))) - } +#[instrument(level = "trace", skip(ecx, state, map))] +fn try_write_constant<'tcx>( + ecx: &mut InterpCx<'_, 'tcx, DummyMachine>, + dest: &PlaceTy<'tcx>, + place: PlaceIndex, + ty: Ty<'tcx>, + state: &State>, + map: &Map, +) -> InterpResult<'tcx> { + let layout = ecx.layout_of(ty)?; + + // Fast path for ZSTs. + if layout.is_zst() { + return Ok(()); + } + + // Fast path for scalars. + if layout.abi.is_scalar() + && let Some(value) = propagatable_scalar(place, state, map) + { + return ecx.write_immediate(Immediate::Scalar(value), dest); + } - ty::Adt(def, args) => { - if def.is_union() { - return None; - } + match ty.kind() { + // ZSTs. Nothing to do. + ty::FnDef(..) => {} - let (variant_idx, variant_def, variant_place) = if def.is_enum() { - let discr = map.apply(place, TrackElem::Discriminant)?; - let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { - return None; - }; - let discr_bits = discr.assert_bits(discr.size()); - let (variant, _) = - def.discriminants(tcx).find(|(_, var)| discr_bits == var.val)?; - let variant_place = map.apply(place, TrackElem::Variant(variant))?; - let variant_int = ty::ValTree::Leaf(variant.as_u32().into()); - (Some(variant_int), def.variant(variant), variant_place) - } else { - (None, def.non_enum_variant(), place) + // Those are scalars, must be handled above. + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"), + + ty::Tuple(elem_tys) => { + for (i, elem) in elem_tys.iter().enumerate() { + let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else { + throw_machine_stop_str!("missing field in tuple") }; + let field_dest = ecx.project_field(dest, i)?; + try_write_constant(ecx, &field_dest, field, elem, state, map)?; + } + } - let branches = variant_def - .fields - .iter_enumerated() - .map(|(i, field)| { - let ty = field.ty(tcx, args); - let field = map.apply(variant_place, TrackElem::Field(i))?; - self.try_make_valtree(field, ty, state, map) - }) - .collect::>>()?; - Some(ty::ValTree::Branch( - tcx.arena.alloc_from_iter(variant_idx.into_iter().chain(branches)), - )) + ty::Adt(def, args) => { + if def.is_union() { + throw_machine_stop_str!("cannot propagate unions") } - // Do not attempt to support indirection in constants. - ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) => None, + let (variant_idx, variant_def, variant_place, variant_dest) = if def.is_enum() { + let Some(discr) = map.apply(place, TrackElem::Discriminant) else { + throw_machine_stop_str!("missing discriminant for enum") + }; + let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { + throw_machine_stop_str!("discriminant with provenance") + }; + let discr_bits = discr.assert_bits(discr.size()); + let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else { + throw_machine_stop_str!("illegal discriminant for enum") + }; + let Some(variant_place) = map.apply(place, TrackElem::Variant(variant)) else { + throw_machine_stop_str!("missing variant for enum") + }; + let variant_dest = ecx.project_downcast(dest, variant)?; + (variant, def.variant(variant), variant_place, variant_dest) + } else { + (FIRST_VARIANT, def.non_enum_variant(), place, dest.clone()) + }; + + for (i, field) in variant_def.fields.iter_enumerated() { + let ty = field.ty(*ecx.tcx, args); + let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else { + throw_machine_stop_str!("missing field in ADT") + }; + let field_dest = ecx.project_field(&variant_dest, i.as_usize())?; + try_write_constant(ecx, &field_dest, field, ty, state, map)?; + } + ecx.write_discriminant(variant_idx, dest)?; + } - ty::Never - | ty::Foreign(..) - | ty::Alias(..) - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Closure(..) - | ty::Coroutine(..) - | ty::Dynamic(..) => None, + // Unsupported for now. + ty::Array(_, _) - ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), - } + // Do not attempt to support indirection in constants. + | ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) + + | ty::Never + | ty::Foreign(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::Coroutine(..) + | ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"), + + ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), } + + Ok(()) } impl<'mir, 'tcx> @@ -671,8 +716,13 @@ impl<'mir, 'tcx> ) { match &statement.kind { StatementKind::Assign(box (_, rvalue)) => { - OperandCollector { state, visitor: self, map: &results.analysis.0.map } - .visit_rvalue(rvalue, location); + OperandCollector { + state, + visitor: self, + ecx: &mut results.analysis.0.ecx, + map: &results.analysis.0.map, + } + .visit_rvalue(rvalue, location); } _ => (), } @@ -690,7 +740,12 @@ impl<'mir, 'tcx> // Don't overwrite the assignment if it already uses a constant (to keep the span). } StatementKind::Assign(box (place, _)) => { - if let Some(value) = self.try_make_constant(place, state, &results.analysis.0.map) { + if let Some(value) = self.try_make_constant( + &mut results.analysis.0.ecx, + place, + state, + &results.analysis.0.map, + ) { self.patch.assignments.insert(location, value); } } @@ -705,8 +760,13 @@ impl<'mir, 'tcx> terminator: &'mir Terminator<'tcx>, location: Location, ) { - OperandCollector { state, visitor: self, map: &results.analysis.0.map } - .visit_terminator(terminator, location); + OperandCollector { + state, + visitor: self, + ecx: &mut results.analysis.0.ecx, + map: &results.analysis.0.map, + } + .visit_terminator(terminator, location); } } @@ -761,6 +821,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { struct OperandCollector<'tcx, 'map, 'locals, 'a> { state: &'a State>, visitor: &'a mut Collector<'tcx, 'locals>, + ecx: &'map mut InterpCx<'tcx, 'tcx, DummyMachine>, map: &'map Map, } @@ -773,7 +834,7 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { location: Location, ) { if let PlaceElem::Index(local) = elem - && let Some(value) = self.visitor.try_make_constant(local.into(), self.state, self.map) + && let Some(value) = self.visitor.try_make_constant(self.ecx, local.into(), self.state, self.map) { self.visitor.patch.before_effect.insert((location, local.into()), value); } @@ -781,7 +842,9 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { if let Some(place) = operand.place() { - if let Some(value) = self.visitor.try_make_constant(place, self.state, self.map) { + if let Some(value) = + self.visitor.try_make_constant(self.ecx, place, self.state, self.map) + { self.visitor.patch.before_effect.insert((location, place), value); } else if !place.projection.is_empty() { // Try to propagate into `Index` projections. @@ -804,7 +867,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm } fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool { - unimplemented!() + false } fn before_access_global( @@ -816,13 +879,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm is_write: bool, ) -> InterpResult<'tcx> { if is_write { - crate::const_prop::throw_machine_stop_str!("can't write to global"); + throw_machine_stop_str!("can't write to global"); } // If the static allocation is mutable, then we can't const prop it as its content // might be different at runtime. if alloc.inner().mutability.is_mut() { - crate::const_prop::throw_machine_stop_str!("can't access mutable globals in ConstProp"); + throw_machine_stop_str!("can't access mutable globals in ConstProp"); } Ok(()) @@ -872,7 +935,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, _right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, ) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> { - crate::const_prop::throw_machine_stop_str!("can't do pointer arithmetic"); + throw_machine_stop_str!("can't do pointer arithmetic"); } fn expose_ptr( diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 0934ee3461744..313e5dddbbba4 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -42,7 +42,7 @@ let _10: std::option::Option; scope 7 { - debug o => _10; -+ debug o => const Option::::Some(99); ++ debug o => const Option::::Some(99_u16); let _17: u32; let _18: u32; scope 8 { @@ -82,7 +82,7 @@ _15 = const false; _16 = const 123_u32; StorageLive(_10); - _10 = const Option::::Some(99); + _10 = const Option::::Some(99_u16); _17 = const 32_u32; _18 = const 32_u32; StorageLive(_11); @@ -98,3 +98,7 @@ } } + ALLOC0 (size: 4, align: 2) { + 01 00 63 00 │ ..c. + } + diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 111be450c7990..4569ffe483b38 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable]; + _5 = const 2_i32; -+ _6 = const (3, false); ++ _6 = const (3_i32, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable]; } @@ -76,5 +76,13 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 80 01 __ __ __ │ .....░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 03 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 733100a889b63..aa7e404eb9f50 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; -+ _6 = const (3, false); ++ _6 = const (3_i32, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue]; } @@ -76,5 +76,13 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 80 01 __ __ __ │ .....░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 03 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index b41ac0b3d2af6..f7fac8890a057 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,7 +1,7 @@ // skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 1e7fdd3b1a0b4..798b0c041b4ec 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -24,7 +24,7 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; @@ -60,5 +60,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 1e7fdd3b1a0b4..798b0c041b4ec 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -24,7 +24,7 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; @@ -60,5 +60,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index c5c95bc6cd185..d502b19823995 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -45,7 +45,7 @@ StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); @@ -111,6 +111,10 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } ALLOC2 (static: RC, size: 4, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 48897b93e46c4..5d69572b50744 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -45,7 +45,7 @@ StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); @@ -111,6 +111,10 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } ALLOC2 (static: RC, size: 8, align: 8) { diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index b5f7f2a472c4d..2d4591ea2d3d8 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const (0, true); ++ _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } @@ -37,5 +37,9 @@ _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 2, align: 1) { ++ 00 01 │ .. } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index e2e799650aa44..e99ac782a2ff0 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; -+ _4 = const (0, true); ++ _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } @@ -37,5 +37,9 @@ _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 2, align: 1) { ++ 00 01 │ .. } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index 4530d8b627bd5..98bd40ab2c3da 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = I32(const 0_i32); -+ _1 = const I32(0); ++ _1 = const I32(0_i32); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -32,12 +32,20 @@ StorageDead(_5); StorageDead(_4); - _2 = I32(move _3); -+ _2 = const I32(0); ++ _2 = const I32(0_i32); StorageDead(_3); _0 = const (); StorageDead(_2); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 4, align: 4) { ++ 00 00 00 00 │ .... ++ } ++ ++ ALLOC1 (size: 4, align: 4) { ++ 00 00 00 00 │ .... } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 8d277459d3bd8..944b061f9939b 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -7,17 +7,24 @@ let mut _3: i32; let mut _5: i32; let mut _6: i32; - let mut _11: BigStruct; - let mut _16: &&BigStruct; - let mut _18: S; - let mut _19: u8; - let mut _20: f32; - let mut _21: S; - let mut _22: &BigStruct; - let mut _23: &BigStruct; - let mut _24: &BigStruct; - let mut _25: &BigStruct; - let mut _26: &BigStruct; + let mut _10: SmallStruct; + let mut _14: &&SmallStruct; + let mut _16: f32; + let mut _17: std::option::Option; + let mut _18: &[f32]; + let mut _22: BigStruct; + let mut _26: &&BigStruct; + let mut _28: f32; + let mut _29: std::option::Option; + let mut _30: &[f64]; + let mut _31: &SmallStruct; + let mut _32: &SmallStruct; + let mut _33: &SmallStruct; + let mut _34: &SmallStruct; + let mut _35: &BigStruct; + let mut _36: &BigStruct; + let mut _37: &BigStruct; + let mut _38: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -26,27 +33,43 @@ let _4: i32; scope 3 { debug b => _4; - let _7: S; - let _8: u8; - let _9: f32; - let _10: S; + let _7: f32; + let _8: std::option::Option; + let _9: &[f32]; scope 4 { debug a => _7; debug b => _8; debug c => _9; - debug d => _10; - let _12: S; - let _13: u8; - let _14: f32; - let _15: S; + let _11: f32; + let _12: std::option::Option; + let _13: &[f32]; scope 5 { - debug a => _12; - debug b => _13; - debug c => _14; - debug d => _15; - let _17: BigStruct; + debug a => _11; + debug b => _12; + debug c => _13; + let _15: SmallStruct; scope 6 { - debug bs => _17; + debug ss => _15; + let _19: f32; + let _20: std::option::Option; + let _21: &[f64]; + scope 7 { + debug a => _19; + debug b => _20; + debug c => _21; + let _23: f32; + let _24: std::option::Option; + let _25: &[f64]; + scope 8 { + debug a => _23; + debug b => _24; + debug c => _25; + let _27: BigStruct; + scope 9 { + debug bs => _27; + } + } + } } } } @@ -57,7 +80,7 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); -+ _1 = const S(1); ++ _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -77,67 +100,95 @@ + _4 = const 6_i32; StorageDead(_6); StorageDead(_5); - StorageLive(_11); - _11 = const _; + StorageLive(_10); + _10 = const _; StorageLive(_7); -- _7 = (_11.0: S); -+ _7 = const S(1_i32); +- _7 = (_10.0: f32); ++ _7 = const 4f32; StorageLive(_8); -- _8 = (_11.1: u8); -+ _8 = const 5_u8; +- _8 = (_10.1: std::option::Option); ++ _8 = const Option::::Some(S(1_i32)); StorageLive(_9); -- _9 = (_11.2: f32); -+ _9 = const 7f32; - StorageLive(_10); -- _10 = (_11.3: S); -+ _10 = const S(13_i32); - StorageDead(_11); - StorageLive(_16); - _16 = const {ALLOC1: &&BigStruct}; - _22 = deref_copy (*_16); + _9 = (_10.2: &[f32]); + StorageDead(_10); + StorageLive(_14); + _14 = const {ALLOC4: &&SmallStruct}; + _31 = deref_copy (*_14); + StorageLive(_11); + _32 = deref_copy (*_14); +- _11 = ((*_32).0: f32); ++ _11 = const 9f32; StorageLive(_12); - _23 = deref_copy (*_16); -- _12 = ((*_23).0: S); -+ _12 = const S(1_i32); + _33 = deref_copy (*_14); + _12 = ((*_33).1: std::option::Option); StorageLive(_13); - _24 = deref_copy (*_16); -- _13 = ((*_24).1: u8); -+ _13 = const 5_u8; - StorageLive(_14); - _25 = deref_copy (*_16); -- _14 = ((*_25).2: f32); -+ _14 = const 7f32; + _34 = deref_copy (*_14); + _13 = ((*_34).2: &[f32]); + StorageDead(_14); StorageLive(_15); - _26 = deref_copy (*_16); -- _15 = ((*_26).3: S); -+ _15 = const S(13_i32); - StorageDead(_16); + StorageLive(_16); +- _16 = _11; ++ _16 = const 9f32; StorageLive(_17); + _17 = _12; StorageLive(_18); -- _18 = _12; -+ _18 = const S(1_i32); + _18 = _13; +- _15 = SmallStruct(move _16, move _17, move _18); ++ _15 = SmallStruct(const 9f32, move _17, move _18); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageLive(_22); + _22 = const _; StorageLive(_19); -- _19 = _13; -+ _19 = const 5_u8; +- _19 = (_22.0: f32); ++ _19 = const 25f32; StorageLive(_20); -- _20 = _14; -+ _20 = const 7f32; + _20 = (_22.1: std::option::Option); StorageLive(_21); -- _21 = _15; -- _17 = BigStruct(move _18, move _19, move _20, move _21); -+ _21 = const S(13_i32); -+ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + _21 = (_22.2: &[f64]); + StorageDead(_22); + StorageLive(_26); + _26 = const {ALLOC5: &&BigStruct}; + _35 = deref_copy (*_26); + StorageLive(_23); + _36 = deref_copy (*_26); +- _23 = ((*_36).0: f32); ++ _23 = const 82f32; + StorageLive(_24); + _37 = deref_copy (*_26); +- _24 = ((*_37).1: std::option::Option); ++ _24 = const Option::::Some(S(35_i32)); + StorageLive(_25); + _38 = deref_copy (*_26); + _25 = ((*_38).2: &[f64]); + StorageDead(_26); + StorageLive(_27); + StorageLive(_28); +- _28 = _23; ++ _28 = const 82f32; + StorageLive(_29); +- _29 = _24; ++ _29 = const Option::::Some(S(35_i32)); + StorageLive(_30); + _30 = _25; +- _27 = BigStruct(move _28, move _29, move _30); ++ _27 = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move _30); + StorageDead(_30); + StorageDead(_29); + StorageDead(_28); + _0 = const (); + StorageDead(_27); + StorageDead(_25); + StorageDead(_24); + StorageDead(_23); StorageDead(_21); StorageDead(_20); StorageDead(_19); - StorageDead(_18); - _0 = const (); - StorageDead(_17); StorageDead(_15); - StorageDead(_14); StorageDead(_13); StorageDead(_12); - StorageDead(_10); + StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -146,13 +197,51 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC6 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC7 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC8 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC9 (size: 8, align: 4) { ++ 01 00 00 00 01 00 00 00 │ ........ ++ } ++ ++ ALLOC10 (size: 4, align: 4) { ++ 01 00 00 00 │ .... } - ALLOC1 (static: STAT, size: 4, align: 4) { + ALLOC5 (static: BIG_STAT, size: 4, align: 4) { ╾ALLOC0╼ │ ╾──╼ } - ALLOC0 (size: 16, align: 4) { - 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ + ALLOC0 (size: 20, align: 4) { + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼.... + 0x10 │ 00 00 a4 42 │ ...B + } + + ALLOC1 (size: 16, align: 4) { + 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + } + + ALLOC4 (static: SMALL_STAT, size: 4, align: 4) { + ╾ALLOC2╼ │ ╾──╼ + } + + ALLOC2 (size: 20, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 10 41 │ ...A + } + + ALLOC3 (size: 4, align: 4) { + 00 00 50 41 │ ..PA } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index fca94beb9ab53..c2c95657a2a3d 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -7,17 +7,24 @@ let mut _3: i32; let mut _5: i32; let mut _6: i32; - let mut _11: BigStruct; - let mut _16: &&BigStruct; - let mut _18: S; - let mut _19: u8; - let mut _20: f32; - let mut _21: S; - let mut _22: &BigStruct; - let mut _23: &BigStruct; - let mut _24: &BigStruct; - let mut _25: &BigStruct; - let mut _26: &BigStruct; + let mut _10: SmallStruct; + let mut _14: &&SmallStruct; + let mut _16: f32; + let mut _17: std::option::Option; + let mut _18: &[f32]; + let mut _22: BigStruct; + let mut _26: &&BigStruct; + let mut _28: f32; + let mut _29: std::option::Option; + let mut _30: &[f64]; + let mut _31: &SmallStruct; + let mut _32: &SmallStruct; + let mut _33: &SmallStruct; + let mut _34: &SmallStruct; + let mut _35: &BigStruct; + let mut _36: &BigStruct; + let mut _37: &BigStruct; + let mut _38: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -26,27 +33,43 @@ let _4: i32; scope 3 { debug b => _4; - let _7: S; - let _8: u8; - let _9: f32; - let _10: S; + let _7: f32; + let _8: std::option::Option; + let _9: &[f32]; scope 4 { debug a => _7; debug b => _8; debug c => _9; - debug d => _10; - let _12: S; - let _13: u8; - let _14: f32; - let _15: S; + let _11: f32; + let _12: std::option::Option; + let _13: &[f32]; scope 5 { - debug a => _12; - debug b => _13; - debug c => _14; - debug d => _15; - let _17: BigStruct; + debug a => _11; + debug b => _12; + debug c => _13; + let _15: SmallStruct; scope 6 { - debug bs => _17; + debug ss => _15; + let _19: f32; + let _20: std::option::Option; + let _21: &[f64]; + scope 7 { + debug a => _19; + debug b => _20; + debug c => _21; + let _23: f32; + let _24: std::option::Option; + let _25: &[f64]; + scope 8 { + debug a => _23; + debug b => _24; + debug c => _25; + let _27: BigStruct; + scope 9 { + debug bs => _27; + } + } + } } } } @@ -57,7 +80,7 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); -+ _1 = const S(1); ++ _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -77,67 +100,95 @@ + _4 = const 6_i32; StorageDead(_6); StorageDead(_5); - StorageLive(_11); - _11 = const _; + StorageLive(_10); + _10 = const _; StorageLive(_7); -- _7 = (_11.0: S); -+ _7 = const S(1_i32); +- _7 = (_10.0: f32); ++ _7 = const 4f32; StorageLive(_8); -- _8 = (_11.1: u8); -+ _8 = const 5_u8; +- _8 = (_10.1: std::option::Option); ++ _8 = const Option::::Some(S(1_i32)); StorageLive(_9); -- _9 = (_11.2: f32); -+ _9 = const 7f32; - StorageLive(_10); -- _10 = (_11.3: S); -+ _10 = const S(13_i32); - StorageDead(_11); - StorageLive(_16); - _16 = const {ALLOC1: &&BigStruct}; - _22 = deref_copy (*_16); + _9 = (_10.2: &[f32]); + StorageDead(_10); + StorageLive(_14); + _14 = const {ALLOC4: &&SmallStruct}; + _31 = deref_copy (*_14); + StorageLive(_11); + _32 = deref_copy (*_14); +- _11 = ((*_32).0: f32); ++ _11 = const 9f32; StorageLive(_12); - _23 = deref_copy (*_16); -- _12 = ((*_23).0: S); -+ _12 = const S(1_i32); + _33 = deref_copy (*_14); + _12 = ((*_33).1: std::option::Option); StorageLive(_13); - _24 = deref_copy (*_16); -- _13 = ((*_24).1: u8); -+ _13 = const 5_u8; - StorageLive(_14); - _25 = deref_copy (*_16); -- _14 = ((*_25).2: f32); -+ _14 = const 7f32; + _34 = deref_copy (*_14); + _13 = ((*_34).2: &[f32]); + StorageDead(_14); StorageLive(_15); - _26 = deref_copy (*_16); -- _15 = ((*_26).3: S); -+ _15 = const S(13_i32); - StorageDead(_16); + StorageLive(_16); +- _16 = _11; ++ _16 = const 9f32; StorageLive(_17); + _17 = _12; StorageLive(_18); -- _18 = _12; -+ _18 = const S(1_i32); + _18 = _13; +- _15 = SmallStruct(move _16, move _17, move _18); ++ _15 = SmallStruct(const 9f32, move _17, move _18); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageLive(_22); + _22 = const _; StorageLive(_19); -- _19 = _13; -+ _19 = const 5_u8; +- _19 = (_22.0: f32); ++ _19 = const 25f32; StorageLive(_20); -- _20 = _14; -+ _20 = const 7f32; + _20 = (_22.1: std::option::Option); StorageLive(_21); -- _21 = _15; -- _17 = BigStruct(move _18, move _19, move _20, move _21); -+ _21 = const S(13_i32); -+ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + _21 = (_22.2: &[f64]); + StorageDead(_22); + StorageLive(_26); + _26 = const {ALLOC5: &&BigStruct}; + _35 = deref_copy (*_26); + StorageLive(_23); + _36 = deref_copy (*_26); +- _23 = ((*_36).0: f32); ++ _23 = const 82f32; + StorageLive(_24); + _37 = deref_copy (*_26); +- _24 = ((*_37).1: std::option::Option); ++ _24 = const Option::::Some(S(35_i32)); + StorageLive(_25); + _38 = deref_copy (*_26); + _25 = ((*_38).2: &[f64]); + StorageDead(_26); + StorageLive(_27); + StorageLive(_28); +- _28 = _23; ++ _28 = const 82f32; + StorageLive(_29); +- _29 = _24; ++ _29 = const Option::::Some(S(35_i32)); + StorageLive(_30); + _30 = _25; +- _27 = BigStruct(move _28, move _29, move _30); ++ _27 = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move _30); + StorageDead(_30); + StorageDead(_29); + StorageDead(_28); + _0 = const (); + StorageDead(_27); + StorageDead(_25); + StorageDead(_24); + StorageDead(_23); StorageDead(_21); StorageDead(_20); StorageDead(_19); - StorageDead(_18); - _0 = const (); - StorageDead(_17); StorageDead(_15); - StorageDead(_14); StorageDead(_13); StorageDead(_12); - StorageDead(_10); + StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -146,13 +197,51 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC6 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC7 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC8 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC9 (size: 8, align: 4) { ++ 01 00 00 00 01 00 00 00 │ ........ ++ } ++ ++ ALLOC10 (size: 4, align: 4) { ++ 01 00 00 00 │ .... } - ALLOC1 (static: STAT, size: 8, align: 8) { + ALLOC5 (static: BIG_STAT, size: 8, align: 8) { ╾ALLOC0╼ │ ╾──────╼ } - ALLOC0 (size: 16, align: 4) { - 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ + ALLOC0 (size: 32, align: 8) { + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ + 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ + } + + ALLOC1 (size: 16, align: 8) { + 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + } + + ALLOC4 (static: SMALL_STAT, size: 8, align: 8) { + ╾ALLOC2╼ │ ╾──────╼ + } + + ALLOC2 (size: 32, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ + 0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░ + } + + ALLOC3 (size: 4, align: 4) { + 00 00 50 41 │ ..PA } diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 5c6edeb3866ef..030f3c0c4dedf 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -6,7 +6,10 @@ struct S(i32); #[derive(Copy, Clone)] -struct BigStruct(S, u8, f32, S); +struct SmallStruct(f32, Option, &'static [f32]); + +#[derive(Copy, Clone)] +struct BigStruct(f32, Option, &'static [f64]); // EMIT_MIR struct.main.DataflowConstProp.diff fn main() { @@ -15,11 +18,21 @@ fn main() { s.0 = 3; let b = a + s.0; - const VAL: BigStruct = BigStruct(S(1), 5, 7., S(13)); - let BigStruct(a, b, c, d) = VAL; + const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); + let SmallStruct(a, b, c) = SMALL_VAL; + + static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); + let SmallStruct(a, b, c) = *SMALL_STAT; + + let ss = SmallStruct(a, b, c); + + const BIG_VAL: BigStruct = BigStruct(25., None, &[]); + let BigStruct(a, b, c) = BIG_VAL; - static STAT: &BigStruct = &BigStruct(S(1), 5, 7., S(13)); - let BigStruct(a, b, c, d) = *STAT; + static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); + let BigStruct(a, b, c) = *BIG_STAT; - let bs = BigStruct(a, b, c, d); + // We arbitrarily limit the size of synthetized values to 4 pointers. + // `BigStruct` can be read, but we will keep a MIR aggregate for this. + let bs = BigStruct(a, b, c); } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.rs b/tests/mir-opt/dataflow-const-prop/transmute.rs index 02e4f1e501346..bb85e4586787e 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.rs +++ b/tests/mir-opt/dataflow-const-prop/transmute.rs @@ -52,8 +52,8 @@ pub unsafe fn undef_union_as_integer() -> u32 { // EMIT_MIR transmute.unreachable_direct.DataflowConstProp.diff pub unsafe fn unreachable_direct() -> ! { // CHECK-LABEL: fn unreachable_direct( - // CHECK: [[unit:_.*]] = (); - // CHECK: move [[unit]] as Never (Transmute); + // CHECK: = const (); + // CHECK: = const ZeroSized: Never; let x: Never = unsafe { transmute(()) }; match x {} } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff index fc0634b1f8fc9..fb28aa8f6d9cf 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff @@ -11,8 +11,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = Union32 { value: move _2 }; +- _2 = (); +- _1 = Union32 { value: move _2 }; ++ _2 = const (); ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff index fc0634b1f8fc9..fb28aa8f6d9cf 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff @@ -11,8 +11,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = Union32 { value: move _2 }; +- _2 = (); +- _1 = Union32 { value: move _2 }; ++ _2 = const (); ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff index acbb5cd1bc733..c8d4d6edba1e8 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff index acbb5cd1bc733..c8d4d6edba1e8 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff similarity index 80% rename from tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff rename to tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff index 21c9b9d1eb96f..f5723cac7d9c8 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff @@ -33,7 +33,7 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32, const 2_i32); -+ _1 = const (1, 2); ++ _1 = const (1_i32, 2_i32); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -50,7 +50,7 @@ + _2 = const 6_i32; StorageDead(_3); - _1 = (const 2_i32, const 3_i32); -+ _1 = const (2, 3); ++ _1 = const (2_i32, 3_i32); StorageLive(_6); StorageLive(_7); StorageLive(_8); @@ -76,12 +76,12 @@ + _12 = const 6_i32; StorageLive(_13); - _13 = _1; -+ _13 = const (2, 3); ++ _13 = const (2_i32, 3_i32); StorageLive(_14); - _14 = _6; - _11 = (move _12, move _13, move _14); + _14 = const 11_i32; -+ _11 = const (6, (2, 3), 11); ++ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); StorageDead(_14); StorageDead(_13); StorageDead(_12); @@ -92,5 +92,21 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC2 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff new file mode 100644 index 0000000000000..f5723cac7d9c8 --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff @@ -0,0 +1,112 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let mut _1: (i32, i32); + let mut _3: i32; + let mut _4: i32; + let mut _5: i32; + let mut _7: i32; + let mut _8: i32; + let mut _9: i32; + let mut _10: i32; + let mut _12: i32; + let mut _13: (i32, i32); + let mut _14: i32; + scope 1 { + debug a => _1; + let _2: i32; + scope 2 { + debug b => _2; + let _6: i32; + scope 3 { + debug c => _6; + let _11: (i32, (i32, i32), i32); + scope 4 { + debug d => _11; + } + } + } + } + + bb0: { + StorageLive(_1); +- _1 = (const 1_i32, const 2_i32); ++ _1 = const (1_i32, 2_i32); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); +- _4 = (_1.0: i32); ++ _4 = const 1_i32; + StorageLive(_5); +- _5 = (_1.1: i32); +- _3 = Add(move _4, move _5); ++ _5 = const 2_i32; ++ _3 = const 3_i32; + StorageDead(_5); + StorageDead(_4); +- _2 = Add(move _3, const 3_i32); ++ _2 = const 6_i32; + StorageDead(_3); +- _1 = (const 2_i32, const 3_i32); ++ _1 = const (2_i32, 3_i32); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = (_1.0: i32); ++ _8 = const 2_i32; + StorageLive(_9); +- _9 = (_1.1: i32); +- _7 = Add(move _8, move _9); ++ _9 = const 3_i32; ++ _7 = const 5_i32; + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); +- _10 = _2; +- _6 = Add(move _7, move _10); ++ _10 = const 6_i32; ++ _6 = const 11_i32; + StorageDead(_10); + StorageDead(_7); + StorageLive(_11); + StorageLive(_12); +- _12 = _2; ++ _12 = const 6_i32; + StorageLive(_13); +- _13 = _1; ++ _13 = const (2_i32, 3_i32); + StorageLive(_14); +- _14 = _6; +- _11 = (move _12, move _13, move _14); ++ _14 = const 11_i32; ++ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + _0 = const (); + StorageDead(_11); + StorageDead(_6); + StorageDead(_2); + StorageDead(_1); + return; + } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC2 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 01 00 00 00 02 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index 7691bc8d7c504..bb706eafe8885 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,5 +1,6 @@ // skip-filecheck // unit-test: DataflowConstProp +// EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff fn main() {