[Git][ghc/ghc][wip/T18765] s/NOINLINE/NOINLINE[0]/g in GHC.Num.Integer (#18765)
Sebastian Graf
gitlab at gitlab.haskell.org
Wed Sep 30 10:45:51 UTC 2020
Sebastian Graf pushed to branch wip/T18765 at Glasgow Haskell Compiler / GHC
Commits:
9b3c12b5 by Sebastian Graf at 2020-09-30T12:44:54+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.
Fixes #18765.
- - - - -
4 changed files:
- compiler/GHC/Core/Opt/ConstantFold.hs
- libraries/base/GHC/Float.hs
- libraries/base/GHC/Real.hs
- libraries/ghc-bignum/src/GHC/Num/Integer.hs
Changes:
=====================================
compiler/GHC/Core/Opt/ConstantFold.hs
=====================================
@@ -1347,7 +1347,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 libraries/base/GHC/Num/Integer.hs
, 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/Real.hs
=====================================
@@ -413,43 +413,31 @@ 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
@@ -457,27 +445,27 @@ instance Integral Integer where
instance Integral Natural where
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/ghc-bignum/src/GHC/Num/Integer.hs
=====================================
@@ -66,6 +66,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
@@ -145,18 +146,19 @@ integerFromInt (I# i) = IS 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 +169,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 +188,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 +214,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 +225,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 +242,48 @@ 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[0] integerEq# #-} -- See Note [Integer constant folding]
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 +291,7 @@ integerEq# _ _ = 0#
-- | Not-equal predicate.
integerNe# :: Integer -> Integer -> Bool#
-{-# NOINLINE integerNe# #-}
+{-# NOINLINE[0] integerNe# #-} -- See Note [Integer constant folding]
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 +299,41 @@ 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[0] integerCompare #-} -- See Note [Integer constant folding]
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 +345,7 @@ integerCompare (IP _) (IN _) = GT
integerCompare (IN _) (IP _) = LT
instance Ord Integer where
+ {-# INLINE compare #-} -- See Note [Integer constant folding]
compare = integerCompare
---------------------------------------------------------------------
@@ -338,7 +354,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 +400,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 +429,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 +494,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)
@@ -489,7 +505,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)
@@ -501,13 +517,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#
@@ -515,7 +531,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)))
@@ -524,7 +540,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))
@@ -533,13 +549,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
@@ -569,13 +586,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
@@ -592,11 +610,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
@@ -611,13 +630,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#
@@ -676,7 +696,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
@@ -731,7 +751,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
@@ -766,7 +786,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##)
@@ -777,7 +797,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
@@ -815,12 +835,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
@@ -841,7 +862,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#)
@@ -863,7 +884,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#)
@@ -878,12 +899,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
@@ -891,7 +913,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
@@ -899,7 +921,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#
@@ -917,7 +939,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
@@ -931,6 +953,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
@@ -948,6 +971,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
@@ -962,6 +986,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
@@ -977,6 +1002,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
@@ -991,7 +1017,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#))
@@ -1005,7 +1031,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))
@@ -1014,14 +1040,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)))
@@ -1040,18 +1066,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
@@ -1059,23 +1086,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)
@@ -1105,6 +1133,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 #)
@@ -1132,6 +1161,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)
@@ -1154,6 +1184,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 #)
@@ -1180,6 +1211,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
@@ -1212,5 +1244,36 @@ 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.
+-}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9b3c12b5351ce930085743c7ab7231acabf75f08
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9b3c12b5351ce930085743c7ab7231acabf75f08
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/20200930/344c49a1/attachment-0001.html>
More information about the ghc-commits
mailing list