Extract simplify_aggregate.
This commit is contained in:
parent
23d4857080
commit
80a5e8522d
@ -682,33 +682,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
Value::Repeat(op, amount)
|
||||
}
|
||||
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
|
||||
Rvalue::Aggregate(box ref kind, ref mut fields) => {
|
||||
let (ty, variant_index) = match *kind {
|
||||
// For empty arrays, we have not mean to recover the type. They are ZSTs
|
||||
// anyway, so return them as such.
|
||||
AggregateKind::Array(..) | AggregateKind::Tuple if fields.is_empty() => {
|
||||
return Some(self.insert(Value::Constant(Const::zero_sized(
|
||||
rvalue.ty(self.local_decls, self.tcx),
|
||||
))));
|
||||
}
|
||||
AggregateKind::Array(..) => (AggregateTy::Array, FIRST_VARIANT),
|
||||
AggregateKind::Tuple => (AggregateTy::Tuple, FIRST_VARIANT),
|
||||
AggregateKind::Closure(did, substs)
|
||||
| AggregateKind::Coroutine(did, substs, _) => {
|
||||
(AggregateTy::Def(did, substs), FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Adt(did, variant_index, substs, _, None) => {
|
||||
(AggregateTy::Def(did, substs), variant_index)
|
||||
}
|
||||
// Do not track unions.
|
||||
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
|
||||
};
|
||||
let fields: Option<Vec<_>> = fields
|
||||
.iter_mut()
|
||||
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
|
||||
.collect();
|
||||
Value::Aggregate(ty, variant_index, fields?)
|
||||
}
|
||||
Rvalue::Aggregate(..) => self.simplify_aggregate(rvalue, location)?,
|
||||
Rvalue::Ref(_, borrow_kind, ref mut place) => {
|
||||
self.simplify_place_projection(place, location);
|
||||
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
|
||||
@ -769,6 +743,61 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn simplify_aggregate(
|
||||
&mut self,
|
||||
rvalue: &mut Rvalue<'tcx>,
|
||||
location: Location,
|
||||
) -> Option<Value<'tcx>> {
|
||||
let Rvalue::Aggregate(box ref kind, ref mut fields) = *rvalue else { bug!() };
|
||||
|
||||
let tcx = self.tcx;
|
||||
if fields.is_empty() {
|
||||
let is_zst = match *kind {
|
||||
AggregateKind::Array(..) | AggregateKind::Tuple | AggregateKind::Closure(..) => {
|
||||
true
|
||||
}
|
||||
// Only enums can be non-ZST.
|
||||
AggregateKind::Adt(did, ..) => tcx.def_kind(did) != DefKind::Enum,
|
||||
// Coroutines are never ZST, as they at least contain the implicit states.
|
||||
AggregateKind::Coroutine(..) => false,
|
||||
};
|
||||
|
||||
if is_zst {
|
||||
let ty = rvalue.ty(self.local_decls, tcx);
|
||||
let value = Value::Constant(Const::zero_sized(ty));
|
||||
return Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
let (ty, variant_index) = match *kind {
|
||||
AggregateKind::Array(..) => {
|
||||
assert!(!fields.is_empty());
|
||||
(AggregateTy::Array, FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Tuple => {
|
||||
assert!(!fields.is_empty());
|
||||
(AggregateTy::Tuple, FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Closure(did, substs) | AggregateKind::Coroutine(did, substs, _) => {
|
||||
(AggregateTy::Def(did, substs), FIRST_VARIANT)
|
||||
}
|
||||
AggregateKind::Adt(did, variant_index, substs, _, None) => {
|
||||
(AggregateTy::Def(did, substs), variant_index)
|
||||
}
|
||||
// Do not track unions.
|
||||
AggregateKind::Adt(_, _, _, _, Some(_)) => return None,
|
||||
};
|
||||
|
||||
let fields: Option<Vec<_>> = fields
|
||||
.iter_mut()
|
||||
.map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque()))
|
||||
.collect();
|
||||
let fields = fields?;
|
||||
|
||||
let value = Value::Aggregate(ty, variant_index, fields);
|
||||
Some(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn op_to_prop_const<'tcx>(
|
||||
|
66
tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff
Normal file
66
tests/mir-opt/gvn.aggregates.GVN.panic-abort.diff
Normal file
@ -0,0 +1,66 @@
|
||||
- // MIR for `aggregates` before GVN
|
||||
+ // MIR for `aggregates` after GVN
|
||||
|
||||
fn aggregates() -> () {
|
||||
let mut _0: ();
|
||||
let _1: S<[u8; 0]>;
|
||||
let mut _2: [u8; 0];
|
||||
let mut _4: [u16; 0];
|
||||
let mut _6: ();
|
||||
let mut _8: ();
|
||||
scope 1 {
|
||||
debug a_array => _1;
|
||||
let _3: S<[u16; 0]>;
|
||||
scope 2 {
|
||||
debug b_array => _3;
|
||||
let _5: S<()>;
|
||||
scope 3 {
|
||||
debug a_tuple => _5;
|
||||
let _7: S<()>;
|
||||
scope 4 {
|
||||
debug b_tuple => _7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
- _2 = [];
|
||||
- _1 = S::<[u8; 0]>(move _2);
|
||||
+ _2 = const [];
|
||||
+ _1 = const S::<[u8; 0]>([]);
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
- _4 = [];
|
||||
- _3 = S::<[u16; 0]>(move _4);
|
||||
+ _4 = const [];
|
||||
+ _3 = const S::<[u16; 0]>([]);
|
||||
StorageDead(_4);
|
||||
StorageLive(_5);
|
||||
- StorageLive(_6);
|
||||
- _6 = ();
|
||||
- _5 = S::<()>(move _6);
|
||||
- StorageDead(_6);
|
||||
+ nop;
|
||||
+ _6 = const ();
|
||||
+ _5 = const S::<()>(());
|
||||
+ nop;
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
- _8 = ();
|
||||
- _7 = S::<()>(move _8);
|
||||
+ _8 = const ();
|
||||
+ _7 = const S::<()>(());
|
||||
StorageDead(_8);
|
||||
_0 = const ();
|
||||
StorageDead(_7);
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
66
tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff
Normal file
66
tests/mir-opt/gvn.aggregates.GVN.panic-unwind.diff
Normal file
@ -0,0 +1,66 @@
|
||||
- // MIR for `aggregates` before GVN
|
||||
+ // MIR for `aggregates` after GVN
|
||||
|
||||
fn aggregates() -> () {
|
||||
let mut _0: ();
|
||||
let _1: S<[u8; 0]>;
|
||||
let mut _2: [u8; 0];
|
||||
let mut _4: [u16; 0];
|
||||
let mut _6: ();
|
||||
let mut _8: ();
|
||||
scope 1 {
|
||||
debug a_array => _1;
|
||||
let _3: S<[u16; 0]>;
|
||||
scope 2 {
|
||||
debug b_array => _3;
|
||||
let _5: S<()>;
|
||||
scope 3 {
|
||||
debug a_tuple => _5;
|
||||
let _7: S<()>;
|
||||
scope 4 {
|
||||
debug b_tuple => _7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bb0: {
|
||||
StorageLive(_1);
|
||||
StorageLive(_2);
|
||||
- _2 = [];
|
||||
- _1 = S::<[u8; 0]>(move _2);
|
||||
+ _2 = const [];
|
||||
+ _1 = const S::<[u8; 0]>([]);
|
||||
StorageDead(_2);
|
||||
StorageLive(_3);
|
||||
StorageLive(_4);
|
||||
- _4 = [];
|
||||
- _3 = S::<[u16; 0]>(move _4);
|
||||
+ _4 = const [];
|
||||
+ _3 = const S::<[u16; 0]>([]);
|
||||
StorageDead(_4);
|
||||
StorageLive(_5);
|
||||
- StorageLive(_6);
|
||||
- _6 = ();
|
||||
- _5 = S::<()>(move _6);
|
||||
- StorageDead(_6);
|
||||
+ nop;
|
||||
+ _6 = const ();
|
||||
+ _5 = const S::<()>(());
|
||||
+ nop;
|
||||
StorageLive(_7);
|
||||
StorageLive(_8);
|
||||
- _8 = ();
|
||||
- _7 = S::<()>(move _8);
|
||||
+ _8 = const ();
|
||||
+ _7 = const S::<()>(());
|
||||
StorageDead(_8);
|
||||
_0 = const ();
|
||||
StorageDead(_7);
|
||||
StorageDead(_5);
|
||||
StorageDead(_3);
|
||||
StorageDead(_1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -231,6 +231,14 @@ fn slices() {
|
||||
assert_eq!(s.as_ptr(), u.as_ptr());
|
||||
}
|
||||
|
||||
fn aggregates() {
|
||||
let a_array: S<[u8; 0]> = S([]);
|
||||
let b_array: S<[u16; 0]> = S([]); // This must not be merged with `a_array`.
|
||||
|
||||
let a_tuple: S<()> = S(());
|
||||
let b_tuple: S<()> = S(()); // But this can be with `a_tuple`.
|
||||
}
|
||||
|
||||
fn main() {
|
||||
subexpression_elimination(2, 4, 5);
|
||||
wrap_unwrap(5);
|
||||
@ -243,6 +251,7 @@ fn main() {
|
||||
references(5);
|
||||
dereferences(&mut 5, &6, &S(7));
|
||||
slices();
|
||||
aggregates();
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
@ -259,3 +268,4 @@ fn opaque(_: impl Sized) {}
|
||||
// EMIT_MIR gvn.references.GVN.diff
|
||||
// EMIT_MIR gvn.dereferences.GVN.diff
|
||||
// EMIT_MIR gvn.slices.GVN.diff
|
||||
// EMIT_MIR gvn.aggregates.GVN.diff
|
||||
|
Loading…
x
Reference in New Issue
Block a user