about summary refs log tree commit diff
path: root/src/librustc/ty
diff options
context:
space:
mode:
authorTyler Mandry <tmandry@gmail.com>2019-07-26 17:13:14 -0700
committerTyler Mandry <tmandry@gmail.com>2019-08-06 14:16:47 -0700
commitb40788e89fac38781ddb838bb4fb0d706a6a3546 (patch)
treec47d72ff91fdeefe0ab916d283e0c4bef3a3f7d5 /src/librustc/ty
parent9d4ca879b88e3a21354dcda458d7e7f7ff6370b2 (diff)
downloadrust-b40788e89fac38781ddb838bb4fb0d706a6a3546.tar.gz
rust-b40788e89fac38781ddb838bb4fb0d706a6a3546.zip
Fix generator size regressions due to optimization
I tested the generator optimizations in #60187 and #61922 on the Fuchsia
build, and noticed that some small generators (about 8% of the async fns
in our build) increased in size slightly.

This is because in #60187 we split the fields into two groups, a
"prefix" non-overlap region and an overlap region, and lay them out
separately. This can introduce unnecessary padding bytes between the two
groups.

In every single case in the Fuchsia build, it was due to there being
only a single variant being used in the overlap region. This means that
we aren't doing any overlapping, period. So it's better to combine the
two regions into one and lay out all the fields at once, which is what
this change does.
Diffstat (limited to 'src/librustc/ty')
-rw-r--r--src/librustc/ty/layout.rs21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 03b95bc3a94..1908cc6c1e8 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -1368,6 +1368,27 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             }
         }
 
+        // Count the number of variants in use. If only one of them, then it is
+        // impossible to overlap any locals in our layout. In this case it's
+        // always better to make the remaining locals ineligible, so we can
+        // lay them out with the other locals in the prefix and eliminate
+        // unnecessary padding bytes.
+        {
+            let mut used_variants = BitSet::new_empty(info.variant_fields.len());
+            for assignment in &assignments {
+                match assignment {
+                    Assigned(idx) => { used_variants.insert(*idx); }
+                    _ => {}
+                }
+            }
+            if used_variants.count() < 2 {
+                for assignment in assignments.iter_mut() {
+                    *assignment = Ineligible(None);
+                }
+                ineligible_locals.insert_all();
+            }
+        }
+
         // Write down the order of our locals that will be promoted to the prefix.
         {
             let mut idx = 0u32;