Simplifier vs. rules problem

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Simplifier vs. rules problem

michael.sperber

I've been trying to make Conal's ConCat plugin work for polymorphic
code, and am running into some problems with the ghc doing that, and I'd
very much appreciate help with that.

Background: I'm trying to get -dcore-lint to flag when my actual problem
happens (has to do with dictionary construction, but it fails earlier
with another problem, which I think comes from the simplifier.

tl;dr: This transformation seems to me problematic:

https://ghc-compiler-notes.readthedocs.io/en/latest/notes/compiler/simplCore/Simplify.hs.html#note-case-to-let-transformation

The docs for the transformation say that it makes this replacement:

case a +# b of r -> …r… into let r = a +# b in …r…

But this creates a let binding with an unlifted binder, which the linter
does not like:

<no location info>: warning:
    [RHS of ... :: Int#]
    The type of this binder is unlifted: ...
    Binder's type: Int#

Arguably, this rule might expect the let to be inlined, but we're seeing
that the let stands, and the linter complains.

My immediate concern is getting around this problem somehow so I can run
the linter on later output of the simplifier.  Is there any way to do
this?  I.e. don't stop when the linter complains, somehow massage the
rules to work better - see below.  Any help would be much appreciated!
(I'm using ghc 8.8.3.)

More details:

The ConCat code has this rule:

"rebox2" [~0] (+#) = \ u# v# -> unboxI (addC (boxI u#, boxI v#))

It fires like this:

Rule fired
    Rule: rebox_2
    Module: (ConCat.Rebox)
    Before: GHC.Prim.+# ValArg 10# ValArg 1#
    After:  (\ (u#_aM4G :: GHC.Prim.Int#) (v#_aM4H :: GHC.Prim.Int#) ->
               ConCat.Rebox.unboxI
                 (ConCat.AltCat.addC
                    @ (->)
                    @ GHC.Types.Int
                    (ConCat.Category.$fNumCat->a @ GHC.Types.Int GHC.Num.$fNumInt)
                    (ConCat.Rebox.boxI u#_aM4G, ConCat.Rebox.boxI v#_aM4H)))
              10# 1#
    Cont:   Stop[BoringCtxt] GHC.Prim.Int#

... and comes out of the simplifier like this:

let {
  n1_sM4V :: GHC.Prim.Int#
  [LclId,
   Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False,
           WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 110 0}]
  n1_sM4V
    = case ConCat.AltCat.addC
             @ (->)
             @ GHC.Types.Int
             (ConCat.Category.$fNumCat->a
                @ GHC.Types.Int GHC.Num.$fNumInt)
             (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
      of
      { GHC.Types.I# i#_aM4S ->
      i#_aM4S
      } } in
GHC.Types.I#
  (case ConCat.AltCat.addC
          @ (->)
          @ GHC.Types.Int
          (ConCat.Category.$fNumCat->a @ GHC.Types.Int GHC.Num.$fNumInt)
          (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
   of
   { GHC.Types.I# i#_aM4S ->
   i#_aM4S
   }) } in ...

Ironically, you can see that the simplifier already *has* inlined, just
not elided the (now dead) let binding yet, before the linter gets to it.

I've also attached a shorter source file with the relevant rules that
triggers the linter, albeit with a different message.

Richard Eisenberg, Gabor Greif, and Conal helped me get to this point.
Many thanks to them!

--
Regards,
Mike

{-# LANGUAGE MagicHash #-}
{-# OPTIONS_GHC -frewrite-rules #-}
{-# OPTIONS_GHC -ddump-rule-rewrites #-}
{-# OPTIONS_GHC -ddump-rules #-}
{-# OPTIONS_GHC -dcore-lint #-}
{-# OPTIONS_GHC -ddump-simpl #-}

module ConCatRules where

import GHC.Prim
import GHC.Int

boxI :: Int# -> Int
boxI = I#
{-# INLINE [0] boxI #-}

unboxI :: Int -> Int#
unboxI (I# i#) = i#
-- {-# INLINE [0] unboxI #-}

plus :: Int -> Int -> Int
plus x y = undefined
{-# NOINLINE plus #-}

{-# RULES
"reboxa" forall u# v# . (+#) u# v# = unboxI (plus (boxI u#) (boxI v#))
"reboxb" forall u# . (+#) u# = \v# -> unboxI (plus (boxI u#) (boxI v#))
"reboxc" (+#) = \ u# v# -> unboxI (plus (boxI u#) (boxI v#))
#-}

foo = I# (10# +# 1#)

_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
Reply | Threaded
Open this post in threaded view
|

RE: Simplifier vs. rules problem

GHC - devs mailing list
Interesting. I have opened
https://gitlab.haskell.org/ghc/ghc/-/issues/18677
for this.

Simon

|  -----Original Message-----
|  From: ghc-devs <[hidden email]> On Behalf Of
|  [hidden email]
|  Sent: 11 September 2020 15:24
|  To: [hidden email]
|  Subject: Simplifier vs. rules problem
|  
|  
|  I've been trying to make Conal's ConCat plugin work for polymorphic
|  code, and am running into some problems with the ghc doing that, and
|  I'd
|  very much appreciate help with that.
|  
|  Background: I'm trying to get -dcore-lint to flag when my actual
|  problem
|  happens (has to do with dictionary construction, but it fails earlier
|  with another problem, which I think comes from the simplifier.
|  
|  tl;dr: This transformation seems to me problematic:
|  
|  https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fghc-
|  compiler-
|  notes.readthedocs.io%2Fen%2Flatest%2Fnotes%2Fcompiler%2FsimplCore%2FSim
|  plify.hs.html%23note-case-to-let-
|  transformation&amp;data=02%7C01%7Csimonpj%40microsoft.com%7C377b6cd1b01
|  0436a17c508d8567ca96f%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C6373
|  54441318347955&amp;sdata=vyO%2FXLW3q3xh8gev%2BLLGxRxL4glGMVb61OYcGc7%2B
|  tpo%3D&amp;reserved=0
|  
|  The docs for the transformation say that it makes this replacement:
|  
|  case a +# b of r -> …r… into let r = a +# b in …r…
|  
|  But this creates a let binding with an unlifted binder, which the
|  linter
|  does not like:
|  
|  <no location info>: warning:
|      [RHS of ... :: Int#]
|      The type of this binder is unlifted: ...
|      Binder's type: Int#
|  
|  Arguably, this rule might expect the let to be inlined, but we're
|  seeing
|  that the let stands, and the linter complains.
|  
|  My immediate concern is getting around this problem somehow so I can
|  run
|  the linter on later output of the simplifier.  Is there any way to do
|  this?  I.e. don't stop when the linter complains, somehow massage the
|  rules to work better - see below.  Any help would be much appreciated!
|  (I'm using ghc 8.8.3.)
|  
|  More details:
|  
|  The ConCat code has this rule:
|  
|  "rebox2" [~0] (+#) = \ u# v# -> unboxI (addC (boxI u#, boxI v#))
|  
|  It fires like this:
|  
|  Rule fired
|      Rule: rebox_2
|      Module: (ConCat.Rebox)
|      Before: GHC.Prim.+# ValArg 10# ValArg 1#
|      After:  (\ (u#_aM4G :: GHC.Prim.Int#) (v#_aM4H :: GHC.Prim.Int#) ->
|                 ConCat.Rebox.unboxI
|                   (ConCat.AltCat.addC
|                      @ (->)
|                      @ GHC.Types.Int
|                      (ConCat.Category.$fNumCat->a @ GHC.Types.Int
|  GHC.Num.$fNumInt)
|                      (ConCat.Rebox.boxI u#_aM4G, ConCat.Rebox.boxI
|  v#_aM4H)))
|                10# 1#
|      Cont:   Stop[BoringCtxt] GHC.Prim.Int#
|  
|  ... and comes out of the simplifier like this:
|  
|  let {
|    n1_sM4V :: GHC.Prim.Int#
|    [LclId,
|     Unf=Unf{Src=<vanilla>, TopLvl=False, Value=False, ConLike=False,
|             WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 110
|  0}]
|    n1_sM4V
|      = case ConCat.AltCat.addC
|               @ (->)
|               @ GHC.Types.Int
|               (ConCat.Category.$fNumCat->a
|                  @ GHC.Types.Int GHC.Num.$fNumInt)
|               (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
|        of
|        { GHC.Types.I# i#_aM4S ->
|        i#_aM4S
|        } } in
|  GHC.Types.I#
|    (case ConCat.AltCat.addC
|            @ (->)
|            @ GHC.Types.Int
|            (ConCat.Category.$fNumCat->a @ GHC.Types.Int
|  GHC.Num.$fNumInt)
|            (ConCat.Rebox.boxI 10#, ConCat.Rebox.boxI 1#)
|     of
|     { GHC.Types.I# i#_aM4S ->
|     i#_aM4S
|     }) } in ...
|  
|  Ironically, you can see that the simplifier already *has* inlined, just
|  not elided the (now dead) let binding yet, before the linter gets to
|  it.
|  
|  I've also attached a shorter source file with the relevant rules that
|  triggers the linter, albeit with a different message.
|  
|  Richard Eisenberg, Gabor Greif, and Conal helped me get to this point.
|  Many thanks to them!
|  
|  --
|  Regards,
|  Mike
_______________________________________________
ghc-devs mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs