summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Klebinger <klebinger.andreas@gmx.at>2020-04-16 17:43:32 +0200
committerAndreas Klebinger <klebinger.andreas@gmx.at>2020-04-19 12:27:44 +0200
commit0ed373698572aed88cf91553368a1dfa9767b749 (patch)
tree0d9f130dfc6eb5fbf5d56d37de53fcefdff92dbf
parentbcafaa82a0223afd5d103e052ab9a097a676e5ea (diff)
downloadhaskell-wip/andreask/inline_div.tar.gz
Always inline divInt and modInt in phase zero.wip/andreask/inline_div
This prevents the overhead of a function call for operations which really only need to be a few instructions. By always inlining them in phase zero we can: * Match on them via rules in earlier phases. * Can constant fold on them in phase zero by rules on their underlying primitives. This fixes #18067
-rw-r--r--libraries/base/GHC/Base.hs27
-rw-r--r--libraries/ghc-prim/GHC/Classes.hs4
2 files changed, 29 insertions, 2 deletions
diff --git a/libraries/base/GHC/Base.hs b/libraries/base/GHC/Base.hs
index 610e2996a8..25d341de87 100644
--- a/libraries/base/GHC/Base.hs
+++ b/libraries/base/GHC/Base.hs
@@ -1545,9 +1545,36 @@ getTag x = dataToTag# x
-- Definitions of the boxed PrimOps; these will be
-- used in the case of partial applications, etc.
+{- Note [Inlining divInt, modInt]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ divInt and modInt are implemented by calling unboxed
+ variants, which themselves are implemented in terms of
+ the quotInt#/remInt# primOps.
+
+ My marking the boxed versions as INLINE[1] we achieve two things:
+
+ * The strength reduction rules which are operating on divInt#/remInt#
+ can already fire in phase 1.
+ * We can inline any constant argument in Phase zero optimizing the
+ general case somewhat.
+
+ This solves #18067 where we observed divInt ending up
+ as a uninlined call to divInt# at times.
+
+ TODO: It might be good to apply the same pattern to
+ quotRemInt and divModInt. But I have not looked at this
+ yet.
+
+-}
+
{-# INLINE quotInt #-}
{-# INLINE remInt #-}
+-- See Note [Inlining divInt, modInt]
+{-# INLINE[1] divInt #-}
+{-# INLINE[1] modInt #-}
+
quotInt, remInt, divInt, modInt :: Int -> Int -> Int
(I# x) `quotInt` (I# y) = I# (x `quotInt#` y)
(I# x) `remInt` (I# y) = I# (x `remInt#` y)
diff --git a/libraries/ghc-prim/GHC/Classes.hs b/libraries/ghc-prim/GHC/Classes.hs
index 4ccfe914bd..43364f40e4 100644
--- a/libraries/ghc-prim/GHC/Classes.hs
+++ b/libraries/ghc-prim/GHC/Classes.hs
@@ -545,8 +545,8 @@ not False = True
-- put them
-- These functions have built-in rules.
-{-# NOINLINE [0] divInt# #-}
-{-# NOINLINE [0] modInt# #-}
+{-# INLINE [0] divInt# #-}
+{-# INLINE [0] modInt# #-}
divInt# :: Int# -> Int# -> Int#
x# `divInt#` y#
-- Be careful NOT to overflow if we do any additional arithmetic