Skip to content

Commit 38c22af

Browse files
committed
Auto merge of #92604 - nnethercote:optimize-impl_read_unsigned_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`
2 parents 69d25fc + facba24 commit 38c22af

File tree

3 files changed

+22
-21
lines changed

3 files changed

+22
-21
lines changed

compiler/rustc_serialize/src/leb128.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,24 @@ impl_write_unsigned_leb128!(write_usize_leb128, usize);
5353
macro_rules! impl_read_unsigned_leb128 {
5454
($fn_name:ident, $int_ty:ty) => {
5555
#[inline]
56-
pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
57-
let mut result = 0;
58-
let mut shift = 0;
59-
let mut position = 0;
56+
pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
57+
// The first iteration of this loop is unpeeled. This is a
58+
// performance win because this code is hot and integer values less
59+
// than 128 are very common, typically occurring 50-80% or more of
60+
// the time, even for u64 and u128.
61+
let byte = slice[*position];
62+
*position += 1;
63+
if (byte & 0x80) == 0 {
64+
return byte as $int_ty;
65+
}
66+
let mut result = (byte & 0x7F) as $int_ty;
67+
let mut shift = 7;
6068
loop {
61-
let byte = slice[position];
62-
position += 1;
69+
let byte = slice[*position];
70+
*position += 1;
6371
if (byte & 0x80) == 0 {
6472
result |= (byte as $int_ty) << shift;
65-
return (result, position);
73+
return result;
6674
} else {
6775
result |= ((byte & 0x7F) as $int_ty) << shift;
6876
}
@@ -122,15 +130,14 @@ impl_write_signed_leb128!(write_isize_leb128, isize);
122130
macro_rules! impl_read_signed_leb128 {
123131
($fn_name:ident, $int_ty:ty) => {
124132
#[inline]
125-
pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
133+
pub fn $fn_name(slice: &[u8], position: &mut usize) -> $int_ty {
126134
let mut result = 0;
127135
let mut shift = 0;
128-
let mut position = 0;
129136
let mut byte;
130137

131138
loop {
132-
byte = slice[position];
133-
position += 1;
139+
byte = slice[*position];
140+
*position += 1;
134141
result |= <$int_ty>::from(byte & 0x7F) << shift;
135142
shift += 7;
136143

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

147-
(result, position)
154+
result
148155
}
149156
};
150157
}

compiler/rustc_serialize/src/opaque.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -560,11 +560,7 @@ impl<'a> Decoder<'a> {
560560
}
561561

562562
macro_rules! read_leb128 {
563-
($dec:expr, $fun:ident) => {{
564-
let (value, bytes_read) = leb128::$fun(&$dec.data[$dec.position..]);
565-
$dec.position += bytes_read;
566-
Ok(value)
567-
}};
563+
($dec:expr, $fun:ident) => {{ Ok(leb128::$fun($dec.data, &mut $dec.position)) }};
568564
}
569565

570566
impl<'a> serialize::Decoder for Decoder<'a> {

compiler/rustc_serialize/tests/leb128.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@ macro_rules! impl_test_unsigned_leb128 {
3030

3131
let mut position = 0;
3232
for &expected in &values {
33-
let (actual, bytes_read) = $read_fn_name(&stream[position..]);
33+
let actual = $read_fn_name(&stream, &mut position);
3434
assert_eq!(expected, actual);
35-
position += bytes_read;
3635
}
3736
assert_eq!(stream.len(), position);
3837
}
@@ -77,9 +76,8 @@ macro_rules! impl_test_signed_leb128 {
7776

7877
let mut position = 0;
7978
for &expected in &values {
80-
let (actual, bytes_read) = $read_fn_name(&stream[position..]);
79+
let actual = $read_fn_name(&stream, &mut position);
8180
assert_eq!(expected, actual);
82-
position += bytes_read;
8381
}
8482
assert_eq!(stream.len(), position);
8583
}

0 commit comments

Comments
 (0)