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)
|
Value::Repeat(op, amount)
|
||||||
}
|
}
|
||||||
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
|
Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty),
|
||||||
Rvalue::Aggregate(box ref kind, ref mut fields) => {
|
Rvalue::Aggregate(..) => self.simplify_aggregate(rvalue, location)?,
|
||||||
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::Ref(_, borrow_kind, ref mut place) => {
|
Rvalue::Ref(_, borrow_kind, ref mut place) => {
|
||||||
self.simplify_place_projection(place, location);
|
self.simplify_place_projection(place, location);
|
||||||
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
|
return self.new_pointer(*place, AddressKind::Ref(borrow_kind));
|
||||||
@ -769,6 +743,61 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
|
|||||||
|
|
||||||
None
|
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>(
|
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());
|
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() {
|
fn main() {
|
||||||
subexpression_elimination(2, 4, 5);
|
subexpression_elimination(2, 4, 5);
|
||||||
wrap_unwrap(5);
|
wrap_unwrap(5);
|
||||||
@ -243,6 +251,7 @@ fn main() {
|
|||||||
references(5);
|
references(5);
|
||||||
dereferences(&mut 5, &6, &S(7));
|
dereferences(&mut 5, &6, &S(7));
|
||||||
slices();
|
slices();
|
||||||
|
aggregates();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
@ -259,3 +268,4 @@ fn opaque(_: impl Sized) {}
|
|||||||
// EMIT_MIR gvn.references.GVN.diff
|
// EMIT_MIR gvn.references.GVN.diff
|
||||||
// EMIT_MIR gvn.dereferences.GVN.diff
|
// EMIT_MIR gvn.dereferences.GVN.diff
|
||||||
// EMIT_MIR gvn.slices.GVN.diff
|
// EMIT_MIR gvn.slices.GVN.diff
|
||||||
|
// EMIT_MIR gvn.aggregates.GVN.diff
|
||||||
|
Loading…
x
Reference in New Issue
Block a user