Refactor type memory layouts and ABIs, to be more general and easier to optimize.#45225
Refactor type memory layouts and ABIs, to be more general and easier to optimize.#45225bors merged 69 commits intorust-lang:masterfrom
Conversation
|
(rust_highfive has picked a reviewer for you, use r? to override) |
|
Started a crater run (we'll run cargobomb later, but that takes longer). |
|
holy shit |
src/librustc_trans/mir/lvalue.rs
Outdated
There was a problem hiding this comment.
Why is this always 1? Because you do a pointercast instead of a gep in the offset 0 case?
There was a problem hiding this comment.
Yes, and the assert ensures it.
src/test/run-pass/issue-30276.rs
Outdated
There was a problem hiding this comment.
Why are you removing this test?
There was a problem hiding this comment.
This is one of those things that don't trigger a typeck error but is totally broken, and I didn't want to deal with it.
There was a problem hiding this comment.
What does "totally broken" mean in this context?
There was a problem hiding this comment.
Something hid the ICE and #30276 was closed, but that was accidental. This is more or less a bug in WF-checking of function arguments in signatures, which @nikomatsakis somewhat insisted on keeping around, which allows fn(Unsized) to even exist (it shouldn't, for now).
src/test/codegen/packed.rs
Outdated
There was a problem hiding this comment.
Is the case this test was intended to check unreachable?
There was a problem hiding this comment.
Now, yeah, ScalarPair only works by having the placement of the second scalar at an ABI-aligned offset, so it's incompatible with packing.
src/librustc/ty/layout.rs
Outdated
There was a problem hiding this comment.
Why do "general" enums use FieldPlacement::Union for the discriminant only and "niche" enums use FieldPlacement::Arbitrary?
There was a problem hiding this comment.
Because a tag is always at offset 0 whereas a niche can be at some offset - we could have a variant of FieldPlacement that's just one Size to avoid the Vec but that's about it.
There was a problem hiding this comment.
But why we can't use FieldPlacement::Arbitrary for both of them? "Normal" structs with one field don't suddenly use FieldPlacement::Union because they can.
There was a problem hiding this comment.
I mean, FieldPlacement::Arbitrary is a bit of a waste, and I considered using FieldPlacement::Union for normal structs too, but then I have checks for Union in some places which would conflict with that now. I think you're right and I should make the change here.
EDIT: done.
EDIT2: That's funny, not using FieldPlacement::Union results in some missed optimizations (codegen/{alloc-optimisation,vec-optimizes-away}). I'll try to see what I can do about it.
EDIT3: None of the tricks I've tried work, I'll just leave it like this to avoid pessimizing tagged enums for now.
There was a problem hiding this comment.
Maybe add a comment to that effect?
c0e7215 to
08eb7c7
Compare
|
I've just moved |
a5b5722 to
d595119
Compare
|
☔ The latest upstream changes (presumably #45031) made this pull request unmergeable. Please resolve the merge conflicts. |
|
@mrhota Are you sure you meant #6791? That issue was closed more than three years ago. The problem with #31215 and #36237 was that they only added code where this PR is a net negative. This PR implements most of rust-lang/rfcs#1230, the description there is confused in places (i.e. it's a list of special cases, but several of them happen to be the exact same optimization, just scattered).
EDIT: for an updated view on these hard cases, see rust-lang/rfcs#1230 (comment). My approach with this PR has been to avoid doing anything that would pessimize codegen, and one example of this is that |
|
I can't reproduce the Travis failure locally, even after commenting out most of my |
|
@alexcrichton @Mark-Simulacrum I hope you don't mind that I just pushed a temporary commit to build on Travis without LLVM 3.7, to check if it's some old LLVM bug getting triggered. |
4c4d081 to
5d92b1a
Compare
|
Confirmed successful build with newer (4.0?) LLVM. I'll try to reproduce locally. |
|
@alexcrichton @Mark-Simulacrum May I suggest outputting a signal number by default? But if I turn verbose mode on, there's an extra (manually wrapped for your convenience): Printing just " |
To combat combinatorial explosion, type layouts are now described through 3 orthogonal properties:
Variantsdescribes the plurality of sum types (where applicable)Singleis for one inhabited/active variant, including all Cstructs andunionsTaggedhas its variants discriminated by an integer tag, including CenumsNicheFillinguses otherwise-invalid values ("niches") for all but one of its inhabited variantsFieldPlacementdescribes the number and memory offsets of fields (if any)Unionhas all its fields at offset0Arrayhas offsets that are a multiple of itsstride; guarantees all fields have one typeArbitraryrecords all the field offsets, which can be out-of-orderAbidescribes how values of the type should be passed around, including for FFIUninhabitedcorresponds to no values, associated with unreachable control-flowScalaris ABI-identical to its only integer/floating-point/pointer "scalar component"ScalarPairhas two "scalar components", but only applies to the Rust ABIVectoris for SIMD vectors, typically#[repr(simd)]structs in RustAggregatehas arbitrary contents, including all non-transparent Cstructs andunionsSize optimizations implemented so far:
Option<!>is 0 bytesResult<T, !>has the same size asT0, to represent a data-less variant, e.g.:Option<bool>,Option<Option<bool>>,Option<Ordering>are all 1 byteOption<char>is 4 bytesenum E { A(bool), B, C, D }is 1 byteCode generation now takes advantage of
ScalarandScalarPairto, in more cases, pass around scalar components as immediates instead of indirectly, through pointers into temporary memory, while avoiding LLVM's "first-class aggregates", and there's more untapped potential here.Closes #44426, fixes #5977, fixes #14540, fixes #43278.