Skip to content

Commit

Permalink
scalar rotates, rotate instr tests
Browse files Browse the repository at this point in the history
  • Loading branch information
TheIronBorn committed Jun 25, 2018
1 parent 1271a3f commit 160ecb4
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 17 deletions.
2 changes: 2 additions & 0 deletions coresimd/ppsv/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ mod shifts;
#[macro_use]
mod rotates;

pub use self::rotates::Rotate;

/// Sealed trait used for constraining select implementations.
pub trait Lanes<A> {}

Expand Down
55 changes: 38 additions & 17 deletions coresimd/ppsv/api/rotates.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,59 @@
//! Implements integer rotates.
#![allow(unused)]

/// Trait used for overloading rotates
pub trait Rotate<T> {
/// Shifts the bits of each lane to the left by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the end of the resulting integer.
///
/// Please note this isn't the same operation as `<<`!. Also note it
/// isn't equivalent to `slice::rotate_left`, it doesn't move the vector's
/// lanes around. (that can be implemented with vector shuffles).
fn rotate_left(self, n: T) -> Self;

/// Shifts the bits of each lane to the right by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the beginning of the resulting integer.
///
/// Please note this isn't the same operation as `>>`!. Also note it
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
/// lanes around. (that can be implemented with vector shuffles).
fn rotate_right(self, n: T) -> Self;
}

macro_rules! impl_vector_rotates {
($id:ident, $elem_ty:ident) => {
impl $id {
/// Shifts the bits of each lane to the left by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the end of the resulting integer.
///
/// Please note this isn't the same operation as `<<`!. Also note it
/// isn't equivalent to `slice::rotate_left` (that can be implemented
/// with vector shuffles).
impl super::api::Rotate<$id> for $id {
#[inline]
pub fn rotate_left(self, n: $id) -> $id {
fn rotate_left(self, n: $id) -> $id {
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
// Protect against undefined behavior for over-long bit shifts
let n = n % LANE_WIDTH;
(self << n) | (self >> ((LANE_WIDTH - n) % LANE_WIDTH))
}

/// Shifts the bits of each lane to the right by the specified amount in
/// the corresponding lane of `n`, wrapping the truncated bits to
/// the beginning of the resulting integer.
///
/// Please note this isn't the same operation as `>>`!. Also note it
/// isn't similar to `slice::rotate_right`, it doesn't move the vector's
/// lanes around. (that can be implemented with vector shuffles).
#[inline]
pub fn rotate_right(self, n: $id) -> $id {
fn rotate_right(self, n: $id) -> $id {
const LANE_WIDTH: $elem_ty = ::mem::size_of::<$elem_ty>() as $elem_ty * 8;
// Protect against undefined behavior for over-long bit shifts
let n = n % LANE_WIDTH;
(self >> n) | (self << ((LANE_WIDTH - n) % LANE_WIDTH))
}
}

impl super::api::Rotate<$elem_ty> for $id {
#[inline]
fn rotate_left(self, n: $elem_ty) -> $id {
self.rotate_left($id::splat(n))
}


#[inline]
fn rotate_right(self, n: $elem_ty) -> $id {
self.rotate_right($id::splat(n))
}
}
};
}

Expand All @@ -43,6 +63,7 @@ macro_rules! test_vector_rotate_ops {
#[test]
fn rotate_ops() {
use coresimd::simd::$id;
use coresimd::simd::Rotate;;
use std::mem;
let z = $id::splat(0 as $elem_ty);
let o = $id::splat(1 as $elem_ty);
Expand Down
2 changes: 2 additions & 0 deletions coresimd/ppsv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub use self::v32::*;
pub use self::v512::*;
pub use self::v64::*;

pub use self::api::Rotate;

/// Safe lossless bitwise conversion from `T` to `Self`.
pub trait FromBits<T>: ::marker::Sized {
/// Safe lossless bitwise from `T` to `Self`.
Expand Down
44 changes: 44 additions & 0 deletions crates/coresimd/tests/rotate_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! rotate instruction tests
#![feature(stdsimd)]
#![feature(proc_macro)]
#![feature(avx512_target_feature)]
#![feature(abi_vectorcall)]

#[macro_use]
// extern crate assert_instr_macro;
extern crate stdsimd_test;
extern crate stdsimd;

use stdsimd::simd::*;
use stdsimd_test::assert_instr;

// Verify that supported hardware compiles rotates into single instructions

#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vprorvq))]
unsafe fn rotate_right_variable(x: u64x8, y: u64x8) -> u64x8 {
x.rotate_right(y)
}

#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vprolvq))]
unsafe fn rotate_left_variable(x: u64x8, y: u64x8) -> u64x8 {
x.rotate_left(y)
}

#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vprorq))]
unsafe fn rotate_right(x: u64x8, y: u64) -> u64x8 {
x.rotate_right(y)
}

#[inline]
#[target_feature(enable = "avx512f")]
#[cfg_attr(test, assert_instr(vprolq))]
unsafe fn rotate_left(x: u64x8, y: u64) -> u64x8 {
x.rotate_left(y)
}

0 comments on commit 160ecb4

Please sign in to comment.