Skip to content

Commit

Permalink
Auto merge of #95695 - the8472:vec-codegen-tests, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bors committed Apr 18, 2022
2 parents e27d9df + 6935896 commit 7b5408d
Showing 1 changed file with 63 additions and 4 deletions.
67 changes: 63 additions & 4 deletions src/test/codegen/vec-in-place.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,72 @@
// min-llvm-version: 14.0
// ignore-debug: the debug assertions get in the way
// compile-flags: -O
// compile-flags: -O -Z merge-functions=disabled
#![crate_type = "lib"]

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

// CHECK-LABEL: @vec_iterator_cast
pub struct Wrapper<T>(T);

#[repr(C)]
pub struct Foo {
a: u64,
b: u64,
c: u64,
d: u64,
}

// Going from an aggregate struct to another type currently requires Copy to
// enable the TrustedRandomAccess specialization. Without it optimizations do not yet
// reliably recognize the loops as noop for for repr(C) or non-Copy structs.
#[derive(Copy, Clone)]
pub struct Bar {
a: u64,
b: u64,
c: u64,
d: u64,
}

// CHECK-LABEL: @vec_iterator_cast_primitive
#[no_mangle]
pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
// CHECK-NOT: loop
// CHECK-NOT: call
vec.into_iter().map(|e| e as u8).collect()
}

// CHECK-LABEL: @vec_iterator_cast_wrapper
#[no_mangle]
pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
// CHECK-NOT: loop
// CHECK-NOT: call
vec.into_iter().map(|e| Wrapper(e)).collect()
}

// CHECK-LABEL: @vec_iterator_cast_unwrap
#[no_mangle]
pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
// CHECK-NOT: loop
// CHECK-NOT: call
vec.into_iter().map(|e| e.0).collect()
}

// CHECK-LABEL: @vec_iterator_cast_aggregate
#[no_mangle]
pub fn vec_iterator_cast(vec: Vec<isize>) -> Vec<usize> {
pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
// CHECK-NOT: loop
// CHECK-NOT: call
vec.into_iter().map(|e| e as usize).collect()
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
}

// CHECK-LABEL: @vec_iterator_cast_deaggregate
#[no_mangle]
pub fn vec_iterator_cast_deaggregate(vec: Vec<Bar>) -> Vec<[u64; 4]> {
// CHECK-NOT: loop
// CHECK-NOT: call

// Safety: For the purpose of this test we assume that Bar layout matches [u64; 4].
// This currently is not guaranteed for repr(Rust) types, but it happens to work here and
// the UCG may add additional guarantees for homogenous types in the future that would make this
// correct.
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
}

0 comments on commit 7b5408d

Please sign in to comment.