Skip to content

Commit 3c488df

Browse files
committed
Auto merge of rust-lang#126852 - scottmcm:more-checked-math-tweaks, r=<try>
Also get `add nuw` from `uN::checked_add` When I was doing this for `checked_{sub,shl,shr}`, it was mentioned rust-lang#124114 (comment) that it'd be worth trying for `checked_add` too. It makes a particularly-big difference for `x.checked_add(C)`, as doing this means that LLVM removes the intrinsic and does it as a normal `x <= MAX - C` instead. cc `@DianQK` who had commented about `checked_add` related to rust-lang/hashbrown#509 before cc llvm/llvm-project#80637 for how LLVM is unlikely to do this itself
2 parents aabbf84 + a53dd2f commit 3c488df

4 files changed

+47
-32
lines changed

library/core/src/num/uint_macros.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,19 @@ macro_rules! uint_impl {
455455
without modifying the original"]
456456
#[inline]
457457
pub const fn checked_add(self, rhs: Self) -> Option<Self> {
458-
let (a, b) = self.overflowing_add(rhs);
459-
if unlikely!(b) { None } else { Some(a) }
458+
// This used to use `overflowing_add`, but that means it ends up being
459+
// a `wrapping_add`, losing some optimization opportunities. Notably,
460+
// phrasing it this way helps `.checked_add(1)` optimize to a check
461+
// against `MAX` and a `add nuw`.
462+
// Per <https://github.com/rust-lang/rust/pull/124114#issuecomment-2066173305>,
463+
// LLVM is happy to re-form the intrinsic later if useful.
464+
465+
if unlikely!(intrinsics::add_with_overflow(self, rhs).1) {
466+
None
467+
} else {
468+
// SAFETY: Just checked it doesn't overflow
469+
Some(unsafe { intrinsics::unchecked_add(self, rhs) })
470+
}
460471
}
461472

462473
/// Strict integer addition. Computes `self + rhs`, panicking

tests/codegen/checked_math.rs

+14
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,17 @@ pub fn checked_shr_signed(a: i32, b: u32) -> Option<i32> {
8484
// CHECK: ret { i32, i32 } %[[R1]]
8585
a.checked_shr(b)
8686
}
87+
88+
// CHECK-LABEL: @checked_add_one_unwrap_unsigned
89+
// CHECK-SAME: (i32 noundef %x)
90+
#[no_mangle]
91+
pub fn checked_add_one_unwrap_unsigned(x: u32) -> u32 {
92+
// CHECK: %[[IS_MAX:.+]] = icmp eq i32 %x, -1
93+
// CHECK: br i1 %[[IS_MAX]], label %[[NONE_BB:.+]], label %[[SOME_BB:.+]]
94+
// CHECK: [[SOME_BB]]:
95+
// CHECK: %[[R:.+]] = add nuw i32 %x, 1
96+
// CHECK: ret i32 %[[R]]
97+
// CHECK: [[NONE_BB]]:
98+
// CHECK: call {{.+}}unwrap_failed
99+
x.checked_add(1).unwrap()
100+
}

tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-abort.mir

+10-15
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,21 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
1111
scope 3 (inlined <u16 as Step>::forward_checked) {
1212
scope 4 {
1313
scope 6 (inlined core::num::<impl u16>::checked_add) {
14+
let mut _5: (u16, bool);
15+
let mut _6: bool;
1416
let mut _7: bool;
15-
scope 7 {
16-
}
17-
scope 8 (inlined core::num::<impl u16>::overflowing_add) {
18-
let mut _5: (u16, bool);
19-
let _6: bool;
20-
scope 9 {
21-
}
22-
}
2317
}
2418
}
2519
scope 5 (inlined convert::num::ptr_try_from_impls::<impl TryFrom<usize> for u16>::try_from) {
2620
let mut _3: bool;
2721
let mut _4: u16;
2822
}
2923
}
30-
scope 10 (inlined Option::<u16>::is_none) {
31-
scope 11 (inlined Option::<u16>::is_some) {
24+
scope 7 (inlined Option::<u16>::is_none) {
25+
scope 8 (inlined Option::<u16>::is_some) {
3226
}
3327
}
34-
scope 12 (inlined core::num::<impl u16>::wrapping_add) {
28+
scope 9 (inlined core::num::<impl u16>::wrapping_add) {
3529
}
3630
}
3731

@@ -45,12 +39,11 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
4539
bb1: {
4640
_4 = _2 as u16 (IntToInt);
4741
StorageDead(_3);
42+
StorageLive(_7);
4843
StorageLive(_6);
4944
StorageLive(_5);
5045
_5 = AddWithOverflow(_1, _4);
5146
_6 = (_5.1: bool);
52-
StorageDead(_5);
53-
StorageLive(_7);
5447
_7 = unlikely(move _6) -> [return: bb2, unwind unreachable];
5548
}
5649

@@ -59,14 +52,16 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
5952
}
6053

6154
bb3: {
62-
StorageDead(_7);
55+
StorageDead(_5);
6356
StorageDead(_6);
57+
StorageDead(_7);
6458
goto -> bb7;
6559
}
6660

6761
bb4: {
68-
StorageDead(_7);
62+
StorageDead(_5);
6963
StorageDead(_6);
64+
StorageDead(_7);
7065
goto -> bb6;
7166
}
7267

tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.panic-unwind.mir

+10-15
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,21 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
1111
scope 3 (inlined <u16 as Step>::forward_checked) {
1212
scope 4 {
1313
scope 6 (inlined core::num::<impl u16>::checked_add) {
14+
let mut _5: (u16, bool);
15+
let mut _6: bool;
1416
let mut _7: bool;
15-
scope 7 {
16-
}
17-
scope 8 (inlined core::num::<impl u16>::overflowing_add) {
18-
let mut _5: (u16, bool);
19-
let _6: bool;
20-
scope 9 {
21-
}
22-
}
2317
}
2418
}
2519
scope 5 (inlined convert::num::ptr_try_from_impls::<impl TryFrom<usize> for u16>::try_from) {
2620
let mut _3: bool;
2721
let mut _4: u16;
2822
}
2923
}
30-
scope 10 (inlined Option::<u16>::is_none) {
31-
scope 11 (inlined Option::<u16>::is_some) {
24+
scope 7 (inlined Option::<u16>::is_none) {
25+
scope 8 (inlined Option::<u16>::is_some) {
3226
}
3327
}
34-
scope 12 (inlined core::num::<impl u16>::wrapping_add) {
28+
scope 9 (inlined core::num::<impl u16>::wrapping_add) {
3529
}
3630
}
3731

@@ -45,12 +39,11 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
4539
bb1: {
4640
_4 = _2 as u16 (IntToInt);
4741
StorageDead(_3);
42+
StorageLive(_7);
4843
StorageLive(_6);
4944
StorageLive(_5);
5045
_5 = AddWithOverflow(_1, _4);
5146
_6 = (_5.1: bool);
52-
StorageDead(_5);
53-
StorageLive(_7);
5447
_7 = unlikely(move _6) -> [return: bb2, unwind unreachable];
5548
}
5649

@@ -59,14 +52,16 @@ fn step_forward(_1: u16, _2: usize) -> u16 {
5952
}
6053

6154
bb3: {
62-
StorageDead(_7);
55+
StorageDead(_5);
6356
StorageDead(_6);
57+
StorageDead(_7);
6458
goto -> bb7;
6559
}
6660

6761
bb4: {
68-
StorageDead(_7);
62+
StorageDead(_5);
6963
StorageDead(_6);
64+
StorageDead(_7);
7065
goto -> bb6;
7166
}
7267

0 commit comments

Comments
 (0)