Skip to content

Commit 27acd92

Browse files
committed
Extract simplify_aggregate.
1 parent e58d794 commit 27acd92

File tree

4 files changed

+198
-27
lines changed

4 files changed

+198
-27
lines changed

compiler/rustc_mir_transform/src/gvn.rs

+56-27
Original file line numberDiff line numberDiff line change
@@ -673,33 +673,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
673673
Value::Repeat(op, amount)
674674
}
675675
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
676-
Rvalue::Aggregate(box ref kind, ref mut fields) => {
677-
let (ty, variant_index) = match *kind {
678-
// For empty arrays, we have not mean to recover the type. They are ZSTs
679-
// anyway, so return them as such.
680-
AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
681-
return Some(self.insert(Value::Constant(Const::zero_sized(
682-
rvalue.ty(self.local_decls, self.tcx),
683-
))));
684-
}
685-
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
686-
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
687-
AggregateKind::Closure(did, substs)
688-
| AggregateKind::Generator(did, substs, _) => {
689-
(AggregateTy::Def(did, substs), FIRST_VARIANT)
690-
}
691-
AggregateKind::Adt(did, variant_index, substs, _, None) => {
692-
(AggregateTy::Def(did, substs), variant_index)
693-
}
694-
// Do not track unions.
695-
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
696-
};
697-
let fields: Option<Vec<_>> = fields
698-
.iter_mut()
699-
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
700-
.collect();
701-
Value::Aggregate(ty, variant_index, fields?)
702-
}
676+
Rvalue::Aggregate(..) => self.simplify_aggregate(rvalue, location)?,
703677
Rvalue::Ref(_, borrow_kind, ref mut place) => {
704678
self.simplify_place_projection(place, location);
705679
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
@@ -760,6 +734,61 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
760734

761735
None
762736
}
737+
738+
fn simplify_aggregate(
739+
&mut self,
740+
rvalue: &mut Rvalue<'tcx>,
741+
location: Location,
742+
) -> Option<Value<'tcx>> {
743+
let Rvalue::Aggregate(box ref kind, ref mut fields) = *rvalue else { bug!() };
744+
745+
let tcx = self.tcx;
746+
if fields.is_empty() {
747+
let is_zst = match *kind {
748+
AggregateKind::Array(..) | AggregateKind::Tuple | AggregateKind::Closure(..) => {
749+
true
750+
}
751+
// Only enums can be non-ZST.
752+
AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum,
753+
// Generators are never ZST, as they at least contain the implicit states.
754+
AggregateKind::Generator(..) => false,
755+
};
756+
757+
if is_zst {
758+
let ty = rvalue.ty(self.local_decls, tcx);
759+
let value = Value::Constant(Const::zero_sized(ty));
760+
return Some(value);
761+
}
762+
}
763+
764+
let (ty, variant_index) = match *kind {
765+
AggregateKind::Array(..) => {
766+
assert!(!fields.is_empty());
767+
(AggregateTy::Array, FIRST_VARIANT)
768+
}
769+
AggregateKind::Tuple => {
770+
assert!(!fields.is_empty());
771+
(AggregateTy::Tuple, FIRST_VARIANT)
772+
}
773+
AggregateKind::Closure(did, substs) | AggregateKind::Generator(did, substs, _) => {
774+
(AggregateTy::Def(did, substs), FIRST_VARIANT)
775+
}
776+
AggregateKind::Adt(did, variant_index, substs, _, None) => {
777+
(AggregateTy::Def(did, substs), variant_index)
778+
}
779+
// Do not track unions.
780+
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
781+
};
782+
783+
let fields: Option<Vec<_>> = fields
784+
.iter_mut()
785+
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
786+
.collect();
787+
let fields = fields?;
788+
789+
let value = Value::Aggregate(ty, variant_index, fields);
790+
Some(value)
791+
}
763792
}
764793

765794
fn op_to_prop_const<'tcx>(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
- // MIR for `aggregates` before GVN
2+
+ // MIR for `aggregates` after GVN
3+
4+
fn aggregates() -> () {
5+
let mut _0: ();
6+
let _1: S<[u8; 0]>;
7+
let mut _2: [u8; 0];
8+
let mut _4: [u16; 0];
9+
let mut _6: ();
10+
let mut _8: ();
11+
scope 1 {
12+
debug a_array => _1;
13+
let _3: S<[u16; 0]>;
14+
scope 2 {
15+
debug b_array => _3;
16+
let _5: S<()>;
17+
scope 3 {
18+
debug a_tuple => _5;
19+
let _7: S<()>;
20+
scope 4 {
21+
debug b_tuple => _7;
22+
}
23+
}
24+
}
25+
}
26+
27+
bb0: {
28+
StorageLive(_1);
29+
StorageLive(_2);
30+
- _2 = [];
31+
- _1 = S::<[u8; 0]>(move _2);
32+
+ _2 = const [];
33+
+ _1 = const S::<[u8; 0]>([]);
34+
StorageDead(_2);
35+
StorageLive(_3);
36+
StorageLive(_4);
37+
- _4 = [];
38+
- _3 = S::<[u16; 0]>(move _4);
39+
+ _4 = const [];
40+
+ _3 = const S::<[u16; 0]>([]);
41+
StorageDead(_4);
42+
StorageLive(_5);
43+
- StorageLive(_6);
44+
- _6 = ();
45+
- _5 = S::<()>(move _6);
46+
- StorageDead(_6);
47+
+ nop;
48+
+ _6 = const ();
49+
+ _5 = const S::<()>(());
50+
+ nop;
51+
StorageLive(_7);
52+
StorageLive(_8);
53+
- _8 = ();
54+
- _7 = S::<()>(move _8);
55+
+ _8 = const ();
56+
+ _7 = const S::<()>(());
57+
StorageDead(_8);
58+
_0 = const ();
59+
StorageDead(_7);
60+
StorageDead(_5);
61+
StorageDead(_3);
62+
StorageDead(_1);
63+
return;
64+
}
65+
}
66+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
- // MIR for `aggregates` before GVN
2+
+ // MIR for `aggregates` after GVN
3+
4+
fn aggregates() -> () {
5+
let mut _0: ();
6+
let _1: S<[u8; 0]>;
7+
let mut _2: [u8; 0];
8+
let mut _4: [u16; 0];
9+
let mut _6: ();
10+
let mut _8: ();
11+
scope 1 {
12+
debug a_array => _1;
13+
let _3: S<[u16; 0]>;
14+
scope 2 {
15+
debug b_array => _3;
16+
let _5: S<()>;
17+
scope 3 {
18+
debug a_tuple => _5;
19+
let _7: S<()>;
20+
scope 4 {
21+
debug b_tuple => _7;
22+
}
23+
}
24+
}
25+
}
26+
27+
bb0: {
28+
StorageLive(_1);
29+
StorageLive(_2);
30+
- _2 = [];
31+
- _1 = S::<[u8; 0]>(move _2);
32+
+ _2 = const [];
33+
+ _1 = const S::<[u8; 0]>([]);
34+
StorageDead(_2);
35+
StorageLive(_3);
36+
StorageLive(_4);
37+
- _4 = [];
38+
- _3 = S::<[u16; 0]>(move _4);
39+
+ _4 = const [];
40+
+ _3 = const S::<[u16; 0]>([]);
41+
StorageDead(_4);
42+
StorageLive(_5);
43+
- StorageLive(_6);
44+
- _6 = ();
45+
- _5 = S::<()>(move _6);
46+
- StorageDead(_6);
47+
+ nop;
48+
+ _6 = const ();
49+
+ _5 = const S::<()>(());
50+
+ nop;
51+
StorageLive(_7);
52+
StorageLive(_8);
53+
- _8 = ();
54+
- _7 = S::<()>(move _8);
55+
+ _8 = const ();
56+
+ _7 = const S::<()>(());
57+
StorageDead(_8);
58+
_0 = const ();
59+
StorageDead(_7);
60+
StorageDead(_5);
61+
StorageDead(_3);
62+
StorageDead(_1);
63+
return;
64+
}
65+
}
66+

tests/mir-opt/gvn.rs

+10
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,14 @@ fn slices() {
230230
assert_eq!(s.as_ptr(), u.as_ptr());
231231
}
232232

233+
fn aggregates() {
234+
let a_array: S<[u8; 0]> = S([]);
235+
let b_array: S<[u16; 0]> = S([]); // This must not be merged with `a_array`.
236+
237+
let a_tuple: S<()> = S(());
238+
let b_tuple: S<()> = S(()); // But this can be with `a_tuple`.
239+
}
240+
233241
fn main() {
234242
subexpression_elimination(2, 4, 5);
235243
wrap_unwrap(5);
@@ -242,6 +250,7 @@ fn main() {
242250
references(5);
243251
dereferences(&mut 5, &6, &S(7));
244252
slices();
253+
aggregates();
245254
}
246255

247256
#[inline(never)]
@@ -258,3 +267,4 @@ fn opaque(_: impl Sized) {}
258267
// EMIT_MIR gvn.references.GVN.diff
259268
// EMIT_MIR gvn.dereferences.GVN.diff
260269
// EMIT_MIR gvn.slices.GVN.diff
270+
// EMIT_MIR gvn.aggregates.GVN.diff

0 commit comments

Comments
 (0)