about summary refs log tree commit diff
path: root/compiler/rustc_mir_transform
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-05-21 12:59:38 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-10-25 06:46:47 +0000
commit80a5e8522de648d70a9ef1dfba7621f730832fb3 (patch)
treec4d05921cef957fd40b7b502e3ea2f919b7dbb25 /compiler/rustc_mir_transform
parent23d4857080a3968447adbb1d55b2720dba46d666 (diff)
downloadrust-80a5e8522de648d70a9ef1dfba7621f730832fb3.tar.gz
rust-80a5e8522de648d70a9ef1dfba7621f730832fb3.zip
Extract simplify_aggregate.
Diffstat (limited to 'compiler/rustc_mir_transform')
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs83
1 files changed, 56 insertions, 27 deletions
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 9880e239957..bbcb39226b7 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -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>(