Jaro Reinders pushed to branch wip/reduce-type-in-stg at Glasgow Haskell Compiler / GHC

Commits:

10 changed files:

Changes:

  • compiler/GHC/CoreToStg.hs
    ... ... @@ -447,7 +447,7 @@ coreToStgExpr expr@(Lam {})
    447 447
                  fun_ty  = mkLamTypes val_bndrs body_ty
    
    448 448
                            -- This type is a bit ill-formed but it doesn't matter
    
    449 449
                  rhs = StgRhsClosure noExtFieldSilent currentCCS
    
    450
    -                                 ReEntrant val_bndrs body' (MkStgKind (typeKind body_ty))
    
    450
    +                                 ReEntrant val_bndrs body' (typeStgKind body_ty)
    
    451 451
                  tmp_fun = mkSysLocal (fsLit "pap") uniq ManyTy fun_ty
    
    452 452
            ; return (StgLet noExtFieldSilent (StgNonRec tmp_fun rhs) $
    
    453 453
                      StgApp tmp_fun []) }
    
    ... ... @@ -607,7 +607,7 @@ mkStgApp f how_bound core_args stg_args res_ty
    607 607
         f_arity    = stgArity f how_bound
    
    608 608
         n_val_args = length stg_args  -- StgArgs are all value arguments
    
    609 609
         exactly_saturated  = f_arity == n_val_args
    
    610
    -    res_kind = MkStgKind (typeKind res_ty)
    
    610
    +    res_kind = typeStgKind res_ty
    
    611 611
     
    
    612 612
     
    
    613 613
     -- Given Core arguments to an unboxed sum datacon, return the 'PrimRep's
    
    ... ... @@ -751,7 +751,7 @@ coreToMkStgRhs bndr expr = do
    751 751
         let mk_rhs = MkStgRhs
    
    752 752
               { rhs_args = bndrs
    
    753 753
               , rhs_expr = body'
    
    754
    -          , rhs_kind = MkStgKind (typeKind (exprType body))
    
    754
    +          , rhs_kind = typeStgKind (exprType body)
    
    755 755
               , rhs_is_join = isJoinId bndr
    
    756 756
               }
    
    757 757
         pure mk_rhs
    

  • compiler/GHC/Stg/BcPrep.hs
    ... ... @@ -50,7 +50,7 @@ bcPrepRHS con@StgRhsCon{} = pure con
    50 50
     bcPrepExpr :: StgExpr -> BcPrepM StgExpr
    
    51 51
     -- explicitly match all constructors so we get a warning if we miss any
    
    52 52
     bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    
    53
    -  | isLiftedTypeKind tick_kind = do
    
    53
    +  | isLiftedTypeStgKind tick_kind = do
    
    54 54
           id <- newId tick_ty
    
    55 55
           rhs' <- bcPrepExpr rhs
    
    56 56
           let expr' = StgTick bp rhs'
    
    ... ... @@ -59,7 +59,7 @@ bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    59 59
                                                 ReEntrant
    
    60 60
                                                 []
    
    61 61
                                                 expr'
    
    62
    -                                            (MkStgKind tick_kind)
    
    62
    +                                            tick_kind
    
    63 63
                                  )
    
    64 64
               letExp = StgLet noExtFieldSilent bnd (StgApp id [])
    
    65 65
           pure letExp
    
    ... ... @@ -72,10 +72,10 @@ bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)
    72 72
                                                 ReEntrant
    
    73 73
                                                 [voidArgId]
    
    74 74
                                                 expr'
    
    75
    -                                            (MkStgKind tick_kind)
    
    75
    +                                            tick_kind
    
    76 76
                                  )
    
    77 77
           pure $ StgLet noExtFieldSilent bnd (StgApp id [StgVarArg realWorldPrimId])
    
    78
    -  where tick_kind = typeKind tick_ty
    
    78
    +  where tick_kind = typeStgKind tick_ty
    
    79 79
     bcPrepExpr (StgTick tick rhs) =
    
    80 80
       StgTick tick <$> bcPrepExpr rhs
    
    81 81
     bcPrepExpr (StgLet xlet bnds expr) =
    

  • compiler/GHC/Stg/Syntax.hs
    ... ... @@ -14,7 +14,8 @@ generation.
    14 14
     -}
    
    15 15
     
    
    16 16
     module GHC.Stg.Syntax (
    
    17
    -        StgKind(..),
    
    17
    +        StgKind(getStgKind), typeStgKind, stgKindPrimRep, stgKindPrimRep1, 
    
    18
    +        stgKindPrimRepU, isUnboxedTupleStgKind, isLiftedTypeStgKind,
    
    18 19
     
    
    19 20
             StgFArgType(..),
    
    20 21
             collectStgFArgTypes,
    
    ... ... @@ -80,7 +81,13 @@ import GHC.Types.CostCentre ( CostCentreStack )
    80 81
     import GHC.Core     ( AltCon )
    
    81 82
     import GHC.Core.DataCon
    
    82 83
     import GHC.Core.TyCon    ( PrimRep(..), PrimOrVoidRep(..), TyCon )
    
    83
    -import GHC.Core.Type     ( Type, tyConAppTyCon )
    
    84
    +import GHC.Core.Type     
    
    85
    +    ( Type, 
    
    86
    +      tyConAppTyCon, 
    
    87
    +      typeKind, 
    
    88
    +      isUnboxedTupleKind, 
    
    89
    +      kindRep_maybe, 
    
    90
    +      isLiftedRuntimeRep )
    
    84 91
     import GHC.Core.Ppr( {- instances -} )
    
    85 92
     
    
    86 93
     import GHC.Types.ForeignCall ( ForeignCall )
    
    ... ... @@ -88,10 +95,19 @@ import GHC.Types.Id
    88 95
     import GHC.Types.Tickish     ( StgTickish )
    
    89 96
     import GHC.Types.Var.Set
    
    90 97
     import GHC.Types.Literal     ( Literal, literalType )
    
    91
    -import GHC.Types.RepType ( typePrimRep, typePrimRep1, typePrimRepU, typePrimRep_maybe, unwrapType )
    
    98
    +import GHC.Types.RepType 
    
    99
    +    ( typePrimRep, 
    
    100
    +      typePrimRep1, 
    
    101
    +      typePrimRepU, 
    
    102
    +      typePrimRep_maybe, 
    
    103
    +      kindPrimRep,
    
    104
    +      kindPrimRep1,
    
    105
    +      kindPrimRep_maybe,
    
    106
    +      unwrapType )
    
    92 107
     
    
    93 108
     import GHC.Utils.Outputable
    
    94 109
     import GHC.Utils.Panic.Plain
    
    110
    +import GHC.Utils.Panic ( pprPanic )
    
    95 111
     
    
    96 112
     import GHC.Builtin.PrimOps ( PrimOp, PrimCall )
    
    97 113
     
    
    ... ... @@ -112,27 +128,54 @@ import GHC.Builtin.Types.Prim
    112 128
     -- Kind is otherwise equal to.
    
    113 129
     -- See Note [Kinds in STG]
    
    114 130
     newtype StgKind = MkStgKind { getStgKind :: Kind }
    
    131
    +-- getStgKind is only used to do some silly pretty printing in the JS backend.
    
    132
    +
    
    133
    +typeStgKind :: Type -> StgKind
    
    134
    +typeStgKind = MkStgKind . typeKind
    
    135
    +
    
    136
    +stgKindPrimRep1 :: StgKind -> PrimRep
    
    137
    +stgKindPrimRep1 = kindPrimRep1 . getStgKind
    
    138
    +
    
    139
    +stgKindPrimRepU :: StgKind -> PrimOrVoidRep
    
    140
    +stgKindPrimRepU (MkStgKind kind) = case kindPrimRep_maybe kind of
    
    141
    +  Just [] -> VoidRep
    
    142
    +  Just [r] -> NVRep r
    
    143
    +  r -> pprPanic "stgKindPrimRepU" (ppr r)
    
    144
    +
    
    145
    +stgKindPrimRep :: StgKind -> [PrimRep]
    
    146
    +stgKindPrimRep = kindPrimRep . getStgKind
    
    147
    +
    
    148
    +isUnboxedTupleStgKind :: StgKind -> Bool
    
    149
    +isUnboxedTupleStgKind = isUnboxedTupleKind . getStgKind
    
    150
    +
    
    151
    +isLiftedTypeStgKind :: StgKind -> Bool
    
    152
    +isLiftedTypeStgKind (MkStgKind kind)
    
    153
    +  = case kindRep_maybe kind of
    
    154
    +      Just rep -> isLiftedRuntimeRep rep
    
    155
    +      Nothing  -> False
    
    115 156
     
    
    116 157
     {-
    
    117 158
     Note [Kinds in STG]
    
    118 159
     ~~~~~~~~~~~~~~~~~~~
    
    119
    -
    
    120
    -Whereas Core is type-annotated, STG is kind-annotated.
    
    160
    +Whereas Core is well-typed, STG is well-kinded.
    
    121 161
     
    
    122 162
     Just as many different values may have a single type, so many different
    
    123 163
     types may have a single kind. So kinds are a "coarser approximation" to the
    
    124 164
     values being manipulated; and that is what we want in STG.
    
    125 165
     
    
    126
    -There are two reasons for this:
    
    166
    +There are two reasons for wanting a coarser type system:
    
    127 167
     
    
    128 168
     (1) It is easier for third party projects to compile to STG. The type system of
    
    129 169
         another language might not be compatible with GHC's type system. In such a
    
    130 170
         case the kind system is often still compatible because it is so much coarser.
    
    131
    -    Example projects are Jaro Reinders' agda2stg and Csaba Hruska's external-stg.
    
    171
    +    Examples of such projects are:
    
    172
    +    
    
    173
    +    - agda2stg: https://github.com/noughtmare/agda2stg
    
    174
    +    - external-stg-interpreter: https://github.com/grin-compiler/ghc-whole-program-compiler-project/tree/master/external-stg-interpreter
    
    132 175
     
    
    133 176
     (2) It allows for more aggressive optimizations. In STG we may do
    
    134
    -    type-incorrect things that are kind-correct. For example consider
    
    135
    -    the following function:
    
    177
    +    type-incorrect things that are still kind-correct. For example
    
    178
    +    consider the following function:
    
    136 179
     
    
    137 180
           f :: Either a b -> Either a c
    
    138 181
           f = \x -> case x of r
    
    ... ... @@ -146,10 +189,12 @@ There are two reasons for this:
    146 189
                       Left _ -> r        <------------- NB
    
    147 190
                       Right _ -> error "urk"
    
    148 191
     
    
    192
    +    See Note [Case 2: CSEing case binders] for the full details of this 
    
    193
    +    optimization.
    
    194
    +
    
    149 195
         This is not type-safe in Core, but it is kind-safe in STG. So, using
    
    150 196
         the coarser notion of kinds in STG allows us to do more aggressive
    
    151
    -    optimizations. Note, however, that we do not implement any such
    
    152
    -    optimizations yet.
    
    197
    +    optimizations.
    
    153 198
     
    
    154 199
     Note that the kinds do not always accurately reflect the final runtime
    
    155 200
     representation. For example, on the JS backend the kind 'TYPE Int64Rep'
    
    ... ... @@ -813,7 +858,6 @@ to move these around together, notably in StgOpApp and COpStmt.
    813 858
     
    
    814 859
     Note [tagToEnum# in STG]
    
    815 860
     ~~~~~~~~~~~~~~~~~~~~~~~~
    
    816
    -
    
    817 861
     STG is untyped, but 'tagToEnum#' needs type information, so we make it a special
    
    818 862
     STG operation which stores the type constructor information alongside it.
    
    819 863
     
    
    ... ... @@ -833,7 +877,6 @@ To preserve this information we desugar the 'tagToEnum#' primop into a special
    833 877
     'StgTagToEnumOp' which has an extra field to store the type constructor
    
    834 878
     information. This desugaring happens when converting Core to STG, which is the
    
    835 879
     last moment that we still have access to the type information.
    
    836
    -
    
    837 880
     -}
    
    838 881
     
    
    839 882
     data StgOp
    

  • compiler/GHC/Stg/Unarise.hs
    ... ... @@ -889,7 +889,7 @@ castArgRename ops in_arg rhs =
    889 889
         ((op,ty,uq):rest_ops) ->
    
    890 890
           let out_id' = mkCastVar uq ty -- out_name `setIdUnique` uq `setIdType` ty
    
    891 891
               sub_cast = castArgRename rest_ops (StgVarArg out_id')
    
    892
    -      in mkCast in_arg op out_id' (MkStgKind (typeKind ty)) $ sub_cast rhs
    
    892
    +      in mkCast in_arg op out_id' (typeStgKind ty) $ sub_cast rhs
    
    893 893
     
    
    894 894
     -- Construct a case binder used when casting sums, of a given type and unique.
    
    895 895
     mkCastVar :: Unique -> Type -> Id
    
    ... ... @@ -899,7 +899,7 @@ mkCast :: StgArg -> PrimOp -> OutId -> StgKind -> StgExpr -> StgExpr
    899 899
     mkCast arg_in cast_op out_id out_kind in_rhs =
    
    900 900
       let scrut = StgOpApp (StgPrimOp cast_op) [arg_in]
    
    901 901
           alt = GenStgAlt { alt_con = DEFAULT, alt_bndrs = [], alt_rhs = in_rhs}
    
    902
    -      alt_ty = PrimAlt (kindPrimRep1 (getStgKind out_kind))
    
    902
    +      alt_ty = PrimAlt (stgKindPrimRep1 out_kind)
    
    903 903
       in (StgCase scrut out_id alt_ty [alt])
    
    904 904
     
    
    905 905
     -- | Build a unboxed sum term from arguments of an alternative.
    

  • compiler/GHC/StgToByteCode.hs
    ... ... @@ -645,12 +645,6 @@ schemeE d s p (StgCase scrut _ _ []) = schemeE d s p scrut
    645 645
     schemeE d s p (StgCase scrut bndr _ alts)
    
    646 646
        = doCase d s p scrut bndr alts
    
    647 647
     
    
    648
    -stgKindPrimRepU :: StgKind -> PrimOrVoidRep
    
    649
    -stgKindPrimRepU (MkStgKind kind) = case kindPrimRep_maybe kind of
    
    650
    -  Just [] -> VoidRep
    
    651
    -  Just [r] -> NVRep r
    
    652
    -  r -> pprPanic "stgKindPrimRepU" (ppr r)
    
    653
    -
    
    654 648
     {-
    
    655 649
        Ticked Expressions
    
    656 650
        ------------------
    

  • compiler/GHC/StgToCmm/Foreign.hs
    ... ... @@ -72,7 +72,7 @@ cgForeignCall :: ForeignCall -- the op
    72 72
     cgForeignCall (CCall (CCallSpec target cconv safety)) arg_tys stg_args res_kind
    
    73 73
       = do  { cmm_args <- getFCallArgs stg_args arg_tys
    
    74 74
             -- ; traceM $ show cmm_args
    
    75
    -        ; (res_regs, res_hints) <- newUnboxedTupleRegs (getStgKind res_kind)
    
    75
    +        ; (res_regs, res_hints) <- newUnboxedTupleRegs res_kind
    
    76 76
             ; let ((call_args, arg_hints), cmm_target)
    
    77 77
                     = case target of
    
    78 78
                         StaticTarget _ _ ForeignValue ->
    

  • compiler/GHC/StgToCmm/Prim.hs
    ... ... @@ -36,7 +36,6 @@ import GHC.Cmm.Graph
    36 36
     import GHC.Stg.Syntax
    
    37 37
     import GHC.Cmm
    
    38 38
     import GHC.Unit         ( rtsUnit )
    
    39
    -import GHC.Core.Type    ( typeKind )
    
    40 39
     import GHC.Core.TyCon ( isEnumerationTyCon )
    
    41 40
     import GHC.Cmm.CLabel
    
    42 41
     import GHC.Cmm.Info     ( closureInfoPtr )
    
    ... ... @@ -105,7 +104,7 @@ cgOpApp (StgTagToEnumOp tyc) args = do
    105 104
     cmmPrimOpApp :: StgToCmmConfig -> PrimOp -> [CmmExpr] -> FCode ReturnKind
    
    106 105
     cmmPrimOpApp cfg primop cmm_args =
    
    107 106
       let PrimopCmmEmit _inline f = emitPrimOp cfg primop cmm_args
    
    108
    -  in f (MkStgKind (typeKind (primOpResultType primop)))
    
    107
    +  in f (typeStgKind (primOpResultType primop))
    
    109 108
     
    
    110 109
     externalPrimop :: PrimOp -> [CmmExpr] -> PrimopCmmEmit
    
    111 110
     externalPrimop primop args = outOfLinePrimop (callExternalPrimop primop args)
    
    ... ... @@ -1919,7 +1918,7 @@ emitPrimOp cfg primop =
    1919 1918
                       pure [reg]
    
    1920 1919
     
    
    1921 1920
               ReturnsTuple
    
    1922
    -            -> do (regs, _hints) <- newUnboxedTupleRegs (getStgKind res_kind)
    
    1921
    +            -> do (regs, _hints) <- newUnboxedTupleRegs res_kind
    
    1923 1922
                       pure regs
    
    1924 1923
             f res_kind regs
    
    1925 1924
             emitReturn (map (CmmReg . CmmLocal) regs)
    

  • compiler/GHC/StgToCmm/Utils.hs
    ... ... @@ -50,6 +50,7 @@ module GHC.StgToCmm.Utils (
    50 50
     import GHC.Prelude hiding ( head, init, last, tail )
    
    51 51
     
    
    52 52
     import GHC.Platform
    
    53
    +import GHC.Stg.Syntax
    
    53 54
     import GHC.StgToCmm.Monad
    
    54 55
     import GHC.StgToCmm.Closure
    
    55 56
     import GHC.StgToCmm.Lit (mkSimpleLit, newStringCLit)
    
    ... ... @@ -65,7 +66,6 @@ import GHC.StgToCmm.CgUtils
    65 66
     
    
    66 67
     import GHC.Types.ForeignCall
    
    67 68
     import GHC.Types.Id.Info
    
    68
    -import GHC.Core.Type
    
    69 69
     import GHC.Core.TyCon
    
    70 70
     import GHC.Runtime.Heap.Layout
    
    71 71
     import GHC.Unit
    
    ... ... @@ -76,7 +76,6 @@ import GHC.Types.Unique
    76 76
     import GHC.Data.FastString
    
    77 77
     import GHC.Utils.Outputable
    
    78 78
     import GHC.Utils.Panic
    
    79
    -import GHC.Types.RepType
    
    80 79
     import GHC.Types.CostCentre
    
    81 80
     import GHC.Types.IPE
    
    82 81
     
    
    ... ... @@ -320,22 +319,20 @@ assignTemp e = do { platform <- getPlatform
    320 319
                       ; emitAssign (CmmLocal reg) e
    
    321 320
                       ; return reg }
    
    322 321
     
    
    323
    -newUnboxedTupleRegs :: HasDebugCallStack => Kind -> FCode ([LocalReg], [ForeignHint])
    
    322
    +newUnboxedTupleRegs :: HasDebugCallStack => StgKind -> FCode ([LocalReg], [ForeignHint])
    
    324 323
     -- Choose suitable local regs to use for the components
    
    325 324
     -- of an unboxed tuple that we are about to return to
    
    326 325
     -- the Sequel.  If the Sequel is a join point, using the
    
    327 326
     -- regs it wants will save later assignments.
    
    328 327
     newUnboxedTupleRegs res_kind
    
    329
    -  = assert (isUnboxedTupleKind res_kind) $
    
    330
    -    case kindPrimRep_maybe res_kind of
    
    331
    -      Just reps ->
    
    332
    -        do  { platform <- getPlatform
    
    333
    -            ; sequel <- getSequel
    
    334
    -            ; regs <- case sequel of
    
    335
    -                AssignTo regs _ -> regs <$ massert (regs `equalLength` reps)
    
    336
    -                _ -> mapM (newTemp . primRepCmmType platform) reps
    
    337
    -            ; return (regs, map primRepForeignHint reps) }
    
    338
    -      Nothing -> pprPanic "newUnboxedTupleRegs applied to non-unboxed-tuple kind" (ppr res_kind)
    
    328
    +  = assert (isUnboxedTupleStgKind res_kind) $
    
    329
    +    let reps = stgKindPrimRep res_kind
    
    330
    +    in do  { platform <- getPlatform
    
    331
    +           ; sequel <- getSequel
    
    332
    +           ; regs <- case sequel of
    
    333
    +               AssignTo regs _ -> regs <$ massert (regs `equalLength` reps)
    
    334
    +               _ -> mapM (newTemp . primRepCmmType platform) reps
    
    335
    +           ; return (regs, map primRepForeignHint reps) }
    
    339 336
     
    
    340 337
     -------------------------------------------------------------------------
    
    341 338
     --      emitMultiAssign
    

  • compiler/GHC/StgToJS/Expr.hs
    ... ... @@ -366,7 +366,7 @@ resultSize kind = result
    366 366
       where
    
    367 367
         result       = result_reps `zip` result_slots
    
    368 368
         result_slots = fmap (slotCount . primRepSize) result_reps
    
    369
    -    result_reps  = kindPrimRep (getStgKind kind)
    
    369
    +    result_reps  = stgKindPrimRep kind
    
    370 370
     
    
    371 371
     -- | Ensure that the set of identifiers has valid 'RuntimeRep's. This function
    
    372 372
     -- returns a no-op when 'csRuntimeAssert' in 'StgToJSConfig' is False.
    

  • compiler/GHC/StgToJS/Utils.hs
    ... ... @@ -205,9 +205,7 @@ typeJSRep :: HasDebugCallStack => Type -> [JSRep]
    205 205
     typeJSRep t = map primRepToJSRep (typePrimRep t)
    
    206 206
     
    
    207 207
     stgKindJSRep :: HasDebugCallStack => StgKind -> [JSRep]
    
    208
    -stgKindJSRep (MkStgKind k) = case kindPrimRep_maybe k of
    
    209
    -  Just rs -> map primRepToJSRep rs
    
    210
    -  Nothing -> pprPanic "kindJSRep" (ppr k)
    
    208
    +stgKindJSRep = map primRepToJSRep . stgKindPrimRep
    
    211 209
     
    
    212 210
     -- only use if you know it's not an unboxed tuple
    
    213 211
     unaryTypeJSRep :: HasDebugCallStack => UnaryType -> JSRep