-
Notifications
You must be signed in to change notification settings - Fork 13.8k
[WIP]: Do not store tag in uninhabited enum variants, or in the single inhabited variant. #145337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[WIP]: Do not store tag in uninhabited enum variants, or in the single inhabited variant. #145337
Conversation
This comment has been minimized.
This comment has been minimized.
7095fd5
to
76ded17
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
e1f38f7
to
6fbb6b7
Compare
Remove TmpLayout in layout_of_enum 09a3846 from <rust-lang#103693> made LayoutData be owned instead of interned in `Variants::Multiple::variants`[^1], so there's no need for `TmpLayout` in layout_of_enum anymore, and we can just store the variants' layouts directly in the prospective `LayoutData`s' `variants` fields. This should have no effect on semantics or layout. (written as part of rust-lang#145337 but not related to the layout optimizations in that PR) [^1]: see line 1154 of `compiler/rustc_target/src/abi/mod.rs` in the linked commit; `Variants::Multiple::variants` effectively changed from `IndexVec<.., Layout<'tcx>>` to `IndexVec<.., LayoutData>` where the `LayoutData`s are not interned as `Layout`s (`LayoutData` was at the time called `LayoutS`)
Rollup merge of #145387 - zachs18:remove-tmplayout, r=cjgillot Remove TmpLayout in layout_of_enum 09a3846 from <#103693> made LayoutData be owned instead of interned in `Variants::Multiple::variants`[^1], so there's no need for `TmpLayout` in layout_of_enum anymore, and we can just store the variants' layouts directly in the prospective `LayoutData`s' `variants` fields. This should have no effect on semantics or layout. (written as part of #145337 but not related to the layout optimizations in that PR) [^1]: see line 1154 of `compiler/rustc_target/src/abi/mod.rs` in the linked commit; `Variants::Multiple::variants` effectively changed from `IndexVec<.., Layout<'tcx>>` to `IndexVec<.., LayoutData>` where the `LayoutData`s are not interned as `Layout`s (`LayoutData` was at the time called `LayoutS`)
bc74d06
to
ac3f50f
Compare
This comment has been minimized.
This comment has been minimized.
ac3f50f
to
89752c2
Compare
89752c2
to
c0c1a81
Compare
☔ The latest upstream changes (presumably #147145) made this pull request unmergeable. Please resolve the merge conflicts. |
c0c1a81
to
f9f573e
Compare
…s enum representations
…rate after the commits which add the relevant layout optimizations.
…ommits which add the relevant layout optimizations.
…in a better layout)
f9f573e
to
018fe5a
Compare
This comment has been minimized.
This comment has been minimized.
…even when the niche is in an uninhabited variant.
018fe5a
to
fb682a3
Compare
This comment has been minimized.
This comment has been minimized.
pointers can be 16-bit, though I think all those targets are tier 3 |
This comment has been minimized.
This comment has been minimized.
17fa840
to
e8d40a6
Compare
let elt = element; | ||
if count == 0 { | ||
return Err(LayoutCalculatorError::ZeroLengthSimdType); | ||
} else if count > crate::MAX_SIMD_LANES { | ||
return Err(LayoutCalculatorError::OversizedSimdType { | ||
max_lanes: crate::MAX_SIMD_LANES, | ||
}); | ||
} | ||
|
||
// Compute the size and alignment of the vector | ||
let dl = self.cx.data_layout(); | ||
let size = elt | ||
.size(&self.cx) | ||
.checked_mul(count, dl) | ||
.ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; | ||
let (repr, align) = if repr_packed && !count.is_power_of_two() { | ||
// Non-power-of-two vectors have padding up to the next power-of-two. | ||
// If we're a packed repr, remove the padding while keeping the alignment as close | ||
// to a vector as possible. | ||
(BackendRepr::Memory { sized: true }, Align::max_aligned_factor(size)) | ||
} else { | ||
(BackendRepr::SimdVector { element, count }, dl.llvmlike_vector_align(size)) | ||
}; | ||
let size = size.align_to(align); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is duplicated code with simd_type
, and the only caller doesn't need a full layout, so you could replace simd_type_for_scalar
by:
fn simd_type_bare_repr<F>(
&self,
element: Scalar,
count: u64,
repr_packed: bool,
) -> Result<(Size, Align, BackendRepr), LayoutCalculatorError<F>>;
and use it both in simd_type
and in the new layouting logic.
PR description is outdated. I'll update it if/when the MCP is accepted.
This PR contains 3 or 4 changes which could probably be split up:
First (first commit): split out into #145387
Second (second commit) (needed for the actual layout changes to be sound with
offset_of!
on uninhabited variants' fields): Keep track of uninhabited non-abset variants' layouts, even if we use an untagged (Variants::Single
) or uninhabited (Variants::Empty
) layout. This is necessary as otherwiseoffset_of!
will "conjure" a layout for uninhabited variants where all fields are at offset 0, which conflicts with partial initialization1.Third (sixth commit): Do not make space for the enum tag in uninhabited variants in the tagged enum layout calculation. This optimizes enums where the uninhabited variants are the largest, and reduces their size by up to the size of the tag. e.g.
enum Foo { A, B(i32, !) }
was 8 bytesA: (tag, uninit), B: (tag, i32, !)
and is now 4 bytesA: (tag,), B: (i32, !)
. Additionally, enums with only zero-sized uninhabited variants are special-cased to return an uninhabited layout of the correct size and alignment without a tag at all, as otherwise we get weird edge cases2.Fourth (seventh commit): Add an additional enum layout that does not encode a tag. This is similar to the existing "single-present-variant" optimization, but works even if some of the uninhabited variants are "present" (have non-1-ZST fields). This works by calculating the layout of the inhabited variant as a struct, and padding it to the maximum size and alignment necessary to fit each uninhabited variant.
The layout changes probably need an MCP and I haven't squashed fully, so draft for now.
r? ghost
Footnotes
This isn't an issue before this PR because the layout algorithm only produces
Variants::Empty
orVariants::Single
when all uninhabited variants are "absent", i.e. have only 1-ZST fields ↩Specifically, without the special-case,
enum Foo { A(Aligned2Never), B(Aligned2Never) }
got a size-0 layout with ani16
tag field, which I assume would cause problems. ↩