[GHC] #2110: Rules to eliminate casted id's

GHC ghc-devs at haskell.org
Sun Sep 15 16:41:18 CEST 2013


#2110: Rules to eliminate casted id's
-------------------------------------+------------------------------------
        Reporter:  igloo             |            Owner:
            Type:  feature request   |           Status:  new
        Priority:  lowest            |        Milestone:  7.6.2
       Component:  Compiler          |          Version:  6.8.2
      Resolution:                    |         Keywords:
Operating System:  Unknown/Multiple  |     Architecture:  Unknown/Multiple
 Type of failure:  None/Unknown      |       Difficulty:  Unknown
       Test Case:                    |       Blocked By:
        Blocking:                    |  Related Tickets:
-------------------------------------+------------------------------------

Comment (by nomeata):

 Please allow me to use this as a notepad; this way I (or someone else) can
 easily find the thoughts later.

 With `Coercible` in GHC, one might want that

 {{{
 {-# RULES
 "myMap/coerce"  myMap coerce = coerce
  #-}
 }}}
 will be a usable rule that would also fire in
 {{{
 foo :: [Int] -> [Age]
 foo = myMap Age
 }}}

 At the moment, it does not do that yet. Here is the rule (as shown by
 `-ddump-rules`, with `-O`):
 {{{
 ==================== Tidy Core rules ====================
 "myMap/coerce" [ALWAYS]
     forall (@ t) (@ t1) ($dCoercible :: GHC.Types.Coercible t t1).
       Test.myMap @ t @ t1 (GHC.Prim.coerce @ t @ t1 $dCoercible)
       = GHC.Prim.coerce
           @ [t]
           @ [t1]
           (case $dCoercible of _ { GHC.Types.MkCoercible ds ->
            GHC.Types.MkCoercible @ [t] @ [t1] @~ [ds]_R
            })
 }}}
 and here is the Core code the rule needs to match (`-ddump-simpl`, with
 `-O`):
 {{{
 Test.foo1 :: GHC.Types.Int -> GHC.Types.Int
 [GblId,
  Arity=1,
  Caf=NoCafRefs,
  Str=DmdType <S,1*U(U)>m,
  Unf=Unf{Src=InlineStable, TopLvl=True, Arity=1, Value=True,
          ConLike=True, WorkFree=True, Expandable=True,
          Guidance=ALWAYS_IF(unsat_ok=True,boring_ok=True)
          Tmpl= \ (tpl_B1 [Occ=Once] :: GHC.Types.Int) -> tpl_B1}]
 Test.foo1 = \ (tpl_B1 :: GHC.Types.Int) -> tpl_B1

 Test.foo :: [GHC.Types.Int] -> [Test.Age]
 [GblId,
  Arity=1,
  Str=DmdType,
  Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=True,
          ConLike=True, WorkFree=True, Expandable=True,
          Guidance=IF_ARGS [] 20 60}]
 Test.foo =
   Test.foo_myMap
     @ GHC.Types.Int
     @ Test.Age
     (Test.foo1
      `cast` (<GHC.Types.Int>_R -> Sym Test.NTCo:Age[0]
              :: (GHC.Types.Int -> GHC.Types.Int)
                   ~#
                 (GHC.Types.Int -> Test.Age)))
 }}}

 Note that in the rule’s LHS, `coerce` was not unfolded, while it is in the
 core. Also note that the rule talks about a `Coercion` value that we do
 not have.

 Here is one plan that might work. If a rule has a binder `$d` of type
 `Coercible a b`, then the rule is changed to have a binder `c` of type `a
 ~R# b`, and every occurrence of `$d` is replaced by `MkCoercible a b c`.
 So the rule above, (after simplification of the RHS) would read

 {{{
 "myMap/coerce" [ALWAYS]
     forall (@ t) (@ t1) (c :: t ~R# t1).
       Test.myMap @ t @ t1 (GHC.Prim.coerce @ t @ t1 (GHC.Types.MkCoercible
 @ t @ t1 @~ c)
       = GHC.Prim.coerce
           @ [t]
           @ [t1]
           (GHC.Types.MkCoercible @ [t] @ [t1] @~ [c]_R)
 }}}

 The next step is to simplify occurrences of `coerce @ a @ b (MkCoercible @
 a @ b @~ c)` and replace them by (id `cast` c):

 {{{
 "myMap/coerce" [ALWAYS]
     forall (@ t) (@ t1) (c :: t ~R# t1).
       Test.myMap @ t @ t1 (id `cast` c)
       = GHC.Prim.coerce
           @ [t]
           @ [t1]
           (GHC.Types.MkCoercible @ [t] @ [t1] @~ [c]_R)
 }}}

 which (possibly after inlining id) with some reasonable hope matches the
 actual code.

 I especially like how the specializing of `Coercible` values to `~R#`
 values allows to use the matched coercion (which could even come from a
 `unsafeCoerce`!) in the RHS of the rule, instead of completely throwing it
 away and firing only if the coercion on the RHS can be found by the type
 checker.

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/2110#comment:36>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler



More information about the ghc-tickets mailing list