
Here is an apparent bug in ghc's specialisation rules. The rewrite rule generated by a SPECIALISE pragma seems to want to pattern-match on exact dictionaries (as well as types). But the compiler is not necessarily able to fully resolve dictionaries before the rules are supposed to fire. First, the source code we want to specialise: {-# SPECIALISE hedgehog :: Float -> Vector3 Float -> [Cell_8 (Coord3 Float)] -> [Cell_8 (Vector3 Float)] -> [(Coord3 Float, Coord3 Float)] #-} hedgehog :: ( Fractional a, Cell cell vert, Eq vert , Geom coord, Geom vector, Embed vector coord ) => a -> vector a -> [cell (coord a)] -> [cell (vector a)] -> [(coord a, coord a)] And the core + interface generated for this module contains the rule: "SPEC Hedgehog.hedgehog" ALWAYS forall Hedgehog.hedgehog @ GHC.Float.Float @ RectGrid.Cell_8 @ CellTypes.MyVertex @ Geometries.Coord3 @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 GHC.Float.$f16 RectGrid.$f2 CellTypes.$f1 Geometries.$f5 Geometries.$f3 Geometries.$f1 = Hedgehog.hedgehog1 But in a different module, here is what the usage site looks like just before the specialisation rules are supposed to fire: hedgehog_a4wy = Hedgehog.hedgehog @ GHC.Float.Float @ RectGrid.Cell_8 @ CellTypes.MyVertex @ Geometries.Coord3 @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 $dFractional_a4xP RectGrid.$f2 CellTypes.$f1 (Dataset.$p2Embed @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 @ Geometries.Coord3 Geometries.$f1) (Dataset.$p1Embed @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 @ Geometries.Coord3 Geometries.$f1) Geometries.$f1 Notice how there are several dictionary selector functions sitting there, so although some of the dictionaries match, not all do, and the rule does not fire. However, later the worker-wrapper transformation is able to resolve those outstanding dictionaries, giving: hedgehog_a4wy = Hedgehog.$whedgehog @ GHC.Float.Float @ RectGrid.Cell_8 @ CellTypes.MyVertex @ Geometries.Coord3 @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 GHC.Float.$f16 RectGrid.$f2 Geometries.$f5 Geometries.$f3 Geometries.$f1 So I'm left calling the worker for the polymorphic version of the function, rather than the specialised monomorphic code I wanted. Given how many dictionaries are involved, and that this is the inner loop of the program, I'm hoping there is a big performance win waiting for me, if only I can get that specialised code to run! Regards, Malcolm

That should not happen. Can you boil out a test case and make a Trac ticket? When I try the same thing it works: Spec.hs: f :: Num a => a -> a {-# SPECIALISE f :: Int -> Int #-} f x = x+2 ghc -c -ddump-rules -O Spec.hs ==================== Top-level specialisations ==================== "SPEC Foo.f" ALWAYS forall {$dNum :: GHC.Num.Num GHC.Types.Int} Foo.f @ GHC.Types.Int $dNum = f Note the quantification over $dNum. Simon | -----Original Message----- | From: glasgow-haskell-users-bounces@haskell.org [mailto:glasgow-haskell-users- | bounces@haskell.org] On Behalf Of Malcolm Wallace | Sent: 11 February 2009 16:58 | To: glasgow-haskell-users@haskell.org | Subject: bug in ghc specialiser? | | Here is an apparent bug in ghc's specialisation rules. The rewrite rule | generated by a SPECIALISE pragma seems to want to pattern-match on exact | dictionaries (as well as types). But the compiler is not necessarily | able to fully resolve dictionaries before the rules are supposed to | fire. | | First, the source code we want to specialise: | | {-# SPECIALISE | hedgehog :: Float -> Vector3 Float | -> [Cell_8 (Coord3 Float)] | -> [Cell_8 (Vector3 Float)] | -> [(Coord3 Float, Coord3 Float)] | #-} | hedgehog :: ( Fractional a, Cell cell vert, Eq vert | , Geom coord, Geom vector, Embed vector coord ) => | a -> vector a | -> [cell (coord a)] | -> [cell (vector a)] | -> [(coord a, coord a)] | | And the core + interface generated for this module contains the rule: | | "SPEC Hedgehog.hedgehog" ALWAYS forall | Hedgehog.hedgehog @ GHC.Float.Float | @ RectGrid.Cell_8 | @ CellTypes.MyVertex | @ Geometries.Coord3 | @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 | GHC.Float.$f16 | RectGrid.$f2 | CellTypes.$f1 | Geometries.$f5 | Geometries.$f3 | Geometries.$f1 | = Hedgehog.hedgehog1 | | But in a different module, here is what the usage site looks like just | before the specialisation rules are supposed to fire: | | hedgehog_a4wy = | Hedgehog.hedgehog | @ GHC.Float.Float | @ RectGrid.Cell_8 | @ CellTypes.MyVertex | @ Geometries.Coord3 | @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 | $dFractional_a4xP | RectGrid.$f2 | CellTypes.$f1 | (Dataset.$p2Embed | @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 | @ Geometries.Coord3 | Geometries.$f1) | (Dataset.$p1Embed | @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 | @ Geometries.Coord3 | Geometries.$f1) | Geometries.$f1 | | Notice how there are several dictionary selector functions sitting | there, so although some of the dictionaries match, not all do, and the | rule does not fire. However, later the worker-wrapper transformation | is able to resolve those outstanding dictionaries, giving: | | hedgehog_a4wy = | Hedgehog.$whedgehog | @ GHC.Float.Float | @ RectGrid.Cell_8 | @ CellTypes.MyVertex | @ Geometries.Coord3 | @ Graphics.Rendering.OpenGL.GL.CoordTrans.Vector3 | GHC.Float.$f16 | RectGrid.$f2 | Geometries.$f5 | Geometries.$f3 | Geometries.$f1 | | So I'm left calling the worker for the polymorphic version of the | function, rather than the specialised monomorphic code I wanted. Given | how many dictionaries are involved, and that this is the inner loop of | the program, I'm hoping there is a big performance win waiting for me, | if only I can get that specialised code to run! | | Regards, | Malcolm | _______________________________________________ | Glasgow-haskell-users mailing list | Glasgow-haskell-users@haskell.org | http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
participants (2)
-
Malcolm Wallace
-
Simon Peyton-Jones