Ticket #4227 (closed bug: fixed)

Opened 3 years ago

Last modified 22 months ago

Allow SPECIALISE pragmas for functions defined in another module

Reported by: simonpj Owned by:
Priority: normal Milestone: 7.4.1
Component: Compiler Version: 6.12.3
Keywords: Cc: sebf@…, michal.terepeta@…
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: None/Unknown Difficulty:
Test Case: Blocked By:
Blocking: Related Tickets:

Description

See  http://www.haskell.org/pipermail/glasgow-haskell-users/2010-July/019042.html

say I have

  module A where
     class C a where ...
     f :: C a => String -> a

  module B where
     import A
     data T = ...
     instance C T where ...
     g :: String -> SomeOtherType
     g s = doSomethingWith (f s)

Is it possible to SPECIALIZE f for the type T? Currently no.

Some care would be needed to support this. Currently GHC's -fexpose-all-unfoldings makes no attempt to ensure that the exposed unfolding for f is exactly what the user originally wrote. For example, other functions might have been inlined into f's RHS that might make it a lot bigger. Maybe you'd want to say

	{-# SPECIALISABLE f #-}
	f = <blah>

to mean "expose f's unfolding, pretty much as-is, rather than optimising it". This is close to what you get with

	{-# INLINE f #-}

(which also exposes the original RHS) but without the "please inline me at every call site" meaning.

Change History

Changed 3 years ago by sebf

The motivation for this is  Matching.hs. Currently it has SPECIALIZE pragmas for Prelude types but more complex matching policies like  Leftmost.hs must use unspecialized matching functions. Ideally, I would just write

 {-# SPECIALIZE partialMatch :: RegExp c -> [(Int,c)] -> Leftmost #-}
 {-# SPECIALIZE matchW :: RegW Leftmost c -> [(Int,c)] -> Leftmost #-}

into Leftmost.hs to specialize partialMatch and its overloaded dependency matchW.

Changed 3 years ago by igloo

  • milestone set to 6.16.1

Changed 3 years ago by simonpj

  • status changed from new to merge

Specialisation for imported functions is implemented in GHC 7, provided they are declared INLINABLE. I failed to write the documentation, but I have now done so:

Wed Nov 17 11:15:59 GMT 2010  simonpj@microsoft.com
  * Document SPECIALISE for imported functions
  
  This is a really useful new facility, but I'd forgotten to document it.
  Pls merge to 7.0 branch

Pls merge.

Simon

Changed 3 years ago by igloo

  • status changed from merge to closed
  • resolution set to fixed

Merged.

Changed 2 years ago by dreixel

Is this working for class methods too? See the following example:

module M1 where

class MyEnum a where
  {-# INLINABLE myEnum #-}
  myEnum :: [a]

instance MyEnum () where myEnum = [()]

{-# INLINABLE myEnum' #-}
myEnum' :: (MyEnum a) => [a]
myEnum' = myEnum
module M2 where

import M1

{-# SPECIALISE myEnum  :: [()] #-}
{-# SPECIALISE myEnum' :: [()] #-}

The first SPECIALISE pragma gives You cannot SPECIALISE `myEnum' because its definition has no INLINE/INLINABLE pragma, whereas the second works fine. I would expect the first to work too.

Changed 2 years ago by Blaisorblade

  • status changed from closed to new
  • resolution fixed deleted

@dreixel: in the example, myEnum specialized to type [()] would coincide with myEnum as defined in the instance. That is general for all non-polymorphic instances: given an instance MyEnum? [a], it would make sense to specialized myEnum :: [Int] (I don't have GHC 7 to test this), assuming that the instance definition myEnum :: [a] is marked as INLINABLE.

OTOH, if the original INLINABLE myEnum annotation is ignored, it should not be ignored silently: an error or warning should be given, and _that is a bug_. Viceversa, INLINABLE on a class method _with_ a definition should be respected. Is it not?

The only reasonable meaning of INLINABLE on an abstract class method could be "make all instance definition inlinable", but in many cases you want to allow specializing only specific instances which have a small size: this might be a good reason against implementing it.

Changed 2 years ago by michalt

  • cc michal.terepeta@… added

I can reproduce the problem on 7.0.3, but it seems to be fixed in HEAD. The example compiles just fine and for some simple test like:

test :: [()]
test = myEnum

the rule for specilization fires as expected.

Changed 22 months ago by simonpj

  • status changed from new to closed
  • resolution set to fixed

Great. Sounds as if we're done with this ticket then.

Note: See TracTickets for help on using tickets.