From a43fe21bd8fd53ac736683a07d1d1cda6660f89f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 7 Apr 2016 18:16:40 +0100 Subject: [PATCH 1/2] Add bitreverse intrinsic --- src/libcore/intrinsics.rs | 4 ++++ src/librustc_trans/context.rs | 5 +++++ src/librustc_trans/intrinsic.rs | 5 ++++- src/librustc_typeck/check/intrinsic.rs | 3 ++- src/test/run-pass/intrinsics-integer.rs | 10 ++++++++++ 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 03bcf9caeea0c..a8e7b214c77a6 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -584,6 +584,10 @@ extern "rust-intrinsic" { /// Reverses the bytes in an integer type `T`. pub fn bswap(x: T) -> T; + /// Reverses the bits in an integer type `T`. + #[cfg(not(stage0))] + pub fn bitreverse(x: T) -> T; + /// Performs checked integer addition. pub fn add_with_overflow(x: T, y: T) -> (T, bool); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 9bbc72eba36ef..229a5001db021 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -1001,6 +1001,11 @@ fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option { ifn!("llvm.bswap.i32", fn(t_i32) -> t_i32); ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64); + ifn!("llvm.bitreverse.i8", fn(t_i8) -> t_i8); + ifn!("llvm.bitreverse.i16", fn(t_i16) -> t_i16); + ifn!("llvm.bitreverse.i32", fn(t_i32) -> t_i32); + ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64); + ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index 5924ae1ad84c5..13ad43089ecb8 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -607,7 +607,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, C_nil(ccx) }, - (_, "ctlz") | (_, "cttz") | (_, "ctpop") | (_, "bswap") | + (_, "ctlz") | (_, "cttz") | (_, "ctpop") | (_, "bswap") | (_, "bitreverse") | (_, "add_with_overflow") | (_, "sub_with_overflow") | (_, "mul_with_overflow") | (_, "overflowing_add") | (_, "overflowing_sub") | (_, "overflowing_mul") | (_, "unchecked_div") | (_, "unchecked_rem") => { @@ -629,6 +629,9 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, &llargs, call_debug_location) } } + "bitreverse" => Call(bcx, ccx.get_intrinsic(&format!("llvm.bitreverse.i{}", + width)), + &llargs, call_debug_location), "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let intrinsic = format!("llvm.{}{}.with.overflow.i{}", if signed { 's' } else { 'u' }, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index eae0cfb0f2267..09ea0763be866 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -265,7 +265,8 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) { "volatile_store" => (1, vec!( tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ), tcx.mk_nil()), - "ctpop" | "ctlz" | "cttz" | "bswap" => (1, vec!(param(ccx, 0)), param(ccx, 0)), + "ctpop" | "ctlz" | "cttz" | "bswap" | "bitreverse" => + (1, vec!(param(ccx, 0)), param(ccx, 0)), "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => (1, vec!(param(ccx, 0), param(ccx, 0)), diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 759dc515456de..79ee2b12fd4a9 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -16,6 +16,7 @@ mod rusti { pub fn ctlz(x: T) -> T; pub fn cttz(x: T) -> T; pub fn bswap(x: T) -> T; + pub fn bitreverse(x: T) -> T; } } @@ -101,5 +102,14 @@ pub fn main() { assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A); assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201); assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201); + + assert_eq!(bitreverse(0x0Au8), 0x50); + assert_eq!(bitreverse(0x0Ai8), 0x50); + assert_eq!(bitreverse(0x0A0Cu16), 0x3050); + assert_eq!(bitreverse(0x0A0Ci16), 0x3050); + assert_eq!(bitreverse(0x0ABBCC0Eu32), 0x7033DD50); + assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50); + assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480); + assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480); } } From ec1c74e6aadb5e4364e5ae463aadbd04b43adf83 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 7 Apr 2016 18:16:52 +0100 Subject: [PATCH 2/2] Add reverse_bits to integer types --- src/libcore/num/mod.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 229a864d712c5..44e4018bdb5e9 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -224,6 +224,24 @@ macro_rules! int_impl { (self as $UnsignedT).trailing_zeros() } + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let n = 0b10101000u8; + /// + /// assert_eq!(n.reverse_bits(), 0b00010101u8); + /// ``` + #[cfg(not(stage0))] + #[unstable(feature = "reverse_bits", issue = "0", reason = "recently added")] + #[inline] + pub fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + /// Shifts the bits to the left by a specified amount, `n`, /// wrapping the truncated bits to the end of the resulting integer. /// @@ -1290,6 +1308,24 @@ macro_rules! uint_impl { } } + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// let n = 0b10101000u8; + /// + /// assert_eq!(n.reverse_bits(), 0b00010101u8); + /// ``` + #[cfg(not(stage0))] + #[unstable(feature = "reverse_bits", issue = "0", reason = "recently added")] + #[inline] + pub fn reverse_bits(self) -> Self { + unsafe { intrinsics::bitreverse(self) } + } + /// Shifts the bits to the left by a specified amount, `n`, /// wrapping the truncated bits to the end of the resulting integer. ///