Skip to content

Commit 6935896

Browse files
committed
Add codegen tests for additional cases where noop iterators get optimized away
Optimization 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.
1 parent 0d13f6a commit 6935896

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)