Skip to content
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

Padding to ensure a value is well-aligned is not used for niche value optimization #79531

Open
jhpratt opened this issue Nov 29, 2020 · 5 comments
Labels
A-layout Area: Memory layout of types A-mir-opt Area: MIR optimizations

Comments

@jhpratt
Copy link
Member

jhpratt commented Nov 29, 2020

use core::mem::size_of;
use core::num::NonZeroU8;

struct Foo(u8, u16);
struct Bar(u8, u16, NonZeroU8);

fn main() {
    dbg!(size_of::<Foo>());
    dbg!(size_of::<Option<Foo>>());
    dbg!(size_of::<Bar>());
    dbg!(size_of::<Option<Bar>>());
}

(Playground)

Output:

[src/main.rs:8] size_of::<Foo>() = 4
[src/main.rs:9] size_of::<Option<Foo>>() = 6
[src/main.rs:10] size_of::<Bar>() = 4
[src/main.rs:11] size_of::<Option<Bar>>() = 4

size_of::<Foo>() returns 4 as expected. size_of::<Option<Foo>>() returns 6, indicating that the unused padding byte is not being used to store the tag for the Option. (playground)

However, by adding a field that is NonZero*, the compiler is able to take advantage of the unused bit. This, of course, only works with one bit, not the potential eight.

In this example, the size of Bar is the same as Foo, but the situation that I ran across this with requires an increase in size of the struct to decrease the size of Option<CompoundStruct>; needless to say this is a tradeoff I don't want to make.

Presumably the compiler could do some magic here to take advantage of the niche values.

@camelid camelid added A-layout Area: Memory layout of types A-mir-opt Area: MIR optimizations labels Nov 29, 2020
@SkiFire13
Copy link
Contributor

The problem with this optimization is that you can no longer overwrite padding bytes when writing to a mutable reference, because doing so could potentially mutate the discriminant, leading to an invalid state.

@jhpratt
Copy link
Member Author

jhpratt commented Nov 30, 2020

@SkiFire13 Why would one want to write to padding bytes?

@SkiFire13
Copy link
Contributor

SkiFire13 commented Nov 30, 2020

I thought the compiler would (or should?) optimize copying structs like Foo to a single instruction that copies 4 bytes (which include the padding bytes), however looks like I'm wrong (#63159 is also kinda related to this). C however behaves like I expected

@erikdesjardins
Copy link
Contributor

This is more-or-less a duplicate of #70230

@QuineDot
Copy link

Why would one want to write to padding bytes?

memcpy of T: Copy was accepted by RFC in 2016. See also this UCG issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-layout Area: Memory layout of types A-mir-opt Area: MIR optimizations
Projects
None yet
Development

No branches or pull requests

5 participants