Skip to content

Commit bb1a03c

Browse files
committed
Auto merge of rust-lang#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.
2 parents 3f391b8 + 8d14c03 commit bb1a03c

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

library/alloc/src/rc.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -2511,14 +2511,23 @@ trait RcInnerPtr {
25112511
fn inc_strong(&self) {
25122512
let strong = self.strong();
25132513

2514+
// We insert an `assume` here to hint LLVM at an otherwise
2515+
// missed optimization.
2516+
// SAFETY: The reference count will never be zero when this is
2517+
// called.
2518+
unsafe {
2519+
core::intrinsics::assume(strong != 0);
2520+
}
2521+
2522+
let strong = strong.wrapping_add(1);
2523+
self.strong_ref().set(strong);
2524+
25142525
// We want to abort on overflow instead of dropping the value.
2515-
// The reference count will never be zero when this is called;
2516-
// nevertheless, we insert an abort here to hint LLVM at
2517-
// an otherwise missed optimization.
2518-
if strong == 0 || strong == usize::MAX {
2526+
// Checking for overflow after the store instead of before
2527+
// allows for slightly better code generation.
2528+
if core::intrinsics::unlikely(strong == 0) {
25192529
abort();
25202530
}
2521-
self.strong_ref().set(strong + 1);
25222531
}
25232532

25242533
#[inline]
@@ -2535,14 +2544,23 @@ trait RcInnerPtr {
25352544
fn inc_weak(&self) {
25362545
let weak = self.weak();
25372546

2547+
// We insert an `assume` here to hint LLVM at an otherwise
2548+
// missed optimization.
2549+
// SAFETY: The reference count will never be zero when this is
2550+
// called.
2551+
unsafe {
2552+
core::intrinsics::assume(weak != 0);
2553+
}
2554+
2555+
let weak = weak.wrapping_add(1);
2556+
self.weak_ref().set(weak);
2557+
25382558
// We want to abort on overflow instead of dropping the value.
2539-
// The reference count will never be zero when this is called;
2540-
// nevertheless, we insert an abort here to hint LLVM at
2541-
// an otherwise missed optimization.
2542-
if weak == 0 || weak == usize::MAX {
2559+
// Checking for overflow after the store instead of before
2560+
// allows for slightly better code generation.
2561+
if core::intrinsics::unlikely(weak == 0) {
25432562
abort();
25442563
}
2545-
self.weak_ref().set(weak + 1);
25462564
}
25472565

25482566
#[inline]

0 commit comments

Comments
 (0)