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

Consider improving layout of this enum #24041

Closed
carllerche opened this issue Apr 4, 2015 · 8 comments
Closed

Consider improving layout of this enum #24041

carllerche opened this issue Apr 4, 2015 · 8 comments
Labels
A-codegen Area: Code generation C-enhancement Category: An issue proposing an enhancement or a PR with one.

Comments

@carllerche
Copy link
Member

I think the following snippet should be possible (but it fails currently). Since &'static MyTrait can't be 0, if the first half of the layout is 0, then the enum must be the Boxed variant.

use std::mem;

pub trait MyTrait {
    fn zomg(&self);
}

enum Foo {
    Inline(&'static MyTrait, [usize; 2]),
    Boxed(Box<MyTrait>),
}

pub fn main() {
    assert_eq!(2 * mem::size_of::<&'static MyTrait>(), mem::size_of::<Foo>());
}
@carllerche carllerche changed the title Improve enum optimization Consider improving layout of this enum Apr 4, 2015
@steveklabnik steveklabnik added the A-codegen Area: Code generation label Apr 4, 2015
@abonander
Copy link
Contributor

I'm not sure I follow. &MyTrait and Box<MyTrait> are the same width, neither can be zero, and the second half of the enum could be [0us; 2] or empty space. I don't see a way to deduce the variant without a discriminator. Maybe I'm missing something.

@Diggsey
Copy link
Contributor

Diggsey commented Apr 12, 2015

The layout of the Boxed variant could theoretically be altered such that Box<MyTrait> occupies the same space as the [usize; 2] from the Inline variant. The first usize bytes could then be used as the discriminator, where 0 => Boxed, _ => Inline.

I'm not sure how worthwhile this is, since it's very specific, and the algorithm to calculate the best layout for every possible scenario is at the very least non-obvious. If there is ever a rust ABI, then it would be preferable to have layouts controlled by predictable, easy to describe rules.

@dotdash
Copy link
Contributor

dotdash commented Apr 12, 2015

If you put the box in the same space as the array, i.e. in the second half,
then you can identify the Boxed variant by the first half being set to zero.
Am 12.04.2015 23:17 schrieb "Austin Bonander" notifications@github.com:

I'm not sure I follow. &MyTrait and Box are the same width,
neither can be zero, and the second half of the enum could be [0us; 2] or
empty space. I don't see a way to deduce the variant without a
discriminator. Maybe I'm missing something.


Reply to this email directly or view it on GitHub
#24041 (comment).

@Marwes
Copy link
Contributor

Marwes commented Jun 27, 2015

Its not necessarily a strictly better idea to put the box in the same space as the array though.

fn zomg(foo: &Foo)
    match *foo {
        Inline(ref t, _) => t.zomg(),
        Boxed(ref t) => t.zomg()
}

In a function such as above, since the the data and vtable are in the same position it could be optimized to just load those positions and call the function, avoiding the discriminant test completely. I don't know if llvm performs that sort of optimization though.

@steveklabnik
Copy link
Member

steveklabnik commented Nov 29, 2016

Triage: thread 'main' panicked at 'assertion failed: (left == right) (left: 32, right: 40)',

@Mark-Simulacrum Mark-Simulacrum added the C-enhancement Category: An issue proposing an enhancement or a PR with one. label Jul 22, 2017
@nox
Copy link
Contributor

nox commented Apr 1, 2018

This could be done with @eddyb's niche-filling optimisation. It currently only applies to enums with a single dataful variant, but we could make it apply to the largest variant of the enum instead. I am pretty sure this would also improve the layout of a bunch of enums in Stylo.

I've thought about this a bit and I think the niche-filling optimisation should apply to the largest variant of any repr(Rust) enum, if there is no other variant that is as large.

Cc @rust-lang/wg-codegen

@eddyb
Copy link
Member

eddyb commented Apr 10, 2018

This seems to (now) be a duplicate of #46213.

@dtolnay
Copy link
Member

dtolnay commented Jul 15, 2019

Closing in favor of the more general #46213.

@dtolnay dtolnay closed this as completed Jul 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-codegen Area: Code generation C-enhancement Category: An issue proposing an enhancement or a PR with one.
Projects
None yet
Development

No branches or pull requests

10 participants