summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2020-05-14 14:40:41 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-05-21 12:19:37 -0400
commita95bbd0bdf06d7d61b0bef6de77b59ca31b2c32d (patch)
tree55d752c5f4caf6fc4fa12ecb7ac3aa48d13f9554
parent2b363ebb988cbf8c92df24eef5366293a80ecb19 (diff)
downloadhaskell-a95bbd0bdf06d7d61b0bef6de77b59ca31b2c32d.tar.gz
Make `Int`'s `mod` and `rem` strict in their first arguments
They used to be strict until 4d2ac2d (9 years ago). It's obviously better to be strict for performance reasons. It also blocks #18067. NoFib results: ``` -------------------------------------------------------------------------------- Program Allocs Instrs -------------------------------------------------------------------------------- integer -1.1% +0.4% wheel-sieve2 +21.2% +20.7% -------------------------------------------------------------------------------- Min -1.1% -0.0% Max +21.2% +20.7% Geometric Mean +0.2% +0.2% ``` The regression in `wheel-sieve2` is due to reboxing that likely will go away with the resolution of #18067. See !3282 for details. Fixes #18187.
-rw-r--r--libraries/base/GHC/Real.hs19
1 files changed, 11 insertions, 8 deletions
diff --git a/libraries/base/GHC/Real.hs b/libraries/base/GHC/Real.hs
index 38a3aa2870..1425f8c306 100644
--- a/libraries/base/GHC/Real.hs
+++ b/libraries/base/GHC/Real.hs
@@ -334,11 +334,8 @@ instance Integral Int where
-- in GHC.Int
| otherwise = a `quotInt` b
- a `rem` b
+ !a `rem` b -- See Note [Special case of mod and rem is lazy]
| b == 0 = divZeroError
- -- The quotRem CPU instruction fails for minBound `quotRem` -1,
- -- but minBound `rem` -1 is well-defined (0). We therefore
- -- special-case it.
| b == (-1) = 0
| otherwise = a `remInt` b
@@ -348,11 +345,8 @@ instance Integral Int where
-- in GHC.Int
| otherwise = a `divInt` b
- a `mod` b
+ !a `mod` b -- See Note [Special case of mod and rem is lazy]
| b == 0 = divZeroError
- -- The divMod CPU instruction fails for minBound `divMod` -1,
- -- but minBound `mod` -1 is well-defined (0). We therefore
- -- special-case it.
| b == (-1) = 0
| otherwise = a `modInt` b
@@ -368,6 +362,15 @@ instance Integral Int where
| b == (-1) && a == minBound = (overflowError, 0)
| otherwise = a `divModInt` b
+{- Note [Special case of mod and rem is lazy]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The `quotRem`/`divMod` CPU instruction fails for minBound `quotRem` -1, but
+minBound `rem` -1 is well-defined (0). We therefore special-case for `b == -1`,
+but not for `a == minBound` because of Note [Order of tests] in GHC.Int. But
+now we have to make sure the function stays strict in a, to guarantee unboxing.
+Hence the bang on a, see #18187.
+-}
+
--------------------------------------------------------------
-- Instances for @Word@
--------------------------------------------------------------