|
| 1 | +// min-llvm-version: 14.0 |
1 | 2 | // ignore-debug: the debug assertions get in the way
|
2 |
| -// compile-flags: -O |
| 3 | +// compile-flags: -O -Z merge-functions=disabled |
3 | 4 | #![crate_type = "lib"]
|
4 | 5 |
|
5 | 6 | // Ensure that trivial casts of vec elements are O(1)
|
6 | 7 |
|
7 |
| -// CHECK-LABEL: @vec_iterator_cast |
| 8 | +pub struct Wrapper<T>(T); |
| 9 | + |
| 10 | +#[repr(C)] |
| 11 | +pub struct Foo { |
| 12 | + a: u64, |
| 13 | + b: u64, |
| 14 | + c: u64, |
| 15 | + d: u64, |
| 16 | +} |
| 17 | + |
| 18 | +// Going from an aggregate struct to another type currently requires Copy to |
| 19 | +// enable the TrustedRandomAccess specialization. Without it optimizations do not yet |
| 20 | +// reliably recognize the loops as noop for for repr(C) or non-Copy structs. |
| 21 | +#[derive(Copy, Clone)] |
| 22 | +pub struct Bar { |
| 23 | + a: u64, |
| 24 | + b: u64, |
| 25 | + c: u64, |
| 26 | + d: u64, |
| 27 | +} |
| 28 | + |
| 29 | +// CHECK-LABEL: @vec_iterator_cast_primitive |
| 30 | +#[no_mangle] |
| 31 | +pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> { |
| 32 | + // CHECK-NOT: loop |
| 33 | + // CHECK-NOT: call |
| 34 | + vec.into_iter().map(|e| e as u8).collect() |
| 35 | +} |
| 36 | + |
| 37 | +// CHECK-LABEL: @vec_iterator_cast_wrapper |
| 38 | +#[no_mangle] |
| 39 | +pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> { |
| 40 | + // CHECK-NOT: loop |
| 41 | + // CHECK-NOT: call |
| 42 | + vec.into_iter().map(|e| Wrapper(e)).collect() |
| 43 | +} |
| 44 | + |
| 45 | +// CHECK-LABEL: @vec_iterator_cast_unwrap |
| 46 | +#[no_mangle] |
| 47 | +pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> { |
| 48 | + // CHECK-NOT: loop |
| 49 | + // CHECK-NOT: call |
| 50 | + vec.into_iter().map(|e| e.0).collect() |
| 51 | +} |
| 52 | + |
| 53 | +// CHECK-LABEL: @vec_iterator_cast_aggregate |
8 | 54 | #[no_mangle]
|
9 |
| -pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> { |
| 55 | +pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> { |
10 | 56 | // CHECK-NOT: loop
|
11 | 57 | // CHECK-NOT: call
|
12 |
| - vec.into_iter().map(|e| e as usize).collect() |
| 58 | + vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() |
| 59 | +} |
| 60 | + |
| 61 | +// CHECK-LABEL: @vec_iterator_cast_deaggregate |
| 62 | +#[no_mangle] |
| 63 | +pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> { |
| 64 | + // CHECK-NOT: loop |
| 65 | + // CHECK-NOT: call |
| 66 | + |
| 67 | + // Safety: For the purpose of this test we assume that Bar layout matches [u64; 4]. |
| 68 | + // This currently is not guaranteed for repr(Rust) types, but it happens to work here and |
| 69 | + // the UCG may add additional guarantees for homogenous types in the future that would make this |
| 70 | + // correct. |
| 71 | + vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() |
13 | 72 | }
|
0 commit comments