[Git][ghc/ghc][wip/T18765] s/NOINLINE/NOINLINE[0]/g in GHC.Num.Integer (#18765)

Sebastian Graf gitlab at gitlab.haskell.org
Fri Oct 2 13:54:02 UTC 2020



Sebastian Graf pushed to branch wip/T18765 at Glasgow Haskell Compiler / GHC


Commits:
5cfe4d6b by Sebastian Graf at 2020-10-02T11:53:51+02:00
s/NOINLINE/NOINLINE[0]/g in GHC.Num.Integer (#18765)

This defeats constant-folding in the final phases of the Simplifier, but
enables us to get rid of allocations by inlining calls that can't be
constant-folded.

`NOINLINE[0]` is a better choice than `NOINLINE`, because

  1. We still delay inlining long enough for the constant-folding RULEs
     to fire
  2. The compiler has the option to inlining them late, possibly
     cancelling away boxes in the process.

`NOINLINE[0]` is a better choice than `INLINE[0]`, because

  3. We don't unconditionally inline huge definitions such as
     `integerDiv`, which would lead to code bloat at pretty much no
     gain.
  4. Since RULEs are unlikely to fire on the inlined RHS of e.g.
     `integerDiv`, there is no gain in inlining the unoptimised
     unfoldings.

We also have to mark all callers that want to participate in constant
folding as `INLINE`. See the new `Note [Integer constant folding]` for
details.

I had to change the `Num.fromInteger` and `Integral.toInteger`
implementations of `Int*` and `Word*` variants to call the constant
folded `integerToInt*#` and `integerToWord*#` variants directly to
ensure constant folding.

Fixes #18765.

Metric Decrease:
    T10359

- - - - -


9 changed files:

- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- libraries/base/GHC/Float.hs
- libraries/base/GHC/Int.hs
- libraries/base/GHC/Integer.hs
- libraries/base/GHC/Num.hs
- libraries/base/GHC/Real.hs
- libraries/base/GHC/Word.hs
- libraries/ghc-bignum/src/GHC/Num/Integer.hs


Changes:

=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -354,6 +354,7 @@ basicKnownKeyNames
         integerToWord64Name,
         integerToInt64Name,
         integerFromWordName,
+        integerFromIntName,
         integerFromWord64Name,
         integerFromInt64Name,
         integerAddName,
@@ -1129,6 +1130,7 @@ integerFromNaturalName
    , integerToWord64Name
    , integerToInt64Name
    , integerFromWordName
+   , integerFromIntName
    , integerFromWord64Name
    , integerFromInt64Name
    , integerAddName
@@ -1197,6 +1199,7 @@ integerToIntName          = bniVarQual "integerToInt#"             integerToIntI
 integerToWord64Name       = bniVarQual "integerToWord64#"          integerToWord64IdKey
 integerToInt64Name        = bniVarQual "integerToInt64#"           integerToInt64IdKey
 integerFromWordName       = bniVarQual "integerFromWord#"          integerFromWordIdKey
+integerFromIntName        = bniVarQual "integerFromInt#"           integerFromIntIdKey
 integerFromWord64Name     = bniVarQual "integerFromWord64#"        integerFromWord64IdKey
 integerFromInt64Name      = bniVarQual "integerFromInt64#"         integerFromInt64IdKey
 integerAddName            = bniVarQual "integerAdd"                integerAddIdKey
@@ -2463,6 +2466,7 @@ integerFromNaturalIdKey
    , integerShiftLIdKey
    , integerShiftRIdKey
    , integerFromWordIdKey
+   , integerFromIntIdKey
    , integerFromWord64IdKey
    , integerFromInt64IdKey
    , integerDecodeDoubleIdKey
@@ -2518,6 +2522,7 @@ integerFromWordIdKey       = mkPreludeMiscIdUnique 638
 integerFromWord64IdKey     = mkPreludeMiscIdUnique 639
 integerFromInt64IdKey      = mkPreludeMiscIdUnique 640
 integerDecodeDoubleIdKey   = mkPreludeMiscIdUnique 641
+integerFromIntIdKey        = mkPreludeMiscIdUnique 642
 
 naturalToWordIdKey         = mkPreludeMiscIdUnique 650
 naturalAddIdKey            = mkPreludeMiscIdUnique 651


=====================================
compiler/GHC/Core/Opt/ConstantFold.hs
=====================================
@@ -1312,7 +1312,8 @@ builtinRules enableBignumRules
 builtinBignumRules :: EnableBignumRules -> [CoreRule]
 builtinBignumRules (EnableBignumRules False) = []
 builtinBignumRules _ =
-      [ rule_IntegerFromLitNum  "Word# -> Integer"    integerFromWordName
+      [ rule_IntegerFromLitNum  "Int# -> Integer"     integerFromIntName
+      , rule_IntegerFromLitNum  "Word# -> Integer"    integerFromWordName
       , rule_IntegerFromLitNum  "Int64# -> Integer"   integerFromInt64Name
       , rule_IntegerFromLitNum  "Word64# -> Integer"  integerFromWord64Name
       , rule_IntegerFromLitNum  "Natural -> Integer"  integerFromNaturalName
@@ -1347,7 +1348,7 @@ builtinBignumRules _ =
       , rule_shift_op           "integerShiftL"       integerShiftLName       shiftL
       , rule_shift_op           "integerShiftR"       integerShiftRName       shiftR
       , rule_integerBit         "integerBit"          integerBitName
-        -- See Note [Integer division constant folding] in libraries/base/GHC/Real.hs
+        -- See Note [Integer constant folding] in "GHC.Num.Integer"
       , rule_divop_one          "integerQuot"         integerQuotName         quot
       , rule_divop_one          "integerRem"          integerRemName          rem
       , rule_divop_one          "integerDiv"          integerDivName          div


=====================================
libraries/base/GHC/Float.hs
=====================================
@@ -494,6 +494,7 @@ instance  Num Double  where
 
 -- | @since 2.01
 instance  Real Double  where
+    {-# INLINE toRational #-} -- See Note [Integer constant folding]
     toRational (D# x#)  =
         case integerDecodeDouble# x# of
           (# m, e# #)
@@ -580,11 +581,7 @@ instance  Floating Double  where
 -- | @since 2.01
 instance  RealFrac Double  where
 
-        -- ceiling, floor, and truncate are all small
-    {-# INLINE [1] ceiling #-}
-    {-# INLINE [1] floor #-}
-    {-# INLINE [1] truncate #-}
-
+    {-# INLINE properFraction #-} -- See Note [Integer constant folding]
     properFraction x
       = case (decodeFloat x)      of { (m,n) ->
         if n >= 0 then
@@ -595,9 +592,11 @@ instance  RealFrac Double  where
             }
         }
 
+    {-# INLINE truncate #-} -- See Note [Integer constant folding]
     truncate x  = case properFraction x of
                      (n,_) -> n
 
+    {-# INLINE round #-} -- See Note [Integer constant folding]
     round x     = case properFraction x of
                      (n,r) -> let
                                 m         = if r < 0.0 then n - 1 else n + 1
@@ -608,9 +607,11 @@ instance  RealFrac Double  where
                                 EQ -> if even n then n else m
                                 GT -> m
 
+    {-# INLINE ceiling #-} -- See Note [Integer constant folding]
     ceiling x   = case properFraction x of
                     (n,r) -> if r > 0.0 then n + 1 else n
 
+    {-# INLINE floor #-} -- See Note [Integer constant folding]
     floor x     = case properFraction x of
                     (n,r) -> if r < 0.0 then n - 1 else n
 
@@ -620,18 +621,23 @@ instance  RealFloat Double  where
     floatDigits _       =  DBL_MANT_DIG     -- ditto
     floatRange _        =  (DBL_MIN_EXP, DBL_MAX_EXP) -- ditto
 
+    {-# INLINE decodeFloat #-} -- See Note [Integer constant folding]
     decodeFloat (D# x#)
       = case integerDecodeDouble# x#   of
           (# i, j #) -> (i, I# j)
 
+    {-# INLINE encodeFloat #-} -- See Note [Integer constant folding]
     encodeFloat i (I# j) = D# (integerEncodeDouble# i j)
 
+    {-# INLINE exponent #-} -- See Note [Integer constant folding]
     exponent x          = case decodeFloat x of
                             (m,n) -> if m == 0 then 0 else n + floatDigits x
 
+    {-# INLINE significand #-} -- See Note [Integer constant folding]
     significand x       = case decodeFloat x of
                             (m,_) -> encodeFloat m (negate (floatDigits x))
 
+    {-# INLINE scaleFloat #-} -- See Note [Integer constant folding]
     scaleFloat 0 x      = x
     scaleFloat k x
       | isFix           = x


=====================================
libraries/base/GHC/Int.hs
=====================================
@@ -106,6 +106,7 @@ instance Num Int8 where
     signum x | x > 0       = 1
     signum 0               = 0
     signum _               = -1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = I8# (narrow8Int# (integerToInt# i))
 
 -- | @since 2.01
@@ -160,7 +161,8 @@ instance Integral Int8 where
                                        (# d, m #) ->
                                            (I8# (narrow8Int# d),
                                             I8# (narrow8Int# m))
-    toInteger (I8# x#)               = IS x#
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (I8# x)                = integerFromInt# x
 
 -- | @since 2.01
 instance Bounded Int8 where
@@ -313,6 +315,7 @@ instance Num Int16 where
     signum x | x > 0       = 1
     signum 0               = 0
     signum _               = -1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = I16# (narrow16Int# (integerToInt# i))
 
 -- | @since 2.01
@@ -367,7 +370,8 @@ instance Integral Int16 where
                                        (# d, m #) ->
                                            (I16# (narrow16Int# d),
                                             I16# (narrow16Int# m))
-    toInteger (I16# x#)              = IS x#
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (I16# x)               = integerFromInt# x
 
 -- | @since 2.01
 instance Bounded Int16 where
@@ -525,6 +529,7 @@ instance Num Int32 where
     signum x | x > 0       = 1
     signum 0               = 0
     signum _               = -1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = I32# (narrow32Int# (integerToInt# i))
 
 -- | @since 2.01
@@ -587,7 +592,8 @@ instance Integral Int32 where
                                        (# d, m #) ->
                                            (I32# (narrow32Int# d),
                                             I32# (narrow32Int# m))
-    toInteger (I32# x#)              = IS x#
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (I32# x)               = integerFromInt# x
 
 -- | @since 2.01
 instance Read Int32 where
@@ -748,6 +754,7 @@ instance Num Int64 where
     signum x | x > 0       = 1
     signum 0               = 0
     signum _               = -1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = I64# (integerToInt64# i)
 
 -- | @since 2.01
@@ -804,6 +811,7 @@ instance Integral Int64 where
         | y == (-1) && x == minBound = (overflowError, 0)
         | otherwise                  = (I64# (x# `divInt64#` y#),
                                         I64# (x# `modInt64#` y#))
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
     toInteger (I64# x)               = integerFromInt64# x
 
 
@@ -953,6 +961,7 @@ instance Num Int64 where
     signum x | x > 0       = 1
     signum 0               = 0
     signum _               = -1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = I64# (integerToInt# i)
 
 -- | @since 2.01
@@ -1006,7 +1015,8 @@ instance Integral Int64 where
         | otherwise                  = case x# `divModInt#` y# of
                                        (# d, m #) ->
                                            (I64# d, I64# m)
-    toInteger (I64# x#)              = IS x#
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (I64# x)               = integerFromInt64# x
 
 -- | @since 2.01
 instance Read Int64 where


=====================================
libraries/base/GHC/Integer.hs
=====================================
@@ -64,156 +64,203 @@ import GHC.Prim
 import GHC.Types
 
 smallInteger :: Int# -> Integer
+{-# INLINE smallInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 smallInteger = I.integerFromInt#
 
 integerToInt :: Integer -> Int#
+{-# INLINE integerToInt #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 integerToInt = I.integerToInt#
 
 wordToInteger :: Word# -> Integer
+{-# INLINE wordToInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 wordToInteger = I.integerFromWord#
 
 integerToWord :: Integer -> Word#
+{-# INLINE integerToWord #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 integerToWord = I.integerToWord#
 
 #if WORD_SIZE_IN_BITS < 64
 
 word64ToInteger :: Word64# -> Integer
+{-# INLINE word64ToInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 word64ToInteger = I.integerFromWord64#
 
 integerToWord64 :: Integer -> Word64#
+{-# INLINE integerToWord64 #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 integerToWord64 = I.integerToWord64#
 
 int64ToInteger :: Int64# -> Integer
+{-# INLINE int64ToInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 int64ToInteger = I.integerFromInt64#
 
 integerToInt64 :: Integer -> Int64#
+{-# INLINE integerToInt64 #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 integerToInt64 = I.integerToInt64#
 
 #endif
 
 
 encodeFloatInteger :: Integer -> Int# -> Float#
+{-# INLINE encodeFloatInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 encodeFloatInteger = I.integerEncodeFloat#
 
 floatFromInteger :: Integer -> Float#
+{-# INLINE floatFromInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 floatFromInteger = I.integerToFloat#
 
 encodeDoubleInteger :: Integer -> Int# -> Double#
+{-# INLINE encodeDoubleInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 encodeDoubleInteger = I.integerEncodeDouble#
 
 doubleFromInteger :: Integer -> Double#
+{-# INLINE doubleFromInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 doubleFromInteger = I.integerToDouble#
 
 decodeDoubleInteger :: Double# -> (# Integer, Int# #)
+{-# INLINE decodeDoubleInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 decodeDoubleInteger = I.integerDecodeDouble#
 
 
 plusInteger :: Integer -> Integer -> Integer
+{-# INLINE plusInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 plusInteger = I.integerAdd
 
 minusInteger :: Integer -> Integer -> Integer
+{-# INLINE minusInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 minusInteger = I.integerSub
 
 timesInteger :: Integer -> Integer -> Integer
+{-# INLINE timesInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 timesInteger = I.integerMul
 
 negateInteger :: Integer -> Integer
+{-# INLINE negateInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 negateInteger = I.integerNegate
 
 absInteger :: Integer -> Integer
+{-# INLINE absInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 absInteger = I.integerAbs
 
 signumInteger :: Integer -> Integer
+{-# INLINE signumInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 signumInteger = I.integerSignum
 
 divModInteger :: Integer -> Integer -> (# Integer, Integer #)
+{-# INLINE divModInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 divModInteger = I.integerDivMod#
 
 divInteger :: Integer -> Integer -> Integer
+{-# INLINE divInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 divInteger = I.integerDiv
 
 modInteger :: Integer -> Integer -> Integer
+{-# INLINE modInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 modInteger = I.integerMod
 
 quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)
+{-# INLINE quotRemInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 quotRemInteger = I.integerQuotRem#
 
 quotInteger :: Integer -> Integer -> Integer
+{-# INLINE quotInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 quotInteger = I.integerQuot
 
 remInteger :: Integer -> Integer -> Integer
+{-# INLINE remInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 remInteger = I.integerRem
 
 
 eqInteger :: Integer -> Integer -> Bool
+{-# INLINE eqInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 eqInteger = I.integerEq
 
 neqInteger :: Integer -> Integer -> Bool
+{-# INLINE neqInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 neqInteger = I.integerNe
 
 leInteger :: Integer -> Integer -> Bool
+{-# INLINE leInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 leInteger = I.integerLe
 
 gtInteger :: Integer -> Integer -> Bool
+{-# INLINE gtInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 gtInteger = I.integerGt
 
 ltInteger :: Integer -> Integer -> Bool
+{-# INLINE ltInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 ltInteger = I.integerLt
 
 geInteger :: Integer -> Integer -> Bool
+{-# INLINE geInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 geInteger = I.integerGe
 
 compareInteger :: Integer -> Integer -> Ordering
+{-# INLINE compareInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 compareInteger = I.integerCompare
 
 
 
 eqInteger# :: Integer -> Integer -> Int#
+{-# INLINE eqInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 eqInteger# = I.integerEq#
 
 neqInteger# :: Integer -> Integer -> Int#
+{-# INLINE neqInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 neqInteger# = I.integerNe#
 
 leInteger# :: Integer -> Integer -> Int#
+{-# INLINE leInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 leInteger# = I.integerLe#
 
 gtInteger# :: Integer -> Integer -> Int#
+{-# INLINE gtInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 gtInteger# = I.integerGt#
 
 ltInteger# :: Integer -> Integer -> Int#
+{-# INLINE ltInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 ltInteger# = I.integerLt#
 
 geInteger# :: Integer -> Integer -> Int#
+{-# INLINE geInteger# #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 geInteger# = I.integerGe#
 
 
 andInteger :: Integer -> Integer -> Integer
+{-# INLINE andInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 andInteger = I.integerAnd
 
 orInteger :: Integer -> Integer -> Integer
+{-# INLINE orInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 orInteger = I.integerOr
 
 xorInteger :: Integer -> Integer -> Integer
+{-# INLINE xorInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 xorInteger = I.integerXor
 
 complementInteger :: Integer -> Integer
+{-# INLINE complementInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 complementInteger = I.integerComplement
 
 shiftLInteger :: Integer -> Int# -> Integer
+{-# INLINE shiftLInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 shiftLInteger n i = I.integerShiftL# n (int2Word# i)
 
 shiftRInteger :: Integer -> Int# -> Integer
+{-# INLINE shiftRInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 shiftRInteger n i = I.integerShiftR# n (int2Word# i)
 
 testBitInteger :: Integer -> Int# -> Bool
+{-# INLINE testBitInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 testBitInteger n i = isTrue# (I.integerTestBit# n (int2Word# i))
 
 hashInteger :: Integer -> Int#
+{-# INLINE hashInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 hashInteger = I.integerToInt#
 
 bitInteger :: Int# -> Integer
+{-# INLINE bitInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 bitInteger i = I.integerBit# (int2Word# i)
 
 popCountInteger :: Integer -> Int#
+{-# INLINE popCountInteger #-} -- See Note [Integer constant folding] in GHC.Num.Integer
 popCountInteger = I.integerPopCount#
-


=====================================
libraries/base/GHC/Num.hs
=====================================
@@ -109,7 +109,7 @@ instance  Num Int  where
              | n `eqInt` 0 = 0
              | otherwise   = 1
 
-    {-# INLINE fromInteger #-}   -- Just to be sure!
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i = integerToInt i
 
 -- | @since 2.01
@@ -121,6 +121,7 @@ instance Num Word where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = integerToWord i
 
 -- | @since 2.01
@@ -150,6 +151,7 @@ instance  Num Natural  where
       | naturalIsZero x = x
       | otherwise       = raise# underflowException
 
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger x
       | x < 0     = raise# underflowException
       | otherwise = integerToNaturalClamp x
@@ -160,4 +162,3 @@ instance  Num Natural  where
 {-# DEPRECATED quotRemInteger "Use integerQuotRem# instead" #-}
 quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)
 quotRemInteger = integerQuotRem#
-


=====================================
libraries/base/GHC/Real.hs
=====================================
@@ -324,7 +324,8 @@ instance  Real Int  where
 
 -- | @since 2.0.1
 instance  Integral Int  where
-    toInteger (I# i) = IS i
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (I# x)              = integerFromInt# x
 
     a `quot` b
      | b == 0                     = divZeroError
@@ -399,6 +400,7 @@ instance Integral Word where
     divMod  (W# x#) y@(W# y#)
         | y /= 0                = (W# (x# `quotWord#` y#), W# (x# `remWord#` y#))
         | otherwise             = divZeroError
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
     toInteger (W# x#)           = integerFromWord# x#
 
 --------------------------------------------------------------
@@ -413,71 +415,60 @@ instance  Real Integer  where
 instance Real Natural where
     toRational n = integerFromNatural n :% 1
 
--- Note [Integer division constant folding]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
--- Constant folding of quot, rem, div, mod, divMod and quotRem for Integer
--- arguments depends crucially on inlining. Constant folding rules defined in
--- GHC.Core.Opt.ConstantFold trigger for integerQuot, integerRem and so on.
--- So if calls to quot, rem and so on were not inlined the rules would not fire.
---
--- The rules would also not fire if calls to integerQuot and so on were inlined,
--- but this does not happen because they are all marked with NOINLINE pragma.
-
-
 -- | @since 2.0.1
 instance  Integral Integer where
     toInteger n      = n
 
-    {-# INLINE quot #-}
+    {-# INLINE quot #-} -- See Note [Integer constant folding]
     _ `quot` 0 = divZeroError
     n `quot` d = n `integerQuot` d
 
-    {-# INLINE rem #-}
+    {-# INLINE rem #-} -- See Note [Integer constant folding]
     _ `rem` 0 = divZeroError
     n `rem` d = n `integerRem` d
 
-    {-# INLINE div #-}
+    {-# INLINE div #-} -- See Note [Integer constant folding]
     _ `div` 0 = divZeroError
     n `div` d = n `integerDiv` d
 
-    {-# INLINE mod #-}
+    {-# INLINE mod #-} -- See Note [Integer constant folding]
     _ `mod` 0 = divZeroError
     n `mod` d = n `integerMod` d
 
-    {-# INLINE divMod #-}
+    {-# INLINE divMod #-} -- See Note [Integer constant folding]
     _ `divMod` 0 = divZeroError
     n `divMod` d = n `integerDivMod` d
 
-    {-# INLINE quotRem #-}
+    {-# INLINE quotRem #-} -- See Note [Integer constant folding]
     _ `quotRem` 0 = divZeroError
     n `quotRem` d = n `integerQuotRem` d
 
 -- | @since 4.8.0.0
 instance Integral Natural where
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
     toInteger = integerFromNatural
 
-    {-# INLINE quot #-}
+    {-# INLINE quot #-} -- See Note [Integer constant folding]
     _ `quot` 0 = divZeroError
     n `quot` d = n `naturalQuot` d
 
-    {-# INLINE rem #-}
+    {-# INLINE rem #-} -- See Note [Integer constant folding]
     _ `rem` 0 = divZeroError
     n `rem` d = n `naturalRem` d
 
-    {-# INLINE div #-}
+    {-# INLINE div #-} -- See Note [Integer constant folding]
     _ `div` 0 = divZeroError
     n `div` d = n `naturalQuot` d
 
-    {-# INLINE mod #-}
+    {-# INLINE mod #-} -- See Note [Integer constant folding]
     _ `mod` 0 = divZeroError
     n `mod` d = n `naturalRem` d
 
-    {-# INLINE divMod #-}
+    {-# INLINE divMod #-} -- See Note [Integer constant folding]
     _ `divMod` 0 = divZeroError
     n `divMod` d = n `naturalQuotRem` d
 
-    {-# INLINE quotRem #-}
+    {-# INLINE quotRem #-} -- See Note [Integer constant folding]
     _ `quotRem` 0 = divZeroError
     n `quotRem` d = n `naturalQuotRem` d
 


=====================================
libraries/base/GHC/Word.hs
=====================================
@@ -112,6 +112,7 @@ instance Num Word8 where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = W8# (narrow8Word# (integerToWord# i))
 
 -- | @since 2.01
@@ -156,7 +157,8 @@ instance Integral Word8 where
     divMod  (W8# x#) y@(W8# y#)
         | y /= 0                  = (W8# (x# `quotWord#` y#), W8# (x# `remWord#` y#))
         | otherwise               = divZeroError
-    toInteger (W8# x#)            = IS (word2Int# x#)
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (W8# x#)            = integerFromWord# x#
 
 -- | @since 2.01
 instance Bounded Word8 where
@@ -303,6 +305,7 @@ instance Num Word16 where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = W16# (narrow16Word# (integerToWord# i))
 
 -- | @since 2.01
@@ -347,7 +350,8 @@ instance Integral Word16 where
     divMod  (W16# x#) y@(W16# y#)
         | y /= 0                    = (W16# (x# `quotWord#` y#), W16# (x# `remWord#` y#))
         | otherwise                 = divZeroError
-    toInteger (W16# x#)             = IS (word2Int# x#)
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (W16# x#)             = integerFromWord# x#
 
 -- | @since 2.01
 instance Bounded Word16 where
@@ -533,6 +537,7 @@ instance Num Word32 where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = W32# (narrow32Word# (integerToWord# i))
 
 -- | @since 2.01
@@ -587,15 +592,8 @@ instance Integral Word32 where
     divMod  (W32# x#) y@(W32# y#)
         | y /= 0                    = (W32# (x# `quotWord#` y#), W32# (x# `remWord#` y#))
         | otherwise                 = divZeroError
-    toInteger (W32# x#)
-#if WORD_SIZE_IN_BITS == 32
-        | isTrue# (i# >=# 0#)       = IS i#
-        | otherwise                 = integerFromWord# x#
-        where
-        !i# = word2Int# x#
-#else
-                                    = IS (word2Int# x#)
-#endif
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (W32# x#)             = integerFromWord# x#
 
 -- | @since 2.01
 instance Bits Word32 where
@@ -728,6 +726,7 @@ instance Num Word64 where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = W64# (integerToWord64# i)
 
 -- | @since 2.01
@@ -770,6 +769,7 @@ instance Integral Word64 where
     divMod  (W64# x#) y@(W64# y#)
         | y /= 0                    = (W64# (x# `quotWord64#` y#), W64# (x# `remWord64#` y#))
         | otherwise                 = divZeroError
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
     toInteger (W64# x#)             = integerFromWord64# x#
 
 -- | @since 2.01
@@ -875,6 +875,7 @@ instance Num Word64 where
     abs x                  = x
     signum 0               = 0
     signum _               = 1
+    {-# INLINE fromInteger #-} -- See Note [Integer constant folding]
     fromInteger i          = W64# (integerToWord# i)
 
 -- | @since 2.01
@@ -953,11 +954,8 @@ instance Integral Word64 where
     divMod  (W64# x#) y@(W64# y#)
         | y /= 0                    = (W64# (x# `quotWord#` y#), W64# (x# `remWord#` y#))
         | otherwise                 = divZeroError
-    toInteger (W64# x#)
-        | isTrue# (i# >=# 0#)       = IS i#
-        | otherwise                 = integerFromWord# x#
-        where
-        !i# = word2Int# x#
+    {-# INLINE toInteger #-} -- See Note [Integer constant folding]
+    toInteger (W64# x#)             = integerFromWord# x#
 
 -- | @since 2.01
 instance Bits Word64 where


=====================================
libraries/ghc-bignum/src/GHC/Num/Integer.hs
=====================================
@@ -1,3 +1,5 @@
+{-# OPTIONS_GHC -fno-spec-constr #-} -- See Note [Integer constant folding],
+                                     -- the bit about `integerAdd`
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE BangPatterns #-}
@@ -66,6 +68,7 @@ integerCheck# (IN bn) = bigNatCheck# bn &&# (bn `bigNatGtWord#` ABS_INT_MINBOUND
 
 -- | Check Integer invariants
 integerCheck :: Integer -> Bool
+{-# INLINE integerCheck #-}
 integerCheck i = isTrue# (integerCheck# i)
 
 -- | Integer Zero
@@ -137,26 +140,29 @@ integerToBigNatClamp# _     = bigNatZero# (# #)
 
 -- | Create an Integer from an Int#
 integerFromInt# :: Int# -> Integer
+{-# NOINLINE[0] integerFromInt# #-} -- See Note [Integer constant folding]
 integerFromInt# i = IS i
 
 -- | Create an Integer from an Int
 integerFromInt :: Int -> Integer
-integerFromInt (I# i) = IS i
+{-# INLINE integerFromInt #-} -- See Note [Integer constant folding]
+integerFromInt (I# i) = integerFromInt# i
 
 -- | Truncates 'Integer' to least-significant 'Int#'
 integerToInt# :: Integer -> Int#
-{-# NOINLINE integerToInt# #-}
+{-# NOINLINE[0] integerToInt# #-} -- See Note [Integer constant folding]
 integerToInt# (IS i) = i
 integerToInt# (IP b) = word2Int# (bigNatToWord# b)
 integerToInt# (IN b) = negateInt# (word2Int# (bigNatToWord# b))
 
 -- | Truncates 'Integer' to least-significant 'Int#'
 integerToInt :: Integer -> Int
+{-# INLINE integerToInt #-} -- See Note [Integer constant folding]
 integerToInt i = I# (integerToInt# i)
 
 -- | Convert a Word# into an Integer
 integerFromWord# :: Word# -> Integer
-{-# NOINLINE integerFromWord# #-}
+{-# NOINLINE[0] integerFromWord# #-} -- See Note [Integer constant folding]
 integerFromWord# w
    | i <- word2Int# w
    , isTrue# (i >=# 0#)
@@ -167,6 +173,7 @@ integerFromWord# w
 
 -- | Convert a Word into an Integer
 integerFromWord :: Word -> Integer
+{-# INLINE integerFromWord #-} -- See Note [Integer constant folding]
 integerFromWord (W# w) = integerFromWord# w
 
 -- | Create a negative Integer with the given Word magnitude
@@ -185,23 +192,25 @@ integerFromWordSign# _  w = integerFromWordNeg# w
 
 -- | Truncate an Integer into a Word
 integerToWord# :: Integer -> Word#
-{-# NOINLINE integerToWord# #-}
+{-# NOINLINE[0] integerToWord# #-} -- See Note [Integer constant folding]
 integerToWord# (IS i)  = int2Word# i
 integerToWord# (IP bn) = bigNatToWord# bn
 integerToWord# (IN bn) = int2Word# (negateInt# (word2Int# (bigNatToWord# bn)))
 
 -- | Truncate an Integer into a Word
 integerToWord :: Integer -> Word
+{-# INLINE integerToWord #-} -- See Note [Integer constant folding]
 integerToWord !i = W# (integerToWord# i)
 
 -- | Convert a Natural into an Integer
 integerFromNatural :: Natural -> Integer
-{-# NOINLINE integerFromNatural #-}
+{-# NOINLINE[0] integerFromNatural #-} -- See Note [Integer constant folding]
 integerFromNatural (NS x) = integerFromWord# x
 integerFromNatural (NB x) = integerFromBigNat# x
 
 -- | Convert a list of Word into an Integer
 integerFromWordList :: Bool -> [Word] -> Integer
+{-# INLINE integerFromWordList #-} -- See Note [Integer constant folding]
 integerFromWordList True  ws = integerFromBigNatNeg# (bigNatFromWordList ws)
 integerFromWordList False ws = integerFromBigNat#    (bigNatFromWordList ws)
 
@@ -209,7 +218,7 @@ integerFromWordList False ws = integerFromBigNat#    (bigNatFromWordList ws)
 --
 -- Return 0 for negative Integers.
 integerToNaturalClamp :: Integer -> Natural
-{-# NOINLINE integerToNaturalClamp #-}
+{-# NOINLINE[0] integerToNaturalClamp #-} -- See Note [Integer constant folding]
 integerToNaturalClamp (IS x)
    | isTrue# (x <# 0#) = naturalZero
    | True              = naturalFromWord# (int2Word# x)
@@ -220,7 +229,7 @@ integerToNaturalClamp (IN _) = naturalZero
 --
 -- Return absolute value
 integerToNatural :: Integer -> Natural
-{-# NOINLINE integerToNatural #-}
+{-# NOINLINE[0] integerToNatural #-} -- See Note [Integer constant folding]
 integerToNatural (IS x) = naturalFromWord# (wordFromAbsInt# x)
 integerToNatural (IP x) = naturalFromBigNat# x
 integerToNatural (IN x) = naturalFromBigNat# x
@@ -237,40 +246,50 @@ integerIsNegative# (IN _)  = 1#
 
 -- | Negative predicate
 integerIsNegative :: Integer -> Bool
+{-# INLINE integerIsNegative #-} -- See Note [Integer constant folding]
 integerIsNegative !i = isTrue# (integerIsNegative# i)
 
 -- | Zero predicate
 integerIsZero :: Integer -> Bool
+{-# INLINE integerIsZero #-} -- See Note [Integer constant folding]
 integerIsZero (IS 0#) = True
 integerIsZero _       = False
 
 -- | Not-equal predicate.
 integerNe :: Integer -> Integer -> Bool
+{-# INLINE integerNe #-} -- See Note [Integer constant folding]
 integerNe !x !y = isTrue# (integerNe# x y)
 
 -- | Equal predicate.
 integerEq :: Integer -> Integer -> Bool
+{-# INLINE integerEq #-} -- See Note [Integer constant folding]
 integerEq !x !y = isTrue# (integerEq# x y)
 
 -- | Lower-or-equal predicate.
 integerLe :: Integer -> Integer -> Bool
+{-# INLINE integerLe #-} -- See Note [Integer constant folding]
 integerLe !x !y = isTrue# (integerLe# x y)
 
 -- | Lower predicate.
 integerLt :: Integer -> Integer -> Bool
+{-# INLINE integerLt #-} -- See Note [Integer constant folding]
 integerLt !x !y = isTrue# (integerLt# x y)
 
 -- | Greater predicate.
 integerGt :: Integer -> Integer -> Bool
+{-# INLINE integerGt #-} -- See Note [Integer constant folding]
 integerGt !x !y = isTrue# (integerGt# x y)
 
 -- | Greater-or-equal predicate.
 integerGe :: Integer -> Integer -> Bool
+{-# INLINE integerGe #-} -- See Note [Integer constant folding]
 integerGe !x !y = isTrue# (integerGe# x y)
 
 -- | Equal predicate.
 integerEq# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerEq# #-}
+{-# NOINLINE integerEq# #-} -- See Note [Integer constant folding]
+                            -- But this function will be too huge if inlined
+                            -- at all. Hence NOINLINE, without [0]
 integerEq# (IS x) (IS y) = x ==# y
 integerEq# (IN x) (IN y) = bigNatEq# x y
 integerEq# (IP x) (IP y) = bigNatEq# x y
@@ -278,7 +297,9 @@ integerEq# _       _     = 0#
 
 -- | Not-equal predicate.
 integerNe# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerNe# #-}
+{-# NOINLINE integerNe# #-} -- See Note [Integer constant folding]
+                            -- But this function will be too huge if inlined
+                            -- at all. Hence NOINLINE, without [0]
 integerNe# (IS x) (IS y) = x /=# y
 integerNe# (IN x) (IN y) = bigNatNe# x y
 integerNe# (IP x) (IP y) = bigNatNe# x y
@@ -286,39 +307,43 @@ integerNe# _       _     = 1#
 
 -- | Greater predicate.
 integerGt# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerGt# #-}
+{-# NOINLINE[0] integerGt# #-} -- See Note [Integer constant folding]
 integerGt# (IS x) (IS y)                  = x ># y
 integerGt# x y | GT <- integerCompare x y = 1#
 integerGt# _ _                            = 0#
 
 -- | Lower-or-equal predicate.
 integerLe# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerLe# #-}
+{-# NOINLINE[0] integerLe# #-} -- See Note [Integer constant folding]
 integerLe# (IS x) (IS y)                  = x <=# y
 integerLe# x y | GT <- integerCompare x y = 0#
 integerLe# _ _                            = 1#
 
 -- | Lower predicate.
 integerLt# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerLt# #-}
+{-# NOINLINE[0] integerLt# #-} -- See Note [Integer constant folding]
 integerLt# (IS x) (IS y)                  = x <# y
 integerLt# x y | LT <- integerCompare x y = 1#
 integerLt# _ _                            = 0#
 
 -- | Greater-or-equal predicate.
 integerGe# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerGe# #-}
+{-# NOINLINE[0] integerGe# #-} -- See Note [Integer constant folding]
 integerGe# (IS x) (IS y)                  = x >=# y
 integerGe# x y | LT <- integerCompare x y = 0#
 integerGe# _ _                            = 1#
 
 instance Eq Integer where
+   {-# INLINE (==) #-} -- See Note [Integer constant folding]
    (==) = integerEq
+   {-# INLINE (/=) #-} -- See Note [Integer constant folding]
    (/=) = integerNe
 
 -- | Compare two Integer
 integerCompare :: Integer -> Integer -> Ordering
-{-# NOINLINE integerCompare #-}
+{-# NOINLINE integerCompare #-} -- See Note [Integer constant folding]
+                                -- But this function will be too huge if inlined
+                                -- at all. Hence NOINLINE, without [0]
 integerCompare (IS x) (IS y) = compareInt# x y
 integerCompare (IP x) (IP y) = bigNatCompare x y
 integerCompare (IN x) (IN y) = bigNatCompare y x
@@ -330,6 +355,7 @@ integerCompare (IP _) (IN _) = GT
 integerCompare (IN _) (IP _) = LT
 
 instance Ord Integer where
+   {-# INLINE compare #-} -- See Note [Integer constant folding]
    compare = integerCompare
 
 ---------------------------------------------------------------------
@@ -338,7 +364,7 @@ instance Ord Integer where
 
 -- | Subtract one 'Integer' from another.
 integerSub :: Integer -> Integer -> Integer
-{-# NOINLINE integerSub #-}
+{-# NOINLINE[0] integerSub #-} -- See Note [Integer constant folding]
 integerSub !x      (IS 0#) = x
 integerSub (IS x#) (IS y#)
   = case subIntC# x# y# of
@@ -384,7 +410,7 @@ integerSub (IN x) (IS y#)
 
 -- | Add two 'Integer's
 integerAdd :: Integer -> Integer -> Integer
-{-# NOINLINE integerAdd #-}
+{-# NOINLINE[0] integerAdd #-} -- See Note [Integer constant folding]
 integerAdd !x      (IS 0#) = x
 integerAdd (IS 0#) y       = y
 integerAdd (IS x#) (IS y#)
@@ -413,7 +439,7 @@ integerAdd (IP x) (IN y)
 
 -- | Multiply two 'Integer's
 integerMul :: Integer -> Integer -> Integer
-{-# NOINLINE integerMul #-}
+{-# NOINLINE[0] integerMul #-} -- See Note [Integer constant folding]
 integerMul !_       (IS 0#)  = IS 0#
 integerMul (IS 0#)  _        = IS 0#
 integerMul x        (IS 1#)  = x
@@ -478,7 +504,7 @@ integerMul (IN x) (IS y)
 -- IP is used iff n > maxBound::Int
 -- IN is used iff n < minBound::Int
 integerNegate :: Integer -> Integer
-{-# NOINLINE integerNegate #-}
+{-# NOINLINE[0] integerNegate #-} -- See Note [Integer constant folding]
 integerNegate (IN b)             = IP b
 integerNegate (IS INT_MINBOUND#) = IP (bigNatFromWord# ABS_INT_MINBOUND##)
 integerNegate (IS i)             = IS (negateInt# i)
@@ -492,7 +518,7 @@ integerNegate (IP b)
 
 -- | Compute absolute value of an 'Integer'
 integerAbs :: Integer -> Integer
-{-# NOINLINE integerAbs #-}
+{-# NOINLINE[0] integerAbs #-} -- See Note [Integer constant folding]
 integerAbs   (IN i)     = IP i
 integerAbs n@(IP _)     = n
 integerAbs n@(IS i)
@@ -504,13 +530,13 @@ integerAbs n@(IS i)
 -- | Return @-1@, @0@, and @1@ depending on whether argument is
 -- negative, zero, or positive, respectively
 integerSignum :: Integer -> Integer
-{-# NOINLINE integerSignum #-}
+{-# NOINLINE[0] integerSignum #-} -- See Note [Integer constant folding]
 integerSignum !j = IS (integerSignum# j)
 
 -- | Return @-1#@, @0#@, and @1#@ depending on whether argument is
 -- negative, zero, or positive, respectively
 integerSignum# :: Integer -> Int#
-{-# NOINLINE integerSignum# #-}
+{-# NOINLINE[0] integerSignum# #-} -- See Note [Integer constant folding]
 integerSignum# (IN _)  = -1#
 integerSignum# (IS i#) = sgnI# i#
 integerSignum# (IP _ ) =  1#
@@ -518,7 +544,7 @@ integerSignum# (IP _ ) =  1#
 -- | Count number of set bits. For negative arguments returns
 -- the negated population count of the absolute value.
 integerPopCount# :: Integer -> Int#
-{-# NOINLINE integerPopCount# #-}
+{-# NOINLINE[0] integerPopCount# #-} -- See Note [Integer constant folding]
 integerPopCount# (IS i)
    | isTrue# (i >=# 0#)  = word2Int# (popCntI# i)
    | True                = negateInt# (word2Int# (popCntI# (negateInt# i)))
@@ -527,7 +553,7 @@ integerPopCount# (IN bn) = negateInt# (word2Int# (bigNatPopCount# bn))
 
 -- | Positive 'Integer' for which only /n/-th bit is set
 integerBit# :: Word# -> Integer
-{-# NOINLINE integerBit# #-}
+{-# NOINLINE[0] integerBit# #-} -- See Note [Integer constant folding]
 integerBit# i
   | isTrue# (i `ltWord#` (WORD_SIZE_IN_BITS## `minusWord#` 1##))
   = IS (uncheckedIShiftL# 1# (word2Int# i))
@@ -536,13 +562,14 @@ integerBit# i
 
 -- | 'Integer' for which only /n/-th bit is set
 integerBit :: Word -> Integer
+{-# INLINE integerBit #-} -- See Note [Integer constant folding]
 integerBit (W# i) = integerBit# i
 
 -- | Test if /n/-th bit is set.
 --
 -- Fake 2's complement for negative values (might be slow)
 integerTestBit# :: Integer -> Word# -> Bool#
-{-# NOINLINE integerTestBit# #-}
+{-# NOINLINE[0] integerTestBit# #-} -- See Note [Integer constant folding]
 integerTestBit# (IS x) i
    | isTrue# (i `ltWord#` WORD_SIZE_IN_BITS##)
    = testBitI# x i
@@ -572,13 +599,14 @@ integerTestBit# (IN x) i
 --
 -- Fake 2's complement for negative values (might be slow)
 integerTestBit :: Integer -> Word -> Bool
+{-# INLINE integerTestBit #-} -- See Note [Integer constant folding]
 integerTestBit !i (W# n) = isTrue# (integerTestBit# i n)
 
 -- | Shift-right operation
 --
 -- Fake 2's complement for negative values (might be slow)
 integerShiftR# :: Integer -> Word# -> Integer
-{-# NOINLINE integerShiftR# #-}
+{-# NOINLINE[0] integerShiftR# #-} -- See Note [Integer constant folding]
 integerShiftR# !x      0## = x
 integerShiftR# (IS i)  n   = IS (iShiftRA# i (word2Int# n))
   where
@@ -595,11 +623,12 @@ integerShiftR# (IN bn) n   =
 --
 -- Fake 2's complement for negative values (might be slow)
 integerShiftR :: Integer -> Word -> Integer
+{-# INLINE integerShiftR #-} -- See Note [Integer constant folding]
 integerShiftR !x (W# w) = integerShiftR# x w
 
 -- | Shift-left operation
 integerShiftL# :: Integer -> Word# -> Integer
-{-# NOINLINE integerShiftL# #-}
+{-# NOINLINE[0] integerShiftL# #-} -- See Note [Integer constant folding]
 integerShiftL# !x      0## = x
 integerShiftL# (IS 0#) _   = IS 0#
 integerShiftL# (IS 1#) n   = integerBit# n
@@ -614,13 +643,14 @@ integerShiftL# (IN bn) n   = IN (bigNatShiftL# bn n)
 -- Remember that bits are stored in sign-magnitude form, hence the behavior of
 -- negative Integers is different from negative Int's behavior.
 integerShiftL :: Integer -> Word -> Integer
+{-# INLINE integerShiftL #-} -- See Note [Integer constant folding]
 integerShiftL !x (W# w) = integerShiftL# x w
 
 -- | Bitwise OR operation
 --
 -- Fake 2's complement for negative values (might be slow)
 integerOr :: Integer -> Integer -> Integer
-{-# NOINLINE integerOr #-}
+{-# NOINLINE[0] integerOr #-} -- See Note [Integer constant folding]
 integerOr a b = case a of
    IS  0# -> b
    IS -1# -> IS -1#
@@ -679,7 +709,7 @@ integerOr a b = case a of
 --
 -- Fake 2's complement for negative values (might be slow)
 integerXor :: Integer -> Integer -> Integer
-{-# NOINLINE integerXor #-}
+{-# NOINLINE[0] integerXor #-} -- See Note [Integer constant folding]
 integerXor a b = case a of
    IS  0# -> b
    IS -1# -> integerComplement b
@@ -734,7 +764,7 @@ integerXor a b = case a of
 --
 -- Fake 2's complement for negative values (might be slow)
 integerAnd :: Integer -> Integer -> Integer
-{-# NOINLINE integerAnd #-}
+{-# NOINLINE[0] integerAnd #-} -- See Note [Integer constant folding]
 integerAnd a b = case a of
    IS 0#  -> IS 0#
    IS -1# -> b
@@ -769,7 +799,7 @@ integerAnd a b = case a of
 
 -- | Binary complement of the
 integerComplement :: Integer -> Integer
-{-# NOINLINE integerComplement #-}
+{-# NOINLINE[0] integerComplement #-} -- See Note [Integer constant folding]
 integerComplement (IS x) = IS (notI# x)
 integerComplement (IP x) = IN (bigNatAddWord# x 1##)
 integerComplement (IN x) = IP (bigNatSubWordUnsafe# x 1##)
@@ -780,7 +810,7 @@ integerComplement (IN x) = IP (bigNatSubWordUnsafe# x 1##)
 -- Divisor must be non-zero otherwise the GHC runtime will terminate
 -- with a division-by-zero fault.
 integerQuotRem# :: Integer -> Integer -> (# Integer, Integer #)
-{-# NOINLINE integerQuotRem# #-}
+{-# NOINLINE[0] integerQuotRem# #-} -- See Note [Integer constant folding]
 integerQuotRem# !n      (IS 1#) = (# n, IS 0# #)
 integerQuotRem# !n     (IS -1#) = let !q = integerNegate n in (# q, (IS 0#) #)
 integerQuotRem# !_      (IS 0#) = case raiseDivZero of
@@ -818,12 +848,13 @@ integerQuotRem# n@(IS n#) (IP d) -- need to account for (IS minBound)
 -- Divisor must be non-zero otherwise the GHC runtime will terminate
 -- with a division-by-zero fault.
 integerQuotRem :: Integer -> Integer -> (Integer, Integer)
+{-# INLINE integerQuotRem #-} -- See Note [Integer constant folding]
 integerQuotRem !x !y = case integerQuotRem# x y of
    (# q, r #) -> (q, r)
 
 
 integerQuot :: Integer -> Integer -> Integer
-{-# NOINLINE integerQuot #-}
+{-# NOINLINE[0] integerQuot #-} -- See Note [Integer constant folding]
 integerQuot !n      (IS 1#)  = n
 integerQuot !n      (IS -1#) = integerNegate n
 integerQuot !_      (IS 0#)  = raiseDivZero
@@ -844,7 +875,7 @@ integerQuot (IN n) (IN d) = integerFromBigNat#    (bigNatQuot n d)
 integerQuot n d = case integerQuotRem# n d of (# q, _ #) -> q
 
 integerRem :: Integer -> Integer -> Integer
-{-# NOINLINE integerRem #-}
+{-# NOINLINE[0] integerRem #-} -- See Note [Integer constant folding]
 integerRem !_       (IS 1#) = IS 0#
 integerRem _       (IS -1#) = IS 0#
 integerRem _        (IS 0#) = IS (remInt# 0# 0#)
@@ -866,7 +897,7 @@ integerRem n d = case integerQuotRem# n d of (# _, r #) -> r
 -- Divisor must be non-zero otherwise the GHC runtime will terminate
 -- with a division-by-zero fault.
 integerDivMod# :: Integer -> Integer -> (# Integer, Integer #)
-{-# NOINLINE integerDivMod# #-}
+{-# NOINLINE[0] integerDivMod# #-} -- See Note [Integer constant folding]
 integerDivMod# !n !d
   | isTrue# (integerSignum# r ==# negateInt# (integerSignum# d))
      = let !q' = integerSub q (IS 1#)
@@ -881,12 +912,13 @@ integerDivMod# !n !d
 -- Divisor must be non-zero otherwise the GHC runtime will terminate
 -- with a division-by-zero fault.
 integerDivMod :: Integer -> Integer -> (Integer, Integer)
+{-# INLINE integerDivMod #-} -- See Note [Integer constant folding]
 integerDivMod !n !d = case integerDivMod# n d of
    (# q,r #) -> (q,r)
 
 
 integerDiv :: Integer -> Integer -> Integer
-{-# NOINLINE integerDiv #-}
+{-# NOINLINE[0] integerDiv #-} -- See Note [Integer constant folding]
 integerDiv !n !d
    -- same-sign ops can be handled by more efficient 'integerQuot'
    | isTrue# (integerIsNegative# n ==# integerIsNegative# d) = integerQuot n d
@@ -894,7 +926,7 @@ integerDiv !n !d
 
 
 integerMod :: Integer -> Integer -> Integer
-{-# NOINLINE integerMod #-}
+{-# NOINLINE[0] integerMod #-} -- See Note [Integer constant folding]
 integerMod !n !d
    -- same-sign ops can be handled by more efficient 'integerRem'
    | isTrue# (integerIsNegative# n ==# integerIsNegative# d) = integerRem n d
@@ -902,7 +934,7 @@ integerMod !n !d
 
 -- | Compute greatest common divisor.
 integerGcd :: Integer -> Integer -> Integer
-{-# NOINLINE integerGcd #-}
+{-# NOINLINE[0] integerGcd #-} -- See Note [Integer constant folding]
 integerGcd (IS 0#)  !b       = integerAbs b
 integerGcd a        (IS 0#)  = integerAbs a
 integerGcd (IS 1#)  _        = IS 1#
@@ -920,7 +952,7 @@ integerGcd (IP a)   (IS b)   = integerFromWord# (bigNatGcdWord# a (int2Word# (ab
 
 -- | Compute least common multiple.
 integerLcm :: Integer -> Integer -> Integer
-{-# NOINLINE integerLcm #-}
+{-# NOINLINE[0] integerLcm #-} -- See Note [Integer constant folding]
 integerLcm (IS 0#) !_  = IS 0#
 integerLcm (IS 1#)  b  = integerAbs b
 integerLcm (IS -1#) b  = integerAbs b
@@ -934,6 +966,7 @@ integerLcm a b         = (aa `integerQuot` (aa `integerGcd` ab)) `integerMul` ab
 
 -- | Square a Integer
 integerSqr :: Integer -> Integer
+{-# INLINE integerSqr #-} -- See Note [Integer constant folding]
 integerSqr !a = integerMul a a
 
 
@@ -951,6 +984,7 @@ integerLog2# (IP b)     = bigNatLog2# b
 --
 -- For numbers <= 0, return 0
 integerLog2 :: Integer -> Word
+{-# INLINE integerLog2 #-} -- See Note [Integer constant folding]
 integerLog2 !i = W# (integerLog2# i)
 
 -- | Logarithm (floor) for an arbitrary base
@@ -965,6 +999,7 @@ integerLogBaseWord# base !i
 --
 -- For numbers <= 0, return 0
 integerLogBaseWord :: Word -> Integer -> Word
+{-# INLINE integerLogBaseWord #-} -- See Note [Integer constant folding]
 integerLogBaseWord (W# base) !i = W# (integerLogBaseWord# base i)
 
 -- | Logarithm (floor) for an arbitrary base
@@ -980,6 +1015,7 @@ integerLogBase# !base !i
 --
 -- For numbers <= 0, return 0
 integerLogBase :: Integer -> Integer -> Word
+{-# INLINE integerLogBase #-} -- See Note [Integer constant folding]
 integerLogBase !base !i = W# (integerLogBase# base i)
 
 -- | Indicate if the value is a power of two and which one
@@ -994,7 +1030,7 @@ integerIsPowerOf2# (IP w) = bigNatIsPowerOf2# w
 
 -- | Convert an Int64# into an Integer on 32-bit architectures
 integerFromInt64# :: Int64# -> Integer
-{-# NOINLINE integerFromInt64# #-}
+{-# NOINLINE[0] integerFromInt64# #-} -- See Note [Integer constant folding]
 integerFromInt64# !i
   | isTrue# ((i `leInt64#` intToInt64#  0x7FFFFFFF#)
       &&# (i `geInt64#` intToInt64# -0x80000000#))
@@ -1008,7 +1044,7 @@ integerFromInt64# !i
 
 -- | Convert a Word64# into an Integer on 32-bit architectures
 integerFromWord64# :: Word64# -> Integer
-{-# NOINLINE integerFromWord64# #-}
+{-# NOINLINE[0] integerFromWord64# #-} -- See Note [Integer constant folding]
 integerFromWord64# !w
   | isTrue# (w `leWord64#` wordToWord64# 0x7FFFFFFF##)
   = IS (int64ToInt# (word64ToInt64# w))
@@ -1017,14 +1053,14 @@ integerFromWord64# !w
 
 -- | Convert an Integer into an Int64# on 32-bit architectures
 integerToInt64# :: Integer -> Int64#
-{-# NOINLINE integerToInt64# #-}
+{-# NOINLINE[0] integerToInt64# #-} -- See Note [Integer constant folding]
 integerToInt64# (IS i) = intToInt64# i
 integerToInt64# (IP b) = word64ToInt64# (bigNatToWord64# b)
 integerToInt64# (IN b) = negateInt64# (word64ToInt64# (bigNatToWord64# b))
 
 -- | Convert an Integer into a Word64# on 32-bit architectures
 integerToWord64# :: Integer -> Word64#
-{-# NOINLINE integerToWord64# #-}
+{-# NOINLINE[0] integerToWord64# #-} -- See Note [Integer constant folding]
 integerToWord64# (IS i) = int64ToWord64# (intToInt64# i)
 integerToWord64# (IP b) = bigNatToWord64# b
 integerToWord64# (IN b) = int64ToWord64# (negateInt64# (word64ToInt64# (bigNatToWord64# b)))
@@ -1033,6 +1069,7 @@ integerToWord64# (IN b) = int64ToWord64# (negateInt64# (word64ToInt64# (bigNatTo
 
 -- | Convert an Int64# into an Integer on 64-bit architectures
 integerFromInt64# :: Int# -> Integer
+{-# NOINLINE[0] integerFromInt64# #-} -- See Note [Integer constant folding]
 integerFromInt64# !x = IS x
 
 #endif
@@ -1043,18 +1080,19 @@ integerFromInt64# !x = IS x
 
 -- | Decode a Double# into (# Integer mantissa, Int# exponent #)
 integerDecodeDouble# :: Double# -> (# Integer, Int# #)
-{-# NOINLINE integerDecodeDouble# #-}
+{-# NOINLINE[0] integerDecodeDouble# #-} -- See Note [Integer constant folding]
 integerDecodeDouble# !x = case decodeDouble_Int64# x of
                             (# m, e #) -> (# integerFromInt64# m, e #)
 
 -- | Decode a Double# into (# Integer mantissa, Int# exponent #)
 integerDecodeDouble :: Double -> (Integer, Int)
+{-# INLINE integerDecodeDouble #-} -- See Note [Integer constant folding]
 integerDecodeDouble (D# x) = case integerDecodeDouble# x of
    (# m, e #) -> (m, I# e)
 
 -- | Encode (# Integer mantissa, Int# exponent #) into a Double#
 integerEncodeDouble# :: Integer -> Int# -> Double#
-{-# NOINLINE integerEncodeDouble# #-}
+{-# NOINLINE[0] integerEncodeDouble# #-} -- See Note [Integer constant folding]
 integerEncodeDouble# (IS i) 0# = int2Double# i
 integerEncodeDouble# (IS i) e  = intEncodeDouble# i e
 integerEncodeDouble# (IP b) e  = bigNatEncodeDouble# b e
@@ -1062,23 +1100,24 @@ integerEncodeDouble# (IN b) e  = negateDouble# (bigNatEncodeDouble# b e)
 
 -- | Encode (Integer mantissa, Int exponent) into a Double
 integerEncodeDouble :: Integer -> Int -> Double
+{-# INLINE integerEncodeDouble #-} -- See Note [Integer constant folding]
 integerEncodeDouble !m (I# e)  = D# (integerEncodeDouble# m e)
 
 -- | Encode an Integer (mantissa) into a Double#
 integerToDouble# :: Integer -> Double#
-{-# NOINLINE integerToDouble# #-}
+{-# NOINLINE[0] integerToDouble# #-} -- See Note [Integer constant folding]
 integerToDouble# !i = integerEncodeDouble# i 0#
 
 -- | Encode an Integer (mantissa) into a Float#
 integerToFloat# :: Integer -> Float#
-{-# NOINLINE integerToFloat# #-}
+{-# NOINLINE[0] integerToFloat# #-} -- See Note [Integer constant folding]
 integerToFloat# !i = integerEncodeFloat# i 0#
 
 -- | Encode (# Integer mantissa, Int# exponent #) into a Float#
 --
 -- TODO: Not sure if it's worth to write 'Float' optimized versions here
 integerEncodeFloat# :: Integer -> Int# -> Float#
-{-# NOINLINE integerEncodeFloat# #-}
+{-# NOINLINE[0] integerEncodeFloat# #-} -- See Note [Integer constant folding]
 integerEncodeFloat# !m 0# = double2Float# (integerToDouble# m)
 integerEncodeFloat# !m e  = double2Float# (integerEncodeDouble# m e)
 
@@ -1108,6 +1147,7 @@ integerToAddr# (IN n) = bigNatToAddr# n
 -- byte first (big-endian) if @1#@ or least significant byte first
 -- (little-endian) if @0#@.
 integerToAddr :: Integer -> Addr# -> Bool# -> IO Word
+{-# INLINE integerToAddr #-} -- See Note [Integer constant folding]
 integerToAddr a addr e = IO \s -> case integerToAddr# a addr e s of
    (# s', w #) -> (# s', W# w #)
 
@@ -1135,6 +1175,7 @@ integerFromAddr# sz addr e s =
 --
 -- Null higher limbs are automatically trimed.
 integerFromAddr :: Word# -> Addr# -> Bool# -> IO Integer
+{-# INLINE integerFromAddr #-} -- See Note [Integer constant folding]
 integerFromAddr sz addr e = IO (integerFromAddr# sz addr e)
 
 
@@ -1157,6 +1198,7 @@ integerToMutableByteArray# (IN a) = bigNatToMutableByteArray# a
 -- byte first (big-endian) if @1#@ or least significant byte first
 -- (little-endian) if @0#@.
 integerToMutableByteArray :: Integer -> MutableByteArray# RealWorld -> Word# -> Bool# -> IO Word
+{-# INLINE integerToMutableByteArray #-} -- See Note [Integer constant folding]
 integerToMutableByteArray i mba w e = IO \s -> case integerToMutableByteArray# i mba w e s of
    (# s', r #) -> (# s', W# r #)
 
@@ -1183,6 +1225,7 @@ integerFromByteArray# sz ba off e s = case bigNatFromByteArray# sz ba off e s of
 --
 -- Null higher limbs are automatically trimed.
 integerFromByteArray :: Word# -> ByteArray# -> Word# -> Bool# -> Integer
+{-# INLINE integerFromByteArray #-} -- See Note [Integer constant folding]
 integerFromByteArray sz ba off e = case runRW# (integerFromByteArray# sz ba off e) of
    (# _, i #) -> i
 
@@ -1215,5 +1258,45 @@ integerGcde
    :: Integer
    -> Integer
    -> ( Integer, Integer, Integer)
+{-# INLINE integerGcde #-} -- See Note [Integer constant folding]
 integerGcde a b = case integerGcde# a b of
    (# g,x,y #) -> (g,x,y)
+
+{- Note [Integer constant folding]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+We define constant folding rules in "GHC.Core.Opt.ConstantFold" for most of the
+ at integer*#@ operations in this module, hence they are marked NOINLINE[0].
+
+Why NOINLINE[0] rather than NOINLINE? Because
+
+  1. We still delay inlining long enough for the constant-folding RULEs
+     to fire
+  2. The compiler has the option to inlining the operations late, possibly
+     cancelling away boxes in the process.
+
+Why NOINLINE[0] rather than INLINE? Because
+
+  3. We don't unconditionally inline huge definitions such as
+     `integerDiv`, which would lead to code bloat at pretty much no
+     gain.
+  4. Since RULEs are unlikely to fire on the inlined RHS of e.g.
+     `integerDiv`, there is no gain in inlining the unoptimised
+     unfoldings.
+
+But since we potentially inline the constant folded operations in phase 0, we
+have to make sure that *all* callers that want to take part in constant folding
+are marked INLINE. Otherwise, we'd store optimised unfoldings for them, in which
+the constant folded functions are inlined.
+That concerns for most of the @integer*@ without trailing hash in this module,
+as well as the type class instances for 'Eq', 'Ord', 'Num', 'Integral',
+'RealFloat' (which is for 'Double'!), etc.
+
+There are a couple of constant-folded functions that require special treatment,
+though:
+
+  * `integerEq`, `integerNe`, `integerCompare`: They are huge and lead to
+    regressions when inlined. Solution: mark these NOINLINE.
+  * Under -O2, `integerAdd` will be specialised by SpecConstr. These
+    specialisations defeat constant folding.
+    Solution: -fno-spec-constr for this module.
+-}



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5cfe4d6bbe12a4c7d560fc19e76d781907bf7bda

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5cfe4d6bbe12a4c7d560fc19e76d781907bf7bda
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20201002/d3f4789a/attachment-0001.html>


More information about the ghc-commits mailing list