diff options
| author | bors <bors@rust-lang.org> | 2022-04-15 23:15:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-04-15 23:15:51 +0000 |
| commit | bb1a03c4fcbe547168fab128fa39b08d1122a1c2 (patch) | |
| tree | 49856ac6e614484fd3439be2f5fd372d650a0b78 | |
| parent | 3f391b84552f210adec7893b50c5da74f9362ae4 (diff) | |
| parent | 8d14c03568d0ec99c586e17ce19a93cc0684ab9e (diff) | |
| download | rust-bb1a03c4fcbe547168fab128fa39b08d1122a1c2.tar.gz rust-bb1a03c4fcbe547168fab128fa39b08d1122a1c2.zip | |
Auto merge of #95224 - mjbshaw:patch-1, r=yaahc
Optimize RcInnerPtr::inc_strong()/inc_weak() instruction count Inspired by this internals thread: https://internals.rust-lang.org/t/rc-optimization-on-64-bit-targets/16362 [The generated assembly is a bit smaller](https://rust.godbolt.org/z/TeTnf6144) and is a more efficient usage of the CPU's instruction cache. `unlikely` doesn't impact any of the small artificial tests I've done, but I've included it in case it might help more complex scenarios when this is inlined.
| -rw-r--r-- | library/alloc/src/rc.rs | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index d0d37c08d13..a42f1c3b4bb 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -2511,14 +2511,23 @@ trait RcInnerPtr { fn inc_strong(&self) { let strong = self.strong(); + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { + core::intrinsics::assume(strong != 0); + } + + let strong = strong.wrapping_add(1); + self.strong_ref().set(strong); + // We want to abort on overflow instead of dropping the value. - // The reference count will never be zero when this is called; - // nevertheless, we insert an abort here to hint LLVM at - // an otherwise missed optimization. - if strong == 0 || strong == usize::MAX { + // Checking for overflow after the store instead of before + // allows for slightly better code generation. + if core::intrinsics::unlikely(strong == 0) { abort(); } - self.strong_ref().set(strong + 1); } #[inline] @@ -2535,14 +2544,23 @@ trait RcInnerPtr { fn inc_weak(&self) { let weak = self.weak(); + // We insert an `assume` here to hint LLVM at an otherwise + // missed optimization. + // SAFETY: The reference count will never be zero when this is + // called. + unsafe { + core::intrinsics::assume(weak != 0); + } + + let weak = weak.wrapping_add(1); + self.weak_ref().set(weak); + // We want to abort on overflow instead of dropping the value. - // The reference count will never be zero when this is called; - // nevertheless, we insert an abort here to hint LLVM at - // an otherwise missed optimization. - if weak == 0 || weak == usize::MAX { + // Checking for overflow after the store instead of before + // allows for slightly better code generation. + if core::intrinsics::unlikely(weak == 0) { abort(); } - self.weak_ref().set(weak + 1); } #[inline] |
