Skip to content

Commit f02e949

Browse files
author
TheIronBorn
committed
scalar rotates, rotate instr tests
1 parent 1271a3f commit f02e949

File tree

4 files changed

+85
-17
lines changed

4 files changed

+85
-17
lines changed

coresimd/ppsv/api/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ mod shifts;
127127
#[macro_use]
128128
mod rotates;
129129

130+
pub use self::rotates::Rotate;
131+
130132
/// Sealed trait used for constraining select implementations.
131133
pub trait Lanes<A> {}
132134

coresimd/ppsv/api/rotates.rs

+38-17
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,59 @@
11
//! Implements integer rotates.
22
#![allow(unused)]
33

4+
/// Trait used for overloading rotates
5+
pub trait Rotate<T> {
6+
/// Shifts the bits of each lane to the left by the specified amount in
7+
/// the corresponding lane of `n`, wrapping the truncated bits to
8+
/// the end of the resulting integer.
9+
///
10+
/// Please note this isn't the same operation as `<<`!. Also note it
11+
/// isn't equivalent to `slice::rotate_left`, it doesn't move the vector's
12+
/// lanes around. (that can be implemented with vector shuffles).
13+
fn rotate_left(self, n: T) -> Self;
14+
15+
/// Shifts the bits of each lane to the right by the specified amount in
16+
/// the corresponding lane of `n`, wrapping the truncated bits to
17+
/// the beginning of the resulting integer.
18+
///
19+
/// Please note this isn't the same operation as `>>`!. Also note it
20+
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
21+
/// lanes around. (that can be implemented with vector shuffles).
22+
fn rotate_right(self, n: T) -> Self;
23+
}
24+
425
macro_rules! impl_vector_rotates {
526
($id:ident, $elem_ty:ident) => {
6-
impl $id {
7-
/// Shifts the bits of each lane to the left by the specified amount in
8-
/// the corresponding lane of `n`, wrapping the truncated bits to
9-
/// the end of the resulting integer.
10-
///
11-
/// Please note this isn't the same operation as `<<`!. Also note it
12-
/// isn't equivalent to `slice::rotate_left` (that can be implemented
13-
/// with vector shuffles).
27+
impl super::api::Rotate<$id> for $id {
1428
#[inline]
15-
pub fn rotate_left(self, n: $id) -> $id {
29+
fn rotate_left(self, n: $id) -> $id {
1630
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
1731
// Protect against undefined behavior for over-long bit shifts
1832
let n = n % LANE_WIDTH;
1933
(self << n) | (self >> ((LANE_WIDTH - n) % LANE_WIDTH))
2034
}
2135

22-
/// Shifts the bits of each lane to the right by the specified amount in
23-
/// the corresponding lane of `n`, wrapping the truncated bits to
24-
/// the beginning of the resulting integer.
25-
///
26-
/// Please note this isn't the same operation as `>>`!. Also note it
27-
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
28-
/// lanes around. (that can be implemented with vector shuffles).
2936
#[inline]
30-
pub fn rotate_right(self, n: $id) -> $id {
37+
fn rotate_right(self, n: $id) -> $id {
3138
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
3239
// Protect against undefined behavior for over-long bit shifts
3340
let n = n % LANE_WIDTH;
3441
(self >> n) | (self << ((LANE_WIDTH - n) % LANE_WIDTH))
3542
}
3643
}
44+
45+
impl super::api::Rotate<$elem_ty> for $id {
46+
#[inline]
47+
fn rotate_left(self, n: $elem_ty) -> $id {
48+
self.rotate_left($id::splat(n))
49+
}
50+
51+
52+
#[inline]
53+
fn rotate_right(self, n: $elem_ty) -> $id {
54+
self.rotate_right($id::splat(n))
55+
}
56+
}
3757
};
3858
}
3959

@@ -43,6 +63,7 @@ macro_rules! test_vector_rotate_ops {
4363
#[test]
4464
fn rotate_ops() {
4565
use coresimd::simd::$id;
66+
use coresimd::simd::Rotate;;
4667
use std::mem;
4768
let z = $id::splat(0 as $elem_ty);
4869
let o = $id::splat(1 as $elem_ty);

coresimd/ppsv/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ pub use self::v32::*;
4848
pub use self::v512::*;
4949
pub use self::v64::*;
5050

51+
pub use self::api::Rotate;
52+
5153
/// Safe lossless bitwise conversion from `T` to `Self`.
5254
pub trait FromBits<T>: ::marker::Sized {
5355
/// Safe lossless bitwise from `T` to `Self`.

crates/coresimd/tests/rotate_tests.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! rotate instruction tests
2+
3+
#![feature(stdsimd)]
4+
#![feature(proc_macro)]
5+
#![feature(avx512_target_feature)]
6+
7+
#[macro_use]
8+
// extern crate assert_instr_macro;
9+
extern crate stdsimd_test;
10+
extern crate stdsimd;
11+
12+
use stdsimd::simd::*;
13+
use stdsimd_test::assert_instr;
14+
15+
// Verify that supported hardware compiles rotates into single instructions
16+
17+
#[inline]
18+
#[target_feature(enable = "avx512f")]
19+
#[cfg_attr(test, assert_instr(vprorvq))]
20+
unsafe fn rotate_right_variable(x: u64x8, y: u64x8) -> u64x8 {
21+
x.rotate_right(y)
22+
}
23+
24+
#[inline]
25+
#[target_feature(enable = "avx512f")]
26+
#[cfg_attr(test, assert_instr(vprolvq))]
27+
unsafe fn rotate_left_variable(x: u64x8, y: u64x8) -> u64x8 {
28+
x.rotate_left(y)
29+
}
30+
31+
#[inline]
32+
#[target_feature(enable = "avx512f")]
33+
#[cfg_attr(test, assert_instr(vprorq))]
34+
unsafe fn rotate_right(x: u64x8, y: u64) -> u64x8 {
35+
x.rotate_right(y)
36+
}
37+
38+
#[inline]
39+
#[target_feature(enable = "avx512f")]
40+
#[cfg_attr(test, assert_instr(vprolq))]
41+
unsafe fn rotate_left(x: u64x8, y: u64) -> u64x8 {
42+
x.rotate_left(y)
43+
}

0 commit comments

Comments
 (0)