[abm] use lzcnt and popcnt features

This commit is contained in:
gnzlbg 2017-09-19 22:15:17 +02:00 committed by Andrew Gallant
parent 08a890a0a0
commit e64f80e479

View file

@ -1,10 +1,6 @@
//! Advanced Bit Manipulation (ABM) instructions
//!
//! That is, POPCNT and LZCNT. These instructions have their own CPUID bits to
//! indicate support.
//!
//! TODO: it is unclear which target feature to use here. SSE4.2 should be good
//! enough but we might need to use BMI for LZCNT if there are any problems.
//! The POPCNT and LZCNT have their own CPUID bits to indicate support.
//!
//! The references are:
//!
@ -19,50 +15,50 @@
///
/// When the operand is zero, it returns its size in bits.
#[inline(always)]
#[target_feature = "+sse4.2"]
#[target_feature = "+lzcnt"]
pub fn _lzcnt_u32(x: u32) -> u32 { x.leading_zeros() }
/// Counts the leading most significant zero bits.
///
/// When the operand is zero, it returns its size in bits.
#[inline(always)]
#[target_feature = "+sse4.2"]
#[target_feature = "+lzcnt"]
pub fn _lzcnt_u64(x: u64) -> u64 { x.leading_zeros() as u64 }
/// Counts the bits that are set.
#[inline(always)]
#[target_feature = "+sse4.2"]
#[target_feature = "+popcnt"]
pub fn _popcnt32(x: u32) -> u32 { x.count_ones() }
/// Counts the bits that are set.
#[inline(always)]
#[target_feature = "+sse4.2"]
#[target_feature = "+popcnt"]
pub fn _popcnt64(x: u64) -> u64 { x.count_ones() as u64 }
#[cfg(all(test, target_feature = "sse4.2", any(target_arch = "x86", target_arch = "x86_64")))]
#[cfg(all(test, target_feature = "bmi", any(target_arch = "x86", target_arch = "x86_64")))]
mod tests {
use x86::abm;
#[test]
#[target_feature = "+sse4.2"]
#[target_feature = "+lzcnt"]
fn _lzcnt_u32() {
assert_eq!(abm::_lzcnt_u32(0b0101_1010u32), 25u32);
}
#[test]
#[target_feature = "+sse4.2"]
#[target_feature = "+lzcnt"]
fn _lzcnt_u64() {
assert_eq!(abm::_lzcnt_u64(0b0101_1010u64), 57u64);
}
#[test]
#[target_feature = "+sse4.2"]
#[target_feature = "+popcnt"]
fn _popcnt32() {
assert_eq!(abm::_popcnt32(0b0101_1010u32), 4);
}
#[test]
#[target_feature = "+sse4.2"]
#[target_feature = "+popcnt"]
fn _popcnt64() {
assert_eq!(abm::_popcnt64(0b0101_1010u64), 4);
}