summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2022-11-09 10:33:56 +0000
committerSimon Peyton Jones <simon.peytonjones@gmail.com>2022-11-11 23:40:10 +0000
commit154c70f6c589aa6531cbeea4aa3ec06e0acaf690 (patch)
tree1d802f45b3989b51d6a44b6d2b9a0fb80713e6b4
parent6b92b47fa2386ccb2f8264110ff7a827958fb7bf (diff)
downloadhaskell-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
-rw-r--r--libraries/base/GHC/Float.hs25
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