Browse Source

Merge pull request #267 from Lokathor/master

Adding __clzsi2
Alex Crichton 6 years ago
parent
commit
9710af9a33
2 changed files with 90 additions and 0 deletions
  1. 65 0
      src/int/mod.rs
  2. 25 0
      testcrate/tests/count_leading_zeros.rs

+ 65 - 0
src/int/mod.rs

@@ -300,3 +300,68 @@ macro_rules! impl_wide_int {
 
 impl_wide_int!(u32, u64, 32);
 impl_wide_int!(u64, u128, 64);
+
+intrinsics! {
+    #[cfg(any(
+        target_pointer_width = "16",
+        target_pointer_width = "32",
+        target_pointer_width = "64"
+    ))]
+    pub extern "C" fn __clzsi2(x: usize) -> usize {
+        // TODO: const this? Would require const-if
+        // Note(Lokathor): the `intrinsics!` macro can't process mut inputs
+        let mut x = x; 
+        let mut y: usize;
+        let mut n: usize = {
+            #[cfg(target_pointer_width = "64")]
+            {
+                64
+            }
+            #[cfg(target_pointer_width = "32")]
+            {
+                32
+            }
+            #[cfg(target_pointer_width = "16")]
+            {
+                16
+            }
+        };
+        #[cfg(target_pointer_width = "64")]
+        {
+            y = x >> 32;
+            if y != 0 {
+                n -= 32;
+                x = y;
+            }
+        }
+        #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
+        {
+            y = x >> 16;
+            if y != 0 {
+                n -= 16;
+                x = y;
+            }
+        }
+        y = x >> 8;
+        if y != 0 {
+            n -= 8;
+            x = y;
+        }
+        y = x >> 4;
+        if y != 0 {
+            n -= 4;
+            x = y;
+        }
+        y = x >> 2;
+        if y != 0 {
+            n -= 2;
+            x = y;
+        }
+        y = x >> 1;
+        if y != 0 {
+            n - 2
+        } else {
+            n - x
+        }
+    }
+}

+ 25 - 0
testcrate/tests/count_leading_zeros.rs

@@ -0,0 +1,25 @@
+#![feature(compiler_builtins_lib)]
+
+extern crate compiler_builtins;
+
+use compiler_builtins::int::__clzsi2;
+
+#[test]
+fn __clzsi2_test() {
+  let mut i: usize = core::usize::MAX;
+  // Check all values above 0
+  while i > 0 {
+    assert_eq!(__clzsi2(i) as u32, i.leading_zeros());
+    i >>= 1;
+  }
+  // check 0 also
+  i = 0;
+  assert_eq!(__clzsi2(i) as u32, i.leading_zeros());
+  // double check for bit patterns that aren't just solid 1s
+  i = 1;
+  for _ in 0..63 {
+    assert_eq!(__clzsi2(i) as u32, i.leading_zeros());
+    i <<= 2;
+    i += 1;
+  }
+}