Specialisation rules fail because dictionary projections do not match
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)]
The core + interface generated for this module contains the rule:
"SPEC Hedgehog.hedgehog" ALWAYS forall
Hedgehog.hedgehog @ GHC.Float.Float
@ RectGrid.Cell_8
@ RectGrid.MyVertex
@ Geometries.Coord3
@ Geometries.Vector3
GHC.Float.$f16
RectGrid.$f2
RectGrid.$f10
Geometries.$f5
Geometries.$f3
Geometries.$f1
But in a different module (Viewer.hs), here is what the usage site looks like just before the specialisation rules are supposed to fire:
hedgehog_aWr =
Hedgehog.hedgehog
@ GHC.Float.Float
@ RectGrid.Cell_8
@ RectGrid.MyVertex
@ Geometries.Coord3
@ Geometries.Vector3
GHC.Float.$f16
RectGrid.$f2
RectGrid.$f10
(Dataset.$p2Embed @ Geometries.Vector3 @ Geometries.Coord3 Geometries.$f1)
(Dataset.$p1Embed @ Geometries.Vector3 @ Geometries.Coord3 Geometries.$f1)
Geometries.$f1
Notice how there are a couple of dictionary projection functions still 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 eventually:
hedgehog_r2at =
Hedgehog.$whedgehog
@ GHC.Float.Float
@ RectGrid.Cell_8
@ RectGrid.MyVertex
@ Geometries.Coord3
@ Geometries.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!
A code archive is attached, to help you reproduce the behaviour. I have cut down the code considerably already, but it is still spread over 5 modules: I was unable to cut it down much further without the bug disappearing (probably through inlining or something).
Classes are defined in Dataset.hs, instances in Geometries.hs. The code I want to specialise is in Hedgehog.hs, and the usage site is in Viewer.hs (the main program).
Trac metadata
Trac field | Value |
---|---|
Version | 6.8.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |