Skip to content

Commit 4479cb8

Browse files
committed
Auto merge of #89459 - tspiteri:idiv-overflow-bitand, r=kennytm
Use bitand when checking for signed integer division overflow For `self == Self::MIN && rhs == -1`, LLVM does not realize that this is the same check made by `self / rhs`, so the code generated may have some unnecessary duplication. For `(self == Self::MIN) & (rhs == -1)`, LLVM realizes it is the same check.
2 parents c24c906 + 1139ee3 commit 4479cb8

File tree

1 file changed

+16
-8
lines changed

1 file changed

+16
-8
lines changed

library/core/src/num/int_macros.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,8 @@ macro_rules! int_impl {
543543
without modifying the original"]
544544
#[inline]
545545
pub const fn checked_div(self, rhs: Self) -> Option<Self> {
546-
if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
546+
// Using `&` helps LLVM see that it is the same check made in division.
547+
if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
547548
None
548549
} else {
549550
// SAFETY: div by zero and by INT_MIN have been checked above
@@ -569,7 +570,8 @@ macro_rules! int_impl {
569570
without modifying the original"]
570571
#[inline]
571572
pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
572-
if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
573+
// Using `&` helps LLVM see that it is the same check made in division.
574+
if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
573575
None
574576
} else {
575577
Some(self.div_euclid(rhs))
@@ -595,7 +597,8 @@ macro_rules! int_impl {
595597
without modifying the original"]
596598
#[inline]
597599
pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
598-
if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
600+
// Using `&` helps LLVM see that it is the same check made in division.
601+
if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
599602
None
600603
} else {
601604
// SAFETY: div by zero and by INT_MIN have been checked above
@@ -621,7 +624,8 @@ macro_rules! int_impl {
621624
without modifying the original"]
622625
#[inline]
623626
pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
624-
if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
627+
// Using `&` helps LLVM see that it is the same check made in division.
628+
if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
625629
None
626630
} else {
627631
Some(self.rem_euclid(rhs))
@@ -1466,7 +1470,8 @@ macro_rules! int_impl {
14661470
#[must_use = "this returns the result of the operation, \
14671471
without modifying the original"]
14681472
pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
1469-
if unlikely!(self == Self::MIN && rhs == -1) {
1473+
// Using `&` helps LLVM see that it is the same check made in division.
1474+
if unlikely!((self == Self::MIN) & (rhs == -1)) {
14701475
(self, true)
14711476
} else {
14721477
(self / rhs, false)
@@ -1496,7 +1501,8 @@ macro_rules! int_impl {
14961501
#[must_use = "this returns the result of the operation, \
14971502
without modifying the original"]
14981503
pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
1499-
if unlikely!(self == Self::MIN && rhs == -1) {
1504+
// Using `&` helps LLVM see that it is the same check made in division.
1505+
if unlikely!((self == Self::MIN) & (rhs == -1)) {
15001506
(self, true)
15011507
} else {
15021508
(self.div_euclid(rhs), false)
@@ -1527,7 +1533,8 @@ macro_rules! int_impl {
15271533
#[must_use = "this returns the result of the operation, \
15281534
without modifying the original"]
15291535
pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
1530-
if unlikely!(self == Self::MIN && rhs == -1) {
1536+
// Using `&` helps LLVM see that it is the same check made in division.
1537+
if unlikely!((self == Self::MIN) & (rhs == -1)) {
15311538
(0, true)
15321539
} else {
15331540
(self % rhs, false)
@@ -1558,7 +1565,8 @@ macro_rules! int_impl {
15581565
without modifying the original"]
15591566
#[inline]
15601567
pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
1561-
if unlikely!(self == Self::MIN && rhs == -1) {
1568+
// Using `&` helps LLVM see that it is the same check made in division.
1569+
if unlikely!((self == Self::MIN) & (rhs == -1)) {
15621570
(0, true)
15631571
} else {
15641572
(self.rem_euclid(rhs), false)

0 commit comments

Comments
 (0)