about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-10-03 10:34:57 +0000
committerbors <bors@rust-lang.org>2021-10-03 10:34:57 +0000
commit4479cb82e52989480a238e0cf8c67e04b655b36d (patch)
tree280d3ac19e09d225644b96007748a417eacebd25
parentc24c9067eec3aec8dd2013d24f6cd0dff3ecec4c (diff)
parent1139ee32aa803401198c02d5541accbf3fddfc94 (diff)
downloadrust-4479cb82e52989480a238e0cf8c67e04b655b36d.tar.gz
rust-4479cb82e52989480a238e0cf8c67e04b655b36d.zip
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.
-rw-r--r--library/core/src/num/int_macros.rs24
1 files changed, 16 insertions, 8 deletions
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index daef5c98967..526e0c37188 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -543,7 +543,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_div(self, rhs: Self) -> Option<Self> {
-            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
                 None
             } else {
                 // SAFETY: div by zero and by INT_MIN have been checked above
@@ -569,7 +570,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_div_euclid(self, rhs: Self) -> Option<Self> {
-            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
                 None
             } else {
                 Some(self.div_euclid(rhs))
@@ -595,7 +597,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_rem(self, rhs: Self) -> Option<Self> {
-            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
                 None
             } else {
                 // SAFETY: div by zero and by INT_MIN have been checked above
@@ -621,7 +624,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn checked_rem_euclid(self, rhs: Self) -> Option<Self> {
-            if unlikely!(rhs == 0 || (self == Self::MIN && rhs == -1)) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!(rhs == 0 || ((self == Self::MIN) & (rhs == -1))) {
                 None
             } else {
                 Some(self.rem_euclid(rhs))
@@ -1466,7 +1470,8 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
-            if unlikely!(self == Self::MIN && rhs == -1) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!((self == Self::MIN) & (rhs == -1)) {
                 (self, true)
             } else {
                 (self / rhs, false)
@@ -1496,7 +1501,8 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
-            if unlikely!(self == Self::MIN && rhs == -1) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!((self == Self::MIN) & (rhs == -1)) {
                 (self, true)
             } else {
                 (self.div_euclid(rhs), false)
@@ -1527,7 +1533,8 @@ macro_rules! int_impl {
         #[must_use = "this returns the result of the operation, \
                       without modifying the original"]
         pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
-            if unlikely!(self == Self::MIN && rhs == -1) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!((self == Self::MIN) & (rhs == -1)) {
                 (0, true)
             } else {
                 (self % rhs, false)
@@ -1558,7 +1565,8 @@ macro_rules! int_impl {
                       without modifying the original"]
         #[inline]
         pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
-            if unlikely!(self == Self::MIN && rhs == -1) {
+            // Using `&` helps LLVM see that it is the same check made in division.
+            if unlikely!((self == Self::MIN) & (rhs == -1)) {
                 (0, true)
             } else {
                 (self.rem_euclid(rhs), false)