Skip to content

Commit dcd9575

Browse files
committed
Extract simplify_aggregate.
1 parent c04c7e3 commit dcd9575

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
@@ -682,33 +682,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
682682
Value::Repeat(op, amount)
683683
}
684684
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
685-
Rvalue::Aggregate(box ref kind, ref mut fields) => {
686-
let (ty, variant_index) = match *kind {
687-
// For empty arrays, we have not mean to recover the type. They are ZSTs
688-
// anyway, so return them as such.
689-
AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
690-
return Some(self.insert(Value::Constant(Const::zero_sized(
691-
rvalue.ty(self.local_decls, self.tcx),
692-
))));
693-
}
694-
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
695-
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
696-
AggregateKind::Closure(did, substs)
697-
| AggregateKind::Generator(did, substs, _) => {
698-
(AggregateTy::Def(did, substs), FIRST_VARIANT)
699-
}
700-
AggregateKind::Adt(did, variant_index, substs, _, None) => {
701-
(AggregateTy::Def(did, substs), variant_index)
702-
}
703-
// Do not track unions.
704-
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
705-
};
706-
let fields: Option<Vec<_>> = fields
707-
.iter_mut()
708-
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
709-
.collect();
710-
Value::Aggregate(ty, variant_index, fields?)
711-
}
685+
Rvalue::Aggregate(..) => self.simplify_aggregate(rvalue, location)?,
712686
Rvalue::Ref(_, borrow_kind, ref mut place) => {
713687
self.simplify_place_projection(place, location);
714688
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
@@ -769,6 +743,61 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
769743

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

774803
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)