]> git.lizzy.rs Git - rust.git/blobdiff - compiler/rustc_mir/src/transform/early_otherwise_branch.rs
Shrink the size of Rvalue by 16 bytes
[rust.git] / compiler / rustc_mir / src / transform / early_otherwise_branch.rs
index 6fbcc140978a7039e7886a0d3730dd3fbaa74041..1128599876cb76723e1872f2d8fac6b6090a7ae8 100644 (file)
@@ -91,8 +91,10 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
                 opt_to_apply.infos[0].first_switch_info.discr_used_in_switch;
             let not_equal_rvalue = Rvalue::BinaryOp(
                 not_equal,
-                Operand::Copy(Place::from(second_discriminant_temp)),
-                Operand::Copy(first_descriminant_place),
+                box (
+                    Operand::Copy(Place::from(second_discriminant_temp)),
+                    Operand::Copy(first_descriminant_place),
+                ),
             );
             patch.add_statement(
                 end_of_block_location,
@@ -284,6 +286,33 @@ fn find_discriminant_switch_pairing(
                 return None;
             }
 
+            // when the second place is a projection of the first one, it's not safe to calculate their discriminant values sequentially.
+            // for example, this should not be optimized:
+            //
+            // ```rust
+            // enum E<'a> { Empty, Some(&'a E<'a>), }
+            // let Some(Some(_)) = e;
+            // ```
+            //
+            // ```mir
+            // bb0: {
+            //   _2 = discriminant(*_1)
+            //   switchInt(_2) -> [...]
+            // }
+            // bb1: {
+            //   _3 = discriminant(*(((*_1) as Some).0: &E))
+            //   switchInt(_3) -> [...]
+            // }
+            // ```
+            let discr_place = discr_info.place_of_adt_discr_read;
+            let this_discr_place = this_bb_discr_info.place_of_adt_discr_read;
+            if discr_place.local == this_discr_place.local
+                && this_discr_place.projection.starts_with(discr_place.projection)
+            {
+                trace!("NO: one target is the projection of another");
+                return None;
+            }
+
             // if we reach this point, the optimization applies, and we should be able to optimize this case
             // store the info that is needed to apply the optimization