[Git][ghc/ghc][wip/T24359] 2 commits: Split up SPECIALISE pragmas in GHC.Internal.Real

sheaf (@sheaf) gitlab at gitlab.haskell.org
Tue Dec 3 10:47:49 UTC 2024



sheaf pushed to branch wip/T24359 at Glasgow Haskell Compiler / GHC


Commits:
977a3b5c by sheaf at 2024-12-03T11:47:40+01:00
Split up SPECIALISE pragmas in GHC.Internal.Real

- - - - -
63c0155f by sheaf at 2024-12-03T11:47:40+01:00
update user's guide for SPECIALISE expression syntax

- - - - -


3 changed files:

- docs/users_guide/exts/pragmas.rst
- docs/users_guide/using-warnings.rst
- libraries/ghc-internal/src/GHC/Internal/Real.hs


Changes:

=====================================
docs/users_guide/exts/pragmas.rst
=====================================
@@ -692,24 +692,26 @@ The :pragma:`RULES` pragma lets you specify rewrite rules. It is described in
    single: pragma, SPECIALIZE
    single: overloading, death to
 
-.. pragma:: SPECIALIZE ⟨name⟩ :: ⟨type⟩
+.. pragma:: SPECIALIZE ⟨expr⟩
 
-    Ask that GHC specialize a polymorphic value to a particular type.
+    Ask that GHC specialize a polymorphic value.
 
 (UK spelling also accepted.) For key overloaded functions, you can
-create extra versions (NB: at the cost of larger code) specialised to particular
-types. Thus, if you have an overloaded function:
+create extra versions (NB: at the cost of larger code), specialised to specific
+arguments. Thus, if you have an overloaded function:
 
 ::
 
       hammeredLookup :: Ord key => [(key, value)] -> key -> value
 
 If it is heavily used on lists with ``Widget`` keys, you could
-specialise it as follows:
+specialise it with either of the following forms (the second syntax,
+introduced in GHC 9.14, additionally requires :extension:`TypeApplications`):
 
 ::
 
       {-# SPECIALIZE hammeredLookup :: [(Widget, value)] -> Widget -> value #-}
+      {-# SPECIALIZE hammeredLookup @Widget #-}
 
 -  A ``SPECIALIZE`` pragma for a function can be put anywhere its type
    signature could be put. Moreover, you can also ``SPECIALIZE`` an
@@ -755,15 +757,14 @@ specialise it as follows:
    specialisation is done too early, the optimisation rules might fail
    to fire.
 
--  The type in a ``SPECIALIZE`` pragma can be any type that is less
-   polymorphic than the type of the original function. In concrete
-   terms, if the original function is ``f`` then the pragma
+-  The ``SPECIALIZE`` pragma is valid only if the expression is well-typed.
+   For example, a specialize pragma of the form
 
    ::
 
          {-# SPECIALIZE f :: <type> #-}
 
-   is valid if and only if the definition
+   is valid only if the definition
 
    ::
 
@@ -777,6 +778,7 @@ specialise it as follows:
 
          f :: Eq a => a -> b -> b
          {-# SPECIALISE f :: Int -> b -> b #-}
+         {-# SPECIALISE f @Float #-}
 
          g :: (Eq a, Ix b) => a -> b -> b
          {-# SPECIALISE g :: (Eq a) => a -> Int -> Int #-}
@@ -789,12 +791,28 @@ specialise it as follows:
    fire very well. If you use this kind of specialisation, let us know
    how well it works.
 
+-  Since GHC 9.14, it is also possible to specialise a function at specific
+   value arguments, e.g.: ::
+
+         fn :: Bool -> Int -> Double
+         fn b i = ...
+           where
+             ... = if b then helper1 else helper2
+         {-# SPECIALISE fn True #-}
+         {-# SPECIALISE fn False #-}
+
+   This will make two copies of ``fn``, one for ``True`` and one for ``False``.
+   These will then be optimised to make direct calls to ``helper1`` or ``helper2``,
+   respectively, instead of dispatching on ``b`` at runtime.
+   Call sites (that use a literal ``True`` or ``False``) will be rewritten
+   to use the specialised versions.
+
 .. _specialize-inline:
 
 ``SPECIALIZE INLINE``
 ~~~~~~~~~~~~~~~~~~~~~
 
-.. pragma:: SPECIALIZE INLINE ⟨name⟩ :: ⟨type⟩
+.. pragma:: SPECIALIZE INLINE ⟨expr⟩
 
     :where: top-level
 


=====================================
docs/users_guide/using-warnings.rst
=====================================
@@ -423,6 +423,20 @@ of ``-W(no-)*``.
     such as a `LANGUAGE` or `OPTIONS_GHC` pragma, appears in the body of
     the module instead.
 
+.. ghc-flag:: -Wdeprecated-pragmas
+    :shortdesc: warn about deprecated pragmas
+    :type: dynamic
+    :reverse: -Wno-deprecated-pragmas
+    :category:
+
+    :since: 9.14
+
+    :default: on
+
+    Emits a warning when using a deprecated form of a SPECIALISE pragma which
+    uses multiple comma-separated type signatures (deprecated and scheduled
+    to be removed in GHC 9.18).
+
 .. ghc-flag:: -Wmissed-specialisations
     :shortdesc: warn when specialisation of an imported, overloaded function
         fails.
@@ -477,6 +491,27 @@ of ``-W(no-)*``.
 
     Alias for :ghc-flag:`-Wall-missed-specialisations`
 
+.. ghc-flag:: -Wuseless-specialisations
+    :shortdesc: warn on useless SPECIALISE pragmas
+    :type: dynamic
+    :reverse: -Wno-useless-specialisations
+    :category:
+
+    :since: 9.14
+
+    :default: on
+
+    Emits a warning if GHC detects a useless SPECIALISE pragma, such as a
+    SPECIALISE pragma on a non-overloaded function, for example
+    ``{-# SPECIALISE id :: Int -> Int #-}``.
+
+.. ghc-flag:: -Wuseless-specializations
+    :shortdesc: alias for :ghc-flag:`-Wuseless-specialisations`
+    :type: dynamic
+    :reverse: -Wno-useless-specializations
+
+    Alias for :ghc-flag:`-Wuseless-specialisations`
+
 .. ghc-flag:: -Wextended-warnings
     :shortdesc: warn about uses of functions & types that have WARNING or
         DEPRECATED pragmas, across all categories


=====================================
libraries/ghc-internal/src/GHC/Internal/Real.hs
=====================================
@@ -746,10 +746,9 @@ x0 ^ y0 | y0 < 0    = errorWithoutStackTrace "Negative exponent"
         | y0 == 0   = 1
         | otherwise = powImpl x0 y0
 
-{-# SPECIALISE powImpl ::
-        Integer -> Integer -> Integer,
-        Integer -> Int -> Integer,
-        Int -> Int -> Int #-}
+{-# SPECIALISE powImpl :: Integer -> Integer -> Integer #-}
+{-# SPECIALISE powImpl :: Integer -> Int -> Integer #-}
+{-# SPECIALISE powImpl :: Int -> Int -> Int #-}
 {-# INLINABLE powImpl #-}    -- See Note [Inlining (^)]
 powImpl :: (Num a, Integral b) => a -> b -> a
 -- powImpl : x0 ^ y0 = (x ^ y)
@@ -757,10 +756,9 @@ powImpl x y | even y    = powImpl (x * x) (y `quot` 2)
             | y == 1    = x
             | otherwise = powImplAcc (x * x) (y `quot` 2) x -- See Note [Half of y - 1]
 
-{-# SPECIALISE powImplAcc ::
-        Integer -> Integer -> Integer -> Integer,
-        Integer -> Int -> Integer -> Integer,
-        Int -> Int -> Int -> Int #-}
+{-# SPECIALISE powImplAcc :: Integer -> Integer -> Integer -> Integer #-}
+{-# SPECIALISE powImplAcc :: Integer -> Int -> Integer -> Integer #-}
+{-# SPECIALISE powImplAcc :: Int -> Int -> Int -> Int #-}
 {-# INLINABLE powImplAcc #-}    -- See Note [Inlining (^)]
 powImplAcc :: (Num a, Integral b) => a -> b -> a -> a
 -- powImplAcc : x0 ^ y0 = (x ^ y) * z



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/dade6ff3f6267aad0bd4f32ff778ae5a129aa15a...63c0155f0b908bad7ea557d2e85cef02d5e108e1

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/dade6ff3f6267aad0bd4f32ff778ae5a129aa15a...63c0155f0b908bad7ea557d2e85cef02d5e108e1
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20241203/2e8ab79d/attachment-0001.html>


More information about the ghc-commits mailing list