Skip to content
  • Simon Peyton Jones's avatar
    Inject implicit bindings before the simplifier (Trac #2070) · 5952ef0d
    Simon Peyton Jones authored
    With constructor unpacking, it's possible for constructors and record
    selectors to have non-trivial code, which should be optimised before
    being fed to the code generator.  Example:
    
      data Foo = Foo { get :: {-# UNPACK #-} !Int }
    
    Then we do not want to get this:
      T2070.get =
        \ (tpl_B1 :: T2070.Foo) ->
        case tpl_B1 of tpl1_B2 { T2070.Foo rb_B4 ->
            let {
              ipv_B3 [Just S] :: GHC.Base.Int
              [Str: DmdType m]
              ipv_B3 = GHC.Base.I# rb_B4
            } in  ipv_B3 }
    
    If this goes through to codegen, we'll generate bad code.  Admittedly,
    this only matters when the selector is used in a curried way (e.g
    map get xs), but nevertheless it's silly.
    
    This patch injects the implicit bindings in SimplCore, before the
    simplifier runs.  That slows the simplifier a little, because it has
    to look at some extra bindings; but it's probably a slight effect.
    If it turns out to matter I suppose we can always inject them later,
    e.g. just before the final simplification.
    
    An unexpected (to me) consequence is that we get some specialisation rules
    for class-method selectors.  E.g. we get a rule
    	RULE  (==) Int dInt = eqInt
    There's no harm in this, but not much benefit either, because the 
    same result will happen when we inline (==) and dInt, but it's perhaps
    more direct.
    
    5952ef0d