Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test codegen for repr(packed,simd) -> repr(simd) #125904

Merged
merged 1 commit into from
Jun 3, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions tests/codegen/simd/packed-simd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//@ revisions:opt3 noopt
//@[opt3] compile-flags: -Copt-level=3
//@[noopt] compile-flags: -Cno-prepopulate-passes

#![crate_type = "lib"]
#![no_std]
#![feature(repr_simd, core_intrinsics)]
use core::intrinsics::simd as intrinsics;
use core::{mem, ptr};

// Test codegen for not only "packed" but also "fully aligned" SIMD types, and conversion between
// A repr(packed,simd) type with 3 elements can't exceed its element alignment,
// whereas the same type as repr(simd) will instead have padding.

#[repr(simd, packed)]
pub struct Simd<T, const N: usize>([T; N]);

#[repr(simd)]
#[derive(Copy, Clone)]
pub struct FullSimd<T, const N: usize>([T; N]);

// non-powers-of-two have padding and need to be expanded to full vectors
fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
unsafe {
let mut tmp = mem::MaybeUninit::<FullSimd<T, N>>::uninit();
ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
tmp.assume_init()
}
}

// CHECK-LABEL: square_packed
// CHECK-SAME: ptr{{[a-z_ ]*}} sret([[RET_TYPE:[^)]+]]) [[RET_ALIGN:align (8|16)]]{{[^%]*}} [[RET_VREG:%[_0-9]*]]
// CHECK-SAME: ptr{{[a-z_ ]*}} align 4
#[no_mangle]
pub fn square_packed(x: Simd<f32, 3>) -> FullSimd<f32, 3> {
// CHECK-NEXT: start
// noopt: alloca [[RET_TYPE]], [[RET_ALIGN]]
// CHECK: load <3 x float>
let x = load(x);
// CHECK: [[VREG:%[a-z0-9_]+]] = fmul <3 x float>
// CHECK-NEXT: store <3 x float> [[VREG]], ptr [[RET_VREG]], [[RET_ALIGN]]
// CHECK-NEXT: ret void
unsafe { intrinsics::simd_mul(x, x) }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This calls simd_mul on FullSimd, which is not what rust-lang/portable-simd#422 does I think -- there the intrinsics are called on packed SIMD types. Conveniently that means they work without any other adjustments in Miri. ;)

Is there any need for simd_mul and other intrinsics to be used on types with padding?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some crates that use length-3 vectors with the repr_simd unstable feature. I've also played around with the idea of making the layout configurable in std::simd, though I haven't really decided if that's actually beneficial. So, I'd lean towards not necessary but a possibility

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a nightly-only feature so breaking those crates is an option. I guess the question is whether there's any advantage to the types that have padding.

Is that tracked anywhere? If not, can you open an issue?

}
Loading