Skip to content

Commit 7b5408d

Browse files
committed
Auto merge of #95695 - the8472:vec-codegen-tests, r=Mark-Simulacrum
Add codegen tests for additional cases where noop iterators get optimized away Optimizations have improved over time and now LLVM manages to optimize more in-place-collect noop-iterators to O(1) functions. This updates the codegen test to match. Many but not all cases reported in #79308 work now.
2 parents e27d9df + 6935896 commit 7b5408d

File tree

1 file changed

+63
-4
lines changed

1 file changed

+63
-4
lines changed

src/test/codegen/vec-in-place.rs

+63-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,72 @@
1+
// min-llvm-version: 14.0
12
// ignore-debug: the debug assertions get in the way
2-
// compile-flags: -O
3+
// compile-flags: -O -Z merge-functions=disabled
34
#![crate_type = "lib"]
45

56
// Ensure that trivial casts of vec elements are O(1)
67

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
854
#[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> {
1056
// CHECK-NOT: loop
1157
// 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()
1372
}

0 commit comments

Comments
 (0)