Skip to content

Commit 7f65502

Browse files
committed
Generate ValTrees in DataflowConstProp.
1 parent eb2446a commit 7f65502

16 files changed

+237
-50
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,105 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> {
550550
state: &State<FlatSet<Scalar>>,
551551
map: &Map,
552552
) -> Option<ConstantKind<'tcx>> {
553-
let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else {
554-
return None;
555-
};
556553
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
557-
Some(ConstantKind::Val(ConstValue::Scalar(value.into()), ty))
554+
let place = map.find(place.as_ref())?;
555+
if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) {
556+
Some(ConstantKind::Val(ConstValue::Scalar(value.into()), ty))
557+
} else {
558+
let valtree = self.try_make_valtree(place, ty, state, map)?;
559+
let constant = ty::Const::new_value(self.patch.tcx, valtree, ty);
560+
Some(ConstantKind::Ty(constant))
561+
}
562+
}
563+
564+
fn try_make_valtree(
565+
&self,
566+
place: PlaceIndex,
567+
ty: Ty<'tcx>,
568+
state: &State<FlatSet<Scalar>>,
569+
map: &Map,
570+
) -> Option<ty::ValTree<'tcx>> {
571+
let tcx = self.patch.tcx;
572+
match ty.kind() {
573+
// ZSTs.
574+
ty::FnDef(..) => Some(ty::ValTree::zst()),
575+
576+
// Scalars.
577+
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => {
578+
if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) {
579+
Some(ty::ValTree::Leaf(value))
580+
} else {
581+
None
582+
}
583+
}
584+
585+
// Unsupported for now.
586+
ty::Array(_, _) => None,
587+
588+
ty::Tuple(elem_tys) => {
589+
let branches = elem_tys
590+
.iter()
591+
.enumerate()
592+
.map(|(i, ty)| {
593+
let field = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i)))?;
594+
self.try_make_valtree(field, ty, state, map)
595+
})
596+
.collect::<Option<Vec<_>>>()?;
597+
Some(ty::ValTree::Branch(tcx.arena.alloc_from_iter(branches.into_iter())))
598+
}
599+
600+
ty::Adt(def, args) => {
601+
if def.is_union() {
602+
return None;
603+
}
604+
605+
let (variant_idx, variant_def, variant_place) = if def.is_enum() {
606+
let discr = map.apply(place, TrackElem::Discriminant)?;
607+
let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else {
608+
return None;
609+
};
610+
let discr_bits = discr.assert_bits(discr.size());
611+
let (variant, _) =
612+
def.discriminants(tcx).find(|(_, var)| discr_bits == var.val)?;
613+
let variant_place = map.apply(place, TrackElem::Variant(variant))?;
614+
let variant_int = ty::ValTree::Leaf(variant.as_u32().into());
615+
(Some(variant_int), def.variant(variant), variant_place)
616+
} else {
617+
(None, def.non_enum_variant(), place)
618+
};
619+
620+
let branches = variant_def
621+
.fields
622+
.iter_enumerated()
623+
.map(|(i, field)| {
624+
let ty = field.ty(tcx, args);
625+
let field = map.apply(variant_place, TrackElem::Field(i))?;
626+
self.try_make_valtree(field, ty, state, map)
627+
})
628+
.collect::<Option<Vec<_>>>()?;
629+
Some(ty::ValTree::Branch(
630+
tcx.arena.alloc_from_iter(variant_idx.into_iter().chain(branches)),
631+
))
632+
}
633+
634+
// Do not attempt to support indirection in constants.
635+
ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) => None,
636+
637+
ty::Never
638+
| ty::Foreign(..)
639+
| ty::Alias(..)
640+
| ty::Param(_)
641+
| ty::Bound(..)
642+
| ty::Placeholder(..)
643+
| ty::Closure(..)
644+
| ty::Generator(..)
645+
| ty::Dynamic(..) => None,
646+
647+
ty::Error(_)
648+
| ty::Infer(..)
649+
| ty::GeneratorWitness(..)
650+
| ty::GeneratorWitnessMIR(..) => bug!(),
651+
}
558652
}
559653
}
560654

tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
+ debug ((f: (bool, bool, u32)).2: u32) => const 123_u32;
4242
let _10: std::option::Option<u16>;
4343
scope 7 {
44-
debug o => _10;
44+
- debug o => _10;
45+
+ debug o => const Option::<u16>::Some(99);
4546
let _17: u32;
4647
let _18: u32;
4748
scope 8 {
@@ -81,7 +82,7 @@
8182
_15 = const false;
8283
_16 = const 123_u32;
8384
StorageLive(_10);
84-
_10 = Option::<u16>::Some(const 99_u16);
85+
_10 = const Option::<u16>::Some(99);
8586
_17 = const 32_u32;
8687
_18 = const 32_u32;
8788
StorageLive(_11);

tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
- _6 = CheckedAdd(_4, _5);
4444
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable];
4545
+ _5 = const 2_i32;
46-
+ _6 = CheckedAdd(const 1_i32, const 2_i32);
46+
+ _6 = const (3, false);
4747
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable];
4848
}
4949

@@ -60,7 +60,7 @@
6060
- _10 = CheckedAdd(_9, const 1_i32);
6161
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable];
6262
+ _9 = const i32::MAX;
63-
+ _10 = CheckedAdd(const i32::MAX, const 1_i32);
63+
+ _10 = const (i32::MIN, true);
6464
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind unreachable];
6565
}
6666

tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
- _6 = CheckedAdd(_4, _5);
4444
- assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue];
4545
+ _5 = const 2_i32;
46-
+ _6 = CheckedAdd(const 1_i32, const 2_i32);
46+
+ _6 = const (3, false);
4747
+ assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue];
4848
}
4949

@@ -60,7 +60,7 @@
6060
- _10 = CheckedAdd(_9, const 1_i32);
6161
- assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue];
6262
+ _9 = const i32::MAX;
63-
+ _10 = CheckedAdd(const i32::MAX, const 1_i32);
63+
+ _10 = const (i32::MIN, true);
6464
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind continue];
6565
}
6666

tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
bb0: {
2525
StorageLive(_1);
26-
_1 = E::V1(const 0_i32);
26+
- _1 = E::V1(const 0_i32);
27+
+ _1 = const E::V1(0);
2728
StorageLive(_2);
2829
- _3 = discriminant(_1);
2930
- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2];

tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@
2323

2424
bb0: {
2525
StorageLive(_1);
26-
_1 = E::V1(const 0_i32);
26+
- _1 = E::V1(const 0_i32);
27+
+ _1 = const E::V1(0);
2728
StorageLive(_2);
2829
- _3 = discriminant(_1);
2930
- switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2];

tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
StorageLive(_1);
4545
StorageLive(_2);
4646
_2 = const {alloc1: &E};
47-
_1 = (*_2);
47+
- _1 = (*_2);
48+
+ _1 = const E::V1(0);
4849
StorageDead(_2);
4950
StorageLive(_3);
5051
- _4 = discriminant(_1);

tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@
4444
StorageLive(_1);
4545
StorageLive(_2);
4646
_2 = const {alloc1: &E};
47-
_1 = (*_2);
47+
- _1 = (*_2);
48+
+ _1 = const E::V1(0);
4849
StorageDead(_2);
4950
StorageLive(_3);
5051
- _4 = discriminant(_1);

tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
_3 = const 1_u8;
2323
- _4 = CheckedAdd(_2, _3);
2424
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable];
25-
+ _4 = CheckedAdd(const u8::MAX, const 1_u8);
25+
+ _4 = const (0, true);
2626
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable];
2727
}
2828

tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
_3 = const 1_u8;
2323
- _4 = CheckedAdd(_2, _3);
2424
- assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue];
25-
+ _4 = CheckedAdd(const u8::MAX, const 1_u8);
25+
+ _4 = const (0, true);
2626
+ assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue];
2727
}
2828

0 commit comments

Comments
 (0)