From 154c70f6c589aa6531cbeea4aa3ec06e0acaf690 Mon Sep 17 00:00:00 2001 From: Simon Peyton Jones Date: Wed, 9 Nov 2022 10:33:56 +0000 Subject: 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 --- libraries/base/GHC/Float.hs | 25 +++++++++++++++++++++++-- 1 file 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 -- cgit v1.2.1