Skip to content

Commit

Permalink
Auto merge of rust-lang#92604 - nnethercote:optimize-impl_read_unsign…
Browse files Browse the repository at this point in the history
…ed_leb128, r=michaelwoerister

Optimize `impl_read_unsigned_leb128`

I see instruction count improvements of up to 3.5% locally with these changes, mostly on the smaller benchmarks.

r? `@michaelwoerister`
  • Loading branch information
bors committed Jan 15, 2022
2 parents 69d25fc + facba24 commit 38c22af
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 21 deletions.
31 changes: 19 additions & 12 deletions compiler/rustc_serialize/src/leb128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,24 @@ impl_write_unsigned_leb128!(write_usize_leb128, usize);
macro_rules! impl_read_unsigned_leb128 {
($fn_name:ident, $int_ty:ty) => {
#[inline]
pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
let mut result = 0;
let mut shift = 0;
let mut position = 0;
pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
// 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;
let byte = slice[*position];
*position += 1;
if (byte & 0x80) == 0 {
result |= (byte as $int_ty) << shift;
return (result, position);
return result;
} else {
result |= ((byte & 0x7F) as $int_ty) << shift;
}
Expand Down Expand Up @@ -122,15 +130,14 @@ impl_write_signed_leb128!(write_isize_leb128, isize);
macro_rules! impl_read_signed_leb128 {
($fn_name:ident, $int_ty:ty) => {
#[inline]
pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
let mut result = 0;
let mut shift = 0;
let mut position = 0;
let mut byte;

loop {
byte = slice[position];
position += 1;
byte = slice[*position];
*position += 1;
result |= <$int_ty>::from(byte & 0x7F) << shift;
shift += 7;

Expand All @@ -144,7 +151,7 @@ macro_rules! impl_read_signed_leb128 {
result |= (!0 << shift);
}

(result, position)
result
}
};
}
Expand Down
6 changes: 1 addition & 5 deletions compiler/rustc_serialize/src/opaque.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,11 +560,7 @@ impl<'a> Decoder<'a> {
}

macro_rules! read_leb128 {
($dec:expr, $fun:ident) => {{
let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position..]);
$dec.position += bytes_read;
Ok(value)
}};
($dec:expr, $fun:ident) => {{ Ok(leb128::$fun($dec.data, &mut $dec.position)) }};
}

impl<'a> serialize::Decoder for Decoder<'a> {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_serialize/tests/leb128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ macro_rules! impl_test_unsigned_leb128 {

let mut position = 0;
for &expected in &values {
let (actual, bytes_read) = $read_fn_name(&stream[position..]);
let actual = $read_fn_name(&stream, &mut position);
assert_eq!(expected, actual);
position += bytes_read;
}
assert_eq!(stream.len(), position);
}
Expand Down Expand Up @@ -77,9 +76,8 @@ macro_rules! impl_test_signed_leb128 {

let mut position = 0;
for &expected in &values {
let (actual, bytes_read) = $read_fn_name(&stream[position..]);
let actual = $read_fn_name(&stream, &mut position);
assert_eq!(expected, actual);
position += bytes_read;
}
assert_eq!(stream.len(), position);
}
Expand Down

0 comments on commit 38c22af

Please sign in to comment.