From a95bbd0bdf06d7d61b0bef6de77b59ca31b2c32d Mon Sep 17 00:00:00 2001
From: Sebastian Graf <sebastian.graf@kit.edu>
Date: Thu, 14 May 2020 14:40:41 +0200
Subject: [PATCH] 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.
---
 libraries/base/GHC/Real.hs | 19 +++++++++++--------
 1 file changed, 11 insertions(+), 8 deletions(-)

diff --git a/libraries/base/GHC/Real.hs b/libraries/base/GHC/Real.hs
index 38a3aa2870d..1425f8c306e 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@
 --------------------------------------------------------------
-- 
GitLab