Skip to content

Commit

Permalink
TEMP FOR PERF: remove the optimization, leaving only the field reorde…
Browse files Browse the repository at this point in the history
…ring
  • Loading branch information
erikdesjardins committed Sep 27, 2020
1 parent ad758f8 commit d5ef4b6
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 82 deletions.
109 changes: 28 additions & 81 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -898,123 +898,72 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants {
let mut dataful_variant = None;
let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0);
let mut max_size = Size::ZERO;
let mut second_max_size = Size::ZERO;
let mut align = dl.aggregate_align;

// The size computations below assume that the padding is minimum.
// This is the case when fields are re-ordered.
let struct_reordering_opt = !def.repr.inhibit_struct_field_reordering_opt();

let mut extend_niche_range = |d| {
niche_variants =
*niche_variants.start().min(&d)..=*niche_variants.end().max(&d);
};

// Find the largest and second largest variant.
for (v, fields) in variants.iter_enumerated() {
// Find one non-ZST variant.
'variants: for (v, fields) in variants.iter_enumerated() {
if absent(fields) {
continue;
continue 'variants;
}
let mut size = Size::ZERO;
for &f in fields {
align = align.max(f.align);
size += f.size;
}
if size > max_size {
second_max_size = max_size;
max_size = size;
if let Some(d) = dataful_variant {
extend_niche_range(d);
}
dataful_variant = Some(v);
} else if size == max_size {
if let Some(d) = dataful_variant {
extend_niche_range(d);
for f in fields {
if !f.is_zst() {
if dataful_variant.is_none() {
dataful_variant = Some(v);
continue 'variants;
} else {
dataful_variant = None;
break 'variants;
}
}
dataful_variant = None;
extend_niche_range(v);
} else {
second_max_size = second_max_size.max(size);
extend_niche_range(v);
}
niche_variants = *niche_variants.start().min(&v)..=v;
}

if niche_variants.start() > niche_variants.end() {
dataful_variant = None;
}

if let Some(dataful_variant) = dataful_variant {
if let Some(i) = dataful_variant {
let count = (niche_variants.end().as_u32()
- niche_variants.start().as_u32()
+ 1) as u128;

// Find the field with the largest niche
let niche_candidate = variants[dataful_variant]
let niche_candidate = variants[i]
.iter()
.enumerate()
.filter_map(|(j, &field)| Some((j, field.largest_niche.as_ref()?)))
.max_by_key(|(_, n)| (n.available(dl), cmp::Reverse(n.offset)))
.and_then(|(field_index, niche)| {
if !struct_reordering_opt && second_max_size > Size::ZERO {
return None;
}
// make sure there is enough room for the other variants
if max_size - (niche.offset + niche.scalar.value.size(dl))
< second_max_size
{
return None;
}
Some((field_index, niche, niche.reserve(self, count)?))
});
.max_by_key(|(_, niche)| niche.available(dl));

if let Some((field_index, niche, (niche_start, niche_scalar))) =
niche_candidate
niche_candidate.and_then(|(field_index, niche)| {
Some((field_index, niche, niche.reserve(self, count)?))
})
{
let prefix = niche.offset + niche.scalar.value.size(dl);
let mut align = dl.aggregate_align;
let st = variants
.iter_enumerated()
.map(|(j, v)| {
let mut st = self.univariant_uninterned(
ty,
v,
&def.repr,
if j == dataful_variant || second_max_size == Size::ZERO {
StructKind::AlwaysSized
} else {
StructKind::Prefixed(
prefix,
Align::from_bytes(1).unwrap(),
)
},
StructKind::AlwaysSized,
)?;
st.variants = Variants::Single { index: j };

debug_assert_eq!(align, align.max(st.align));
align = align.max(st.align);

Ok(st)
})
.collect::<Result<IndexVec<VariantIdx, _>, _>>()?;

let offset = if struct_reordering_opt {
debug_assert_eq!(
st[dataful_variant].fields.offset(field_index),
Size::ZERO
);
niche.offset
} else {
st[dataful_variant].fields.offset(field_index) + niche.offset
};

let size = st[dataful_variant].size.align_to(align.abi);
debug_assert!(
!struct_reordering_opt || size == max_size.align_to(align.abi)
);
debug_assert!(st.iter().all(|v| v.size <= size));
let offset = st[i].fields.offset(field_index) + niche.offset;
let size = st[i].size;

let abi = if st.iter().all(|v| v.abi.is_uninhabited()) {
Abi::Uninhabited
} else if second_max_size == Size::ZERO {
match st[dataful_variant].abi {
} else {
match st[i].abi {
Abi::Scalar(_) => Abi::Scalar(niche_scalar.clone()),
Abi::ScalarPair(ref first, ref second) => {
// We need to use scalar_unit to reset the
Expand All @@ -1036,8 +985,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
}
_ => Abi::Aggregate { sized: true },
}
} else {
Abi::Aggregate { sized: true }
};

let largest_niche =
Expand All @@ -1047,7 +994,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
variants: Variants::Multiple {
tag: niche_scalar,
tag_encoding: TagEncoding::Niche {
dataful_variant,
dataful_variant: i,
niche_variants,
niche_start,
},
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ crate enum StmtKind<'tcx> {

// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Expr<'_>, if cfg!(bootstrap) { 168 } else { 160 });
rustc_data_structures::static_assert_size!(Expr<'_>, 168);

/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
/// into instances of this `Expr` enum. This lowering can be done
Expand Down

0 comments on commit d5ef4b6

Please sign in to comment.