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

Use addcarryx LLVM intrinsics and add tests for addcarry and subborrow intrinsics #672

Merged
merged 1 commit into from
Jan 31, 2019
Merged
Show file tree
Hide file tree
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
106 changes: 105 additions & 1 deletion crates/core_arch/src/x86/adx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use stdsimd_test::assert_instr;
extern "unadjusted" {
#[link_name = "llvm.x86.addcarry.32"]
fn llvm_addcarry_u32(a: u8, b: u32, c: u32) -> (u8, u32);
#[link_name = "llvm.x86.addcarryx.u32"]
fn llvm_addcarryx_u32(a: u8, b: u32, c: u32, d: *mut u8) -> u8;
#[link_name = "llvm.x86.subborrow.32"]
fn llvm_subborrow_u32(a: u8, b: u32, c: u32) -> (u8, u32);
}
Expand All @@ -30,7 +32,8 @@ pub unsafe fn _addcarry_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 {
#[stable(feature = "simd_x86_adx", since = "1.33.0")]
#[cfg(not(stage0))]
pub unsafe fn _addcarryx_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 {
_addcarry_u32(c_in, a, b, out)
let r = llvm_addcarryx_u32(c_in, a, b, out as *mut _ as *mut u8);
r
}

/// Add unsigned 32-bit integers a and b with unsigned 8-bit carry-in `c_in`
Expand All @@ -44,3 +47,104 @@ pub unsafe fn _subborrow_u32(c_in: u8, a: u32, b: u32, out: &mut u32) -> u8 {
*out = b;
a
}

#[cfg(test)]
mod tests {
use stdsimd_test::simd_test;

use core_arch::x86::*;

#[test]
fn test_addcarry_u32() {
unsafe {
let a = u32::max_value();
let mut out = 0;

let r = _addcarry_u32(0, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u32(0, a, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, a);

let r = _addcarry_u32(1, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 1);

let r = _addcarry_u32(1, a, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u32(0, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 7);

let r = _addcarry_u32(1, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 8);
}
}

#[simd_test(enable = "adx")]
unsafe fn test_addcarryx_u32() {
let a = u32::max_value();
let mut out = 0;

let r = _addcarry_u32(0, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u32(0, a, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, a);

let r = _addcarry_u32(1, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 1);

let r = _addcarry_u32(1, a, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u32(0, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 7);

let r = _addcarry_u32(1, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 8);
}

#[test]
fn test_subborrow_u32() {
unsafe {
let a = u32::max_value();
let mut out = 0;

let r = _subborrow_u32(0, 0, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a);

let r = _subborrow_u32(0, 0, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 0);

let r = _subborrow_u32(1, 0, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a - 1);

let r = _subborrow_u32(1, 0, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a);

let r = _subborrow_u32(0, 7, 3, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 4);

let r = _subborrow_u32(1, 7, 3, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 3);
}
}
}
105 changes: 104 additions & 1 deletion crates/core_arch/src/x86_64/adx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ use stdsimd_test::assert_instr;
extern "unadjusted" {
#[link_name = "llvm.x86.addcarry.64"]
fn llvm_addcarry_u64(a: u8, b: u64, c: u64) -> (u8, u64);
#[link_name = "llvm.x86.addcarryx.u64"]
fn llvm_addcarryx_u64(a: u8, b: u64, c: u64, d: *mut u8) -> u8;
#[link_name = "llvm.x86.subborrow.64"]
fn llvm_subborrow_u64(a: u8, b: u64, c: u64) -> (u8, u64);
}
Expand All @@ -30,7 +32,7 @@ pub unsafe fn _addcarry_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
#[stable(feature = "simd_x86_adx", since = "1.33.0")]
#[cfg(not(stage0))]
pub unsafe fn _addcarryx_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
_addcarry_u64(c_in, a, b, out)
llvm_addcarryx_u64(c_in, a, b, out as *mut _ as *mut u8)
}

/// Add unsigned 64-bit integers a and b with unsigned 8-bit carry-in `c_in`
Expand All @@ -44,3 +46,104 @@ pub unsafe fn _subborrow_u64(c_in: u8, a: u64, b: u64, out: &mut u64) -> u8 {
*out = b;
a
}

#[cfg(test)]
mod tests {
use stdsimd_test::simd_test;

use core_arch::x86_64::*;

#[test]
fn test_addcarry_u64() {
unsafe {
let a = u64::max_value();
let mut out = 0;

let r = _addcarry_u64(0, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u64(0, a, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, a);

let r = _addcarry_u64(1, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 1);

let r = _addcarry_u64(1, a, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u64(0, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 7);

let r = _addcarry_u64(1, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 8);
}
}

#[simd_test(enable = "adx")]
unsafe fn test_addcarryx_u64() {
let a = u64::max_value();
let mut out = 0;

let r = _addcarry_u64(0, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u64(0, a, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, a);

let r = _addcarry_u64(1, a, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 1);

let r = _addcarry_u64(1, a, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, 0);

let r = _addcarry_u64(0, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 7);

let r = _addcarry_u64(1, 3, 4, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 8);
}

#[test]
fn test_subborrow_u64() {
unsafe {
let a = u64::max_value();
let mut out = 0;

let r = _subborrow_u64(0, 0, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a);

let r = _subborrow_u64(0, 0, 0, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 0);

let r = _subborrow_u64(1, 0, 1, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a - 1);

let r = _subborrow_u64(1, 0, 0, &mut out);
assert_eq!(r, 1);
assert_eq!(out, a);

let r = _subborrow_u64(0, 7, 3, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 4);

let r = _subborrow_u64(1, 7, 3, &mut out);
assert_eq!(r, 0);
assert_eq!(out, 3);
}
}
}