Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRefactor type memory layouts and ABIs, to be more general and easier to optimize. #45225
Conversation
rust-highfive
assigned
nikomatsakis
Oct 12, 2017
This comment has been minimized.
This comment has been minimized.
|
(rust_highfive has picked a reviewer for you, use r? to override) |
eddyb
referenced this pull request
Oct 12, 2017
Closed
Move layout & ABI code into s/librustc_back/librustc_target. #45226
This comment has been minimized.
This comment has been minimized.
|
Started a crater run (we'll run cargobomb later, but that takes longer). |
This comment has been minimized.
This comment has been minimized.
|
holy shit |
This comment has been minimized.
This comment has been minimized.
eddyb
force-pushed the
eddyb:trans-abi
branch
from
2b0e0b2
to
e27cba8
Oct 12, 2017
arielb1
reviewed
Oct 12, 2017
| } else if let layout::Abi::ScalarPair(ref a, ref b) = self.layout.abi { | ||
| // Offsets have to match either first or second field. | ||
| assert_eq!(offset, a.value.size(ccx).abi_align(b.value.align(ccx))); | ||
| bcx.struct_gep(self.llval, 1) |
This comment has been minimized.
This comment has been minimized.
arielb1
Oct 12, 2017
•
Contributor
Why is this always 1? Because you do a pointercast instead of a gep in the offset 0 case?
This comment has been minimized.
This comment has been minimized.
eddyb
force-pushed the
eddyb:trans-abi
branch
from
e27cba8
to
a3f7156
Oct 12, 2017
arielb1
reviewed
Oct 12, 2017
| @@ -1,14 +0,0 @@ | |||
| // Copyright 2013 The Rust Project Developers. See the COPYRIGHT | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eddyb
Oct 12, 2017
Author
Member
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.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eddyb
Nov 5, 2017
Author
Member
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).
arielb1
reviewed
Oct 12, 2017
| @@ -54,9 +54,6 @@ pub struct PackedPair(u8, u32); | |||
| // CHECK-LABEL: @pkd_pair | |||
| #[no_mangle] | |||
| pub fn pkd_pair(pair1: &mut PackedPair, pair2: &mut PackedPair) { | |||
| // CHECK: [[V1:%[a-z0-9]+]] = load i8, i8* %{{.*}}, align 1 | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eddyb
Oct 12, 2017
Author
Member
Now, yeah, ScalarPair only works by having the placement of the second scalar at an ABI-aligned offset, so it's incompatible with packing.
arielb1
reviewed
Oct 12, 2017
| } | ||
| /// Describes how the fields of a type are located in memory. | ||
| #[derive(PartialEq, Eq, Hash, Debug)] | ||
| pub enum FieldPlacement { |
This comment has been minimized.
This comment has been minimized.
arielb1
Oct 12, 2017
Contributor
Why do "general" enums use FieldPlacement::Union for the discriminant only and "niche" enums use FieldPlacement::Arbitrary?
This comment has been minimized.
This comment has been minimized.
eddyb
Oct 12, 2017
Author
Member
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.
This comment has been minimized.
This comment has been minimized.
arielb1
Oct 12, 2017
•
Contributor
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.
This comment has been minimized.
This comment has been minimized.
eddyb
Oct 12, 2017
•
Author
Member
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.
This comment has been minimized.
This comment has been minimized.
eddyb
force-pushed the
eddyb:trans-abi
branch
2 times, most recently
from
c0e7215
to
08eb7c7
Oct 12, 2017
This comment has been minimized.
This comment has been minimized.
|
I've just moved |
eddyb
force-pushed the
eddyb:trans-abi
branch
2 times, most recently
from
a5b5722
to
d595119
Oct 12, 2017
This comment has been minimized.
This comment has been minimized.
eddyb
force-pushed the
eddyb:trans-abi
branch
from
d595119
to
436e8aa
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
|
@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 |
eddyb
force-pushed the
eddyb:trans-abi
branch
from
436e8aa
to
3504ac6
Oct 13, 2017
kennytm
added
the
S-waiting-on-author
label
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
|
I can't reproduce the Travis failure locally, even after commenting out most of my |
This comment has been minimized.
This comment has been minimized.
|
@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. |
eddyb
force-pushed the
eddyb:trans-abi
branch
2 times, most recently
from
4c4d081
to
5d92b1a
Oct 13, 2017
This comment has been minimized.
This comment has been minimized.
|
Confirmed successful build with newer (4.0?) LLVM. I'll try to reproduce locally. |
This comment has been minimized.
This comment has been minimized.
|
@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 " |
eddyb commentedOct 12, 2017
•
edited
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.