Skip to content

Commit 85eae44

Browse files
committed
Extract simplify_aggregate.
1 parent 9739fc2 commit 85eae44

File tree

4 files changed

+198
-27
lines changed

4 files changed

+198
-27
lines changed

compiler/rustc_mir_transform/src/gvn.rs

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

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

767796
fn op_to_prop_const<'tcx>(
Lines changed: 66 additions & 0 deletions
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+
Lines changed: 66 additions & 0 deletions
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

Lines changed: 10 additions & 0 deletions
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)