Fix performance regression in quotRemInteger/divModInteger
authorSimon Marlow <marlowsd@gmail.com>
Thu, 20 Nov 2008 09:58:15 +0000 (09:58 +0000)
committerSimon Marlow <marlowsd@gmail.com>
Thu, 20 Nov 2008 09:58:15 +0000 (09:58 +0000)
This fixes most of the performance regression in these functions
between 6.8.3 and 6.10.1, it was due to a slight difference in the
strictness between the old and new versions (see comments for
details).  There's still a few percent loss in performance in the div
test in nofib/spectral/integer that I haven't tracked down as yet.

GHC/Integer.lhs

index 137eff1..b31f551 100644 (file)
@@ -161,7 +161,14 @@ toBig i@(J# _ _) = i
 
 quotRemInteger :: Integer -> Integer -> (# Integer, Integer #)
 quotRemInteger a@(S# INT_MINBOUND) b = quotRemInteger (toBig a) b
-quotRemInteger (S# i) (S# j) = (# S# (i `quotInt#` j), S# (i `remInt#` j) #)
+quotRemInteger (S# i) (S# j) = (# S# q, S# r #)
+    where
+      -- NB. don't inline these.  (# S# (i `quotInt#` j), ... #) means
+      -- (# let q = i `quotInt#` j in S# q, ... #) which builds a
+      -- useless thunk.  Placing the bindings here means they'll be
+      -- evaluated strictly.
+      q = i `quotInt#` j
+      r = i `remInt#`  j
 quotRemInteger i1@(J# _ _) i2@(S# _) = quotRemInteger i1 (toBig i2)
 quotRemInteger i1@(S# _) i2@(J# _ _) = quotRemInteger (toBig i1) i2
 quotRemInteger (J# s1 d1) (J# s2 d2)
@@ -171,8 +178,12 @@ quotRemInteger (J# s1 d1) (J# s2 d2)
 
 divModInteger :: Integer -> Integer -> (# Integer, Integer #)
 divModInteger a@(S# INT_MINBOUND) b = divModInteger (toBig a) b
-divModInteger (S# i) (S# j) = (# S# (i `divInt#` j), S# (i `modInt#` j) #)
+divModInteger (S# i) (S# j) = (# S# d, S# m #)
     where
+      -- NB. don't inline these.  See quotRemInteger above.
+      d = i `divInt#` j
+      m = i `modInt#` j
+
       -- XXX Copied from GHC.Base
       divInt# :: Int# -> Int# -> Int#
       x# `divInt#` y#