-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #73453 - erikdesjardins:tuplayout, r=eddyb
Ignore ZST offsets when deciding whether to use Scalar/ScalarPair layout This is important because Scalar/ScalarPair layout previously would not be used if any ZST had nonzero offset. For example, before this change, only `((), u128)` would be laid out like `u128`, not `(u128, ())`. Fixes #63244
- Loading branch information
Showing
7 changed files
with
228 additions
and
74 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// ignore-emscripten | ||
// compile-flags: -C no-prepopulate-passes | ||
|
||
// Test that tuples get optimized layout, in particular with a ZST in the last field (#63244) | ||
|
||
#![crate_type="lib"] | ||
|
||
type ScalarZstLast = (u128, ()); | ||
// CHECK: define i128 @test_ScalarZstLast(i128 %_1) | ||
#[no_mangle] | ||
pub fn test_ScalarZstLast(_: ScalarZstLast) -> ScalarZstLast { loop {} } | ||
|
||
type ScalarZstFirst = ((), u128); | ||
// CHECK: define i128 @test_ScalarZstFirst(i128 %_1) | ||
#[no_mangle] | ||
pub fn test_ScalarZstFirst(_: ScalarZstFirst) -> ScalarZstFirst { loop {} } | ||
|
||
type ScalarPairZstLast = (u8, u128, ()); | ||
// CHECK: define { i128, i8 } @test_ScalarPairZstLast(i128 %_1.0, i8 %_1.1) | ||
#[no_mangle] | ||
pub fn test_ScalarPairZstLast(_: ScalarPairZstLast) -> ScalarPairZstLast { loop {} } | ||
|
||
type ScalarPairZstFirst = ((), u8, u128); | ||
// CHECK: define { i8, i128 } @test_ScalarPairZstFirst(i8 %_1.0, i128 %_1.1) | ||
#[no_mangle] | ||
pub fn test_ScalarPairZstFirst(_: ScalarPairZstFirst) -> ScalarPairZstFirst { loop {} } | ||
|
||
type ScalarPairLotsOfZsts = ((), u8, (), u128, ()); | ||
// CHECK: define { i128, i8 } @test_ScalarPairLotsOfZsts(i128 %_1.0, i8 %_1.1) | ||
#[no_mangle] | ||
pub fn test_ScalarPairLotsOfZsts(_: ScalarPairLotsOfZsts) -> ScalarPairLotsOfZsts { loop {} } | ||
|
||
type ScalarPairLottaNesting = (((), ((), u8, (), u128, ())), ()); | ||
// CHECK: define { i128, i8 } @test_ScalarPairLottaNesting(i128 %_1.0, i8 %_1.1) | ||
#[no_mangle] | ||
pub fn test_ScalarPairLottaNesting(_: ScalarPairLottaNesting) -> ScalarPairLottaNesting { loop {} } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// compile-flags: -C no-prepopulate-passes | ||
|
||
#![crate_type = "lib"] | ||
#![feature(repr_simd)] | ||
|
||
// Hack to get the correct size for the length part in slices | ||
// CHECK: @helper([[USIZE:i[0-9]+]] %_1) | ||
#[no_mangle] | ||
pub fn helper(_: usize) { | ||
} | ||
|
||
// Check that we correctly generate a GEP for a ZST that is not included in Scalar layout | ||
// CHECK-LABEL: @scalar_layout | ||
#[no_mangle] | ||
pub fn scalar_layout(s: &(u64, ())) { | ||
// CHECK: [[X0:%[0-9]+]] = bitcast i64* %s to i8* | ||
// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 8 | ||
let x = &s.1; | ||
&x; // keep variable in an alloca | ||
} | ||
|
||
// Check that we correctly generate a GEP for a ZST that is not included in ScalarPair layout | ||
// CHECK-LABEL: @scalarpair_layout | ||
#[no_mangle] | ||
pub fn scalarpair_layout(s: &(u64, u32, ())) { | ||
// CHECK: [[X0:%[0-9]+]] = bitcast { i64, i32 }* %s to i8* | ||
// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 12 | ||
let x = &s.2; | ||
&x; // keep variable in an alloca | ||
} | ||
|
||
#[repr(simd)] | ||
pub struct U64x4(u64, u64, u64, u64); | ||
|
||
// Check that we correctly generate a GEP for a ZST that is not included in Vector layout | ||
// CHECK-LABEL: @vector_layout | ||
#[no_mangle] | ||
pub fn vector_layout(s: &(U64x4, ())) { | ||
// CHECK: [[X0:%[0-9]+]] = bitcast <4 x i64>* %s to i8* | ||
// CHECK-NEXT: [[X1:%[0-9]+]] = getelementptr i8, i8* [[X0]], [[USIZE]] 32 | ||
let x = &s.1; | ||
&x; // keep variable in an alloca | ||
} |
26 changes: 26 additions & 0 deletions
26
src/test/ui/dynamically-sized-types/dst-tuple-no-reorder.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// run-pass | ||
|
||
#![feature(unsized_tuple_coercion)] | ||
|
||
// Ensure that unsizable fields that might be accessed don't get reordered | ||
|
||
fn nonzero_size() { | ||
let sized: (u8, [u32; 2]) = (123, [456, 789]); | ||
let unsize: &(u8, [u32]) = &sized; | ||
assert_eq!(unsize.0, 123); | ||
assert_eq!(unsize.1.len(), 2); | ||
assert_eq!(unsize.1[0], 456); | ||
assert_eq!(unsize.1[1], 789); | ||
} | ||
|
||
fn zst() { | ||
let sized: (u8, [u32; 0]) = (123, []); | ||
let unsize: &(u8, [u32]) = &sized; | ||
assert_eq!(unsize.0, 123); | ||
assert_eq!(unsize.1.len(), 0); | ||
} | ||
|
||
pub fn main() { | ||
nonzero_size(); | ||
zst(); | ||
} |
22 changes: 22 additions & 0 deletions
22
src/test/ui/dynamically-sized-types/dst-tuple-zst-offsets.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// run-pass | ||
|
||
#![feature(unsized_tuple_coercion)] | ||
|
||
// Check that we do not change the offsets of ZST fields when unsizing | ||
|
||
fn scalar_layout() { | ||
let sized: &(u8, [(); 13]) = &(123, [(); 13]); | ||
let unsize: &(u8, [()]) = sized; | ||
assert_eq!(sized.1.as_ptr(), unsize.1.as_ptr()); | ||
} | ||
|
||
fn scalarpair_layout() { | ||
let sized: &(u8, u16, [(); 13]) = &(123, 456, [(); 13]); | ||
let unsize: &(u8, u16, [()]) = sized; | ||
assert_eq!(sized.2.as_ptr(), unsize.2.as_ptr()); | ||
} | ||
|
||
pub fn main() { | ||
scalar_layout(); | ||
scalarpair_layout(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// compile-flags: -Z mir-opt-level=2 | ||
// build-pass | ||
#![crate_type="lib"] | ||
|
||
// This used to ICE: const-prop did not account for field reordering of scalar pairs, | ||
// and would generate a tuple like `(0x1337, VariantBar): (FooEnum, isize)`, | ||
// causing assertion failures in codegen when trying to read 0x1337 at the wrong type. | ||
|
||
pub enum FooEnum { | ||
VariantBar, | ||
VariantBaz, | ||
VariantBuz, | ||
} | ||
|
||
pub fn wrong_index() -> isize { | ||
let (_, b) = id((FooEnum::VariantBar, 0x1337)); | ||
b | ||
} | ||
|
||
pub fn wrong_index_two() -> isize { | ||
let (_, (_, b)) = id(((), (FooEnum::VariantBar, 0x1338))); | ||
b | ||
} | ||
|
||
fn id<T>(x: T) -> T { | ||
x | ||
} |