about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <n.nethercote@gmail.com>2022-01-07 11:50:52 +1100
committerNicholas Nethercote <n.nethercote@gmail.com>2022-01-07 13:36:26 +1100
commitfacba24926e218f996a953b0d91494a04374b217 (patch)
treecb36da36e703595a68287325caf208e7a4de7ddb
parent5f549d9b49868648f0fb152aa12084dcb859ee45 (diff)
downloadrust-facba24926e218f996a953b0d91494a04374b217.tar.gz
rust-facba24926e218f996a953b0d91494a04374b217.zip
Unpeel the first iteration of the loop in impl_read_unsigned_leb128.
-rw-r--r--compiler/rustc_serialize/src/leb128.rs13
1 files changed, 11 insertions, 2 deletions
diff --git a/compiler/rustc_serialize/src/leb128.rs b/compiler/rustc_serialize/src/leb128.rs
index de333774763..08b3c054200 100644
--- a/compiler/rustc_serialize/src/leb128.rs
+++ b/compiler/rustc_serialize/src/leb128.rs
@@ -54,8 +54,17 @@ macro_rules! impl_read_unsigned_leb128 {
     ($fn_name:ident, $int_ty:ty) => {
         #[inline]
         pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
-            let mut result = 0;
-            let mut shift = 0;
+            // The first iteration of this loop is unpeeled. This is a
+            // performance win because this code is hot and integer values less
+            // than 128 are very common, typically occurring 50-80% or more of
+            // the time, even for u64 and u128.
+            let byte = slice[*position];
+            *position += 1;
+            if (byte & 0x80) == 0 {
+                return byte as $int_ty;
+            }
+            let mut result = (byte & 0x7F) as $int_ty;
+            let mut shift = 7;
             loop {
                 let byte = slice[*position];
                 *position += 1;