diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2022-11-09 10:33:56 +0000 |
---|---|---|
committer | Simon Peyton Jones <simon.peytonjones@gmail.com> | 2022-11-11 23:40:10 +0000 |
commit | 154c70f6c589aa6531cbeea4aa3ec06e0acaf690 (patch) | |
tree | 1d802f45b3989b51d6a44b6d2b9a0fb80713e6b4 /libraries/base/GHC/Float.hs | |
parent | 6b92b47fa2386ccb2f8264110ff7a827958fb7bf (diff) | |
download | haskell-154c70f6c589aa6531cbeea4aa3ec06e0acaf690.tar.gz |
Fix fragile RULE setup in GHC.Float
In testing my type-vs-constraint patch I found that the handling
of Natural literals was very fragile -- and I somehow tripped that
fragility in my work.
So this patch fixes the fragility.
See Note [realToFrac natural-to-float]
This made a big (9%) difference in one existing test in
perf/should_run/T1-359
Metric Decrease:
T10359
Diffstat (limited to 'libraries/base/GHC/Float.hs')
-rw-r--r-- | libraries/base/GHC/Float.hs | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/libraries/base/GHC/Float.hs b/libraries/base/GHC/Float.hs index 1d02acb2f1..6a04b2ed32 100644 --- a/libraries/base/GHC/Float.hs +++ b/libraries/base/GHC/Float.hs @@ -345,7 +345,8 @@ instance Fractional Float where recip x = 1.0 / x rationalToFloat :: Integer -> Integer -> Float -{-# NOINLINE [1] rationalToFloat #-} +{-# NOINLINE [0] rationalToFloat #-} +-- Re NOINLINE pragma, see Note [realToFrac natural-to-float] rationalToFloat n 0 | n == 0 = 0/0 | n < 0 = (-1)/0 @@ -577,7 +578,8 @@ instance Fractional Double where recip x = 1.0 / x rationalToDouble :: Integer -> Integer -> Double -{-# NOINLINE [1] rationalToDouble #-} +{-# NOINLINE [0] rationalToDouble #-} +-- Re NOINLINE pragma, see Note [realToFrac natural-to-float] rationalToDouble n 0 | n == 0 = 0/0 | n < 0 = (-1)/0 @@ -1488,6 +1490,25 @@ with the native backend, and 0.143 seconds with the C backend. A few more details in #2251, and the patch message "Add RULES for realToFrac from Int". + +Note [realToFrac natural-to-float] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Consider (realToFrac @Natural @Float ..dicts.. (NS lit#)) +We want to constant-fold this. For many types this is guaranteed +by a RULE for realToFrac: eg. RULE "realToFrac/Float->Double" above. + +In case there is a similar rule, we do not inline realToFrac in stage 2. +But for whatever reason, there is no such RULE for Natural. So in stage 1 +we end up with + rationalToFloat (integerFromNatural (NS lit)) +and that turns into + rationalToFloat (IS lit#) (IS 1#) + +Now we'd have a BUILTIN constant folding rule for rationalToFloat; but +to allow that rule to fire reliably we should delay inlining rationalToFloat +until stage 0. (It may get an inlining from CPR analysis.) + +Hence the NOINLINE[0] rationalToFloat, and similarly rationalToDouble. -} -- Utils |