Skip to content

Commit ac276e4

Browse files
committed
Generate ValTrees in DataflowConstProp.
1 parent cee9ed8 commit ac276e4

16 files changed

+236
-50
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

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

556649
fn make_operand(&self, literal: ConstantKind<'tcx>) -> Operand<'tcx> {

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

+3-2
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

+2-2
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

+2-2
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

+2-1
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

+2-1
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

+2-1
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

+2-1
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

+1-1
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

+1-1
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

tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
bb0: {
1919
StorageLive(_1);
20-
_1 = I32(const 0_i32);
20+
- _1 = I32(const 0_i32);
21+
+ _1 = const I32(0);
2122
StorageLive(_2);
2223
StorageLive(_3);
2324
StorageLive(_4);
@@ -31,7 +32,7 @@
3132
StorageDead(_5);
3233
StorageDead(_4);
3334
- _2 = I32(move _3);
34-
+ _2 = I32(const 0_i32);
35+
+ _2 = const I32(0);
3536
StorageDead(_3);
3637
_0 = const ();
3738
StorageDead(_2);

tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff

+44-15
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,15 @@
99
let mut _6: i32;
1010
let mut _11: BigStruct;
1111
let mut _16: &&BigStruct;
12-
let mut _17: &BigStruct;
13-
let mut _18: &BigStruct;
14-
let mut _19: &BigStruct;
15-
let mut _20: &BigStruct;
16-
let mut _21: &BigStruct;
12+
let mut _18: S;
13+
let mut _19: u8;
14+
let mut _20: f32;
15+
let mut _21: S;
16+
let mut _22: &BigStruct;
17+
let mut _23: &BigStruct;
18+
let mut _24: &BigStruct;
19+
let mut _25: &BigStruct;
20+
let mut _26: &BigStruct;
1721
scope 1 {
1822
debug s => _1;
1923
let _2: i32;
@@ -40,6 +44,10 @@
4044
debug b => _13;
4145
debug c => _14;
4246
debug d => _15;
47+
let _17: BigStruct;
48+
scope 6 {
49+
debug bs => _17;
50+
}
4351
}
4452
}
4553
}
@@ -48,7 +56,8 @@
4856

4957
bb0: {
5058
StorageLive(_1);
51-
_1 = S(const 1_i32);
59+
- _1 = S(const 1_i32);
60+
+ _1 = const S(1);
5261
StorageLive(_2);
5362
StorageLive(_3);
5463
- _3 = (_1.0: i32);
@@ -85,25 +94,45 @@
8594
StorageDead(_11);
8695
StorageLive(_16);
8796
_16 = const {alloc1: &&BigStruct};
88-
_17 = deref_copy (*_16);
97+
_22 = deref_copy (*_16);
8998
StorageLive(_12);
90-
_18 = deref_copy (*_16);
91-
- _12 = ((*_18).0: S);
99+
_23 = deref_copy (*_16);
100+
- _12 = ((*_23).0: S);
92101
+ _12 = const S(1_i32);
93102
StorageLive(_13);
94-
_19 = deref_copy (*_16);
95-
- _13 = ((*_19).1: u8);
103+
_24 = deref_copy (*_16);
104+
- _13 = ((*_24).1: u8);
96105
+ _13 = const 5_u8;
97106
StorageLive(_14);
98-
_20 = deref_copy (*_16);
99-
- _14 = ((*_20).2: f32);
107+
_25 = deref_copy (*_16);
108+
- _14 = ((*_25).2: f32);
100109
+ _14 = const 7f32;
101110
StorageLive(_15);
102-
_21 = deref_copy (*_16);
103-
- _15 = ((*_21).3: S);
111+
_26 = deref_copy (*_16);
112+
- _15 = ((*_26).3: S);
104113
+ _15 = const S(13_i32);
105114
StorageDead(_16);
115+
StorageLive(_17);
116+
StorageLive(_18);
117+
- _18 = _12;
118+
+ _18 = const S(1_i32);
119+
StorageLive(_19);
120+
- _19 = _13;
121+
+ _19 = const 5_u8;
122+
StorageLive(_20);
123+
- _20 = _14;
124+
+ _20 = const 7f32;
125+
StorageLive(_21);
126+
- _21 = _15;
127+
- _17 = BigStruct(move _18, move _19, move _20, move _21);
128+
+ _21 = const S(13_i32);
129+
+ _17 = const BigStruct(S(1), 5, 7f32, S(13));
130+
StorageDead(_21);
131+
StorageDead(_20);
132+
StorageDead(_19);
133+
StorageDead(_18);
106134
_0 = const ();
135+
StorageDead(_17);
107136
StorageDead(_15);
108137
StorageDead(_14);
109138
StorageDead(_13);

0 commit comments

Comments
 (0)