Skip to content

Commit dfdb356

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

File tree

4 files changed

+91
-17
lines changed

4 files changed

+91
-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

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

0 commit comments

Comments
 (0)