-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support to array-based SIMD (#2633)
Originally, repr(simd) supported only multi-field form. An array based version was later added and it's likely to become the only supported way (rust-lang/compiler-team#621). The array-based version is currently used in the standard library, and it is used to implement `portable-simd`. This change adds support to instantiating and using the array-based version.
- Loading branch information
Showing
6 changed files
with
225 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
//! Verify that Kani can properly handle SIMD declaration and field access using array syntax. | ||
|
||
#![allow(non_camel_case_types)] | ||
#![feature(repr_simd)] | ||
|
||
#[repr(simd)] | ||
#[derive(Clone, PartialEq, Eq, PartialOrd, kani::Arbitrary)] | ||
pub struct i64x2([i64; 2]); | ||
|
||
#[kani::proof] | ||
fn check_diff() { | ||
let x = i64x2([1, 2]); | ||
let y = i64x2([3, 4]); | ||
assert!(x != y); | ||
} | ||
|
||
#[kani::proof] | ||
fn check_ge() { | ||
let x: i64x2 = kani::any(); | ||
kani::assume(x.0[0] > 0); | ||
kani::assume(x.0[1] > 0); | ||
assert!(x > i64x2([0, 0])); | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
#[repr(simd)] | ||
struct CustomSimd<T, const LANES: usize>([T; LANES]); | ||
|
||
#[kani::proof] | ||
fn simd_vec() { | ||
let simd = CustomSimd([0u8; 10]); | ||
let idx: usize = kani::any_where(|x: &usize| *x < 10); | ||
assert_eq!(simd.0[idx], 0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
//! Verify that Kani can properly handle SIMD declaration and field access using multi-field syntax. | ||
//! Note: Multi-field SIMD is actually being deprecated, but until it's removed, we might | ||
//! as well keep supporting it. | ||
//! See <https://github.com/rust-lang/compiler-team/issues/621> for more details. | ||
|
||
#![allow(non_camel_case_types)] | ||
#![feature(repr_simd)] | ||
|
||
#[repr(simd)] | ||
#[derive(PartialEq, Eq, PartialOrd, kani::Arbitrary)] | ||
pub struct i64x2(i64, i64); | ||
|
||
#[kani::proof] | ||
fn check_diff() { | ||
let x = i64x2(1, 2); | ||
let y = i64x2(3, 4); | ||
assert!(x != y); | ||
} | ||
|
||
#[kani::proof] | ||
fn check_ge() { | ||
let x: i64x2 = kani::any(); | ||
kani::assume(x.0 > 0); | ||
kani::assume(x.1 > 0); | ||
assert!(x > i64x2(0, 0)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! Ensure we have basic support of portable SIMD. | ||
#![feature(portable_simd)] | ||
|
||
use std::simd::u64x16; | ||
|
||
#[kani::proof] | ||
fn check_sum_any() { | ||
let a = u64x16::splat(0); | ||
let b = u64x16::from_array(kani::any()); | ||
// Cannot compare them directly: https://github.com/model-checking/kani/issues/2632 | ||
assert_eq!((a + b).as_array(), b.as_array()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright Kani Contributors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! Ensure we can handle SIMD defined in the standard library | ||
//! FIXME: <https://github.com/model-checking/kani/issues/2631> | ||
#![allow(non_camel_case_types)] | ||
#![feature(repr_simd, platform_intrinsics, portable_simd)] | ||
use std::simd::f32x4; | ||
|
||
extern "platform-intrinsic" { | ||
fn simd_add<T>(x: T, y: T) -> T; | ||
fn simd_eq<T, U>(x: T, y: T) -> U; | ||
} | ||
|
||
#[repr(simd)] | ||
#[derive(Clone, PartialEq, kani::Arbitrary)] | ||
pub struct f32x2(f32, f32); | ||
|
||
impl f32x2 { | ||
fn as_array(&self) -> &[f32; 2] { | ||
unsafe { &*(self as *const f32x2 as *const [f32; 2]) } | ||
} | ||
} | ||
|
||
#[kani::proof] | ||
fn check_sum() { | ||
let a = f32x2(0.0, 0.0); | ||
let b = kani::any::<f32x2>(); | ||
let sum = unsafe { simd_add(a.clone(), b) }; | ||
assert_eq!(sum.as_array(), a.as_array()); | ||
} | ||
|
||
#[kani::proof] | ||
fn check_sum_portable() { | ||
let a = f32x4::splat(0.0); | ||
let b = f32x4::from_array(kani::any()); | ||
// Cannot compare them directly: https://github.com/model-checking/kani/issues/2632 | ||
assert_eq!((a + b).as_array(), b.as_array()); | ||
} |