Sebastian Graf pushed to branch wip/sg/enter-taggable-invariant at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/StgToCmm/Expr.hs
    ... ... @@ -35,7 +35,9 @@ import GHC.Cmm.Graph
    35 35
     import GHC.Cmm.BlockId
    
    36 36
     import GHC.Cmm hiding ( succ )
    
    37 37
     import GHC.Cmm.Info
    
    38
    -import GHC.Cmm.Utils ( cmmTagMask, mkWordCLit, cmmLoadGCWord )
    
    38
    +import GHC.Cmm.Utils ( cmmTagMask, mkWordCLit )
    
    39
    +import GHC.Cmm.CLabel ( mkCmmCodeLabel )
    
    40
    +import GHC.Unit ( rtsUnitId )
    
    39 41
     import GHC.Platform.Tag ( mAX_PTR_TAG )
    
    40 42
     import GHC.Core
    
    41 43
     import GHC.Core.DataCon
    
    ... ... @@ -1190,32 +1192,17 @@ emitEnter fun = do
    1190 1192
       ; adjustHpBackwards
    
    1191 1193
       ; sequel      <- getSequel
    
    1192 1194
       ; updfr_off   <- getUpdFrameOff
    
    1193
    -  ; align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig
    
    1194 1195
       ; case sequel of
    
    1195
    -      -- For a return we test the tag and, if the value is already tagged
    
    1196
    -      -- (hence evaluated), return it directly rather than entering it. This
    
    1197
    -      -- upholds the invariant that the entry code of a taggable normal form is
    
    1198
    -      -- never reached: only an untagged closure is entered. The tag test costs
    
    1199
    -      -- a branch on every tail enter, but a tagged value reaching here is the
    
    1200
    -      -- common case.
    
    1196
    +      -- For a return we evaluate through stg_enter_data, the specialisation
    
    1197
    +      -- of stg_ap_0_fast to values whose type rules out functions
    
    1198
    +      -- (getCallMethod selects EnterIt only for those): it returns a tagged
    
    1199
    +      -- (hence evaluated) value directly and enters an untagged closure, so
    
    1200
    +      -- the entry code of a taggable normal form is never reached and the
    
    1201
    +      -- tail enter costs a single jump in the generated code.
    
    1201 1202
           Return -> do
    
    1202
    -        { fun_tmp <- assignTemp fun
    
    1203
    -        ; let funR     = CmmReg (CmmLocal fun_tmp)
    
    1204
    -              entry    = entryCode platform
    
    1205
    -                       $ closureInfoPtr platform align_check
    
    1206
    -                       $ CmmReg (nodeReg platform)
    
    1207
    -              ret_addr = entryCode platform
    
    1208
    -                       $ cmmLoadGCWord platform (CmmStackSlot Old updfr_off)
    
    1209
    -        ; lenter <- newBlockId
    
    1210
    -        ; lret   <- newBlockId
    
    1211
    -        ; tscope <- getTickScope
    
    1212
    -        ; emit $
    
    1213
    -            mkCbranch (cmmIsTagged platform funR) lret lenter Nothing <*>
    
    1214
    -            outOfLine lenter
    
    1215
    -              ( mkJump profile NativeNodeCall entry [cmmUntag platform funR] updfr_off
    
    1216
    -              , tscope ) <*>
    
    1217
    -            mkLabel lret tscope <*>
    
    1218
    -            mkReturn profile ret_addr [funR] updfr_off
    
    1203
    +        { let enter_data = CmmLit (CmmLabel
    
    1204
    +                             (mkCmmCodeLabel rtsUnitId (fsLit "stg_enter_data")))
    
    1205
    +        ; emit $ mkJump profile NativeNodeCall enter_data [fun] updfr_off
    
    1219 1206
             ; return AssignedDirectly
    
    1220 1207
             }
    
    1221 1208
     
    

  • rts/Apply.cmm
    ... ... @@ -54,6 +54,25 @@ import CLOSURE stg_restore_cccs_eval_info;
    54 54
      * everything being returned is guaranteed evaluated, so it would be a no-op.
    
    55 55
      */
    
    56 56
     
    
    57
    +/* -----------------------------------------------------------------------------
    
    58
    +   Evaluate a value whose type rules out functions.
    
    59
    +
    
    60
    +   A specialisation of stg_ap_0_fast (below) to closures that are a
    
    61
    +   thunk, a constructor, or an indirection to one: the FUN/PAP/BCO arms
    
    62
    +   of the generic evaluation are unreachable, and an indirection's own
    
    63
    +   entry code performs the following, so evaluation reduces to the tag
    
    64
    +   test and an entry jump. The code generator jumps here to evaluate in
    
    65
    +   tail position; see emitEnter in GHC.StgToCmm.Expr.
    
    66
    +   -------------------------------------------------------------------------- */
    
    67
    +
    
    68
    +stg_enter_data ( P_ x )
    
    69
    +{
    
    70
    +    if (GETTAG(x) != 0) {
    
    71
    +        return (x);
    
    72
    +    }
    
    73
    +    jump %GET_ENTRY(x) (x);
    
    74
    +}
    
    75
    +
    
    57 76
     STRING(stg_ap_0_ret_str,"stg_ap_0_ret... ")
    
    58 77
     
    
    59 78
     stg_ap_0_fast ( P_ fun )
    

  • rts/RtsSymbols.c
    ... ... @@ -848,6 +848,7 @@ extern char **environ;
    848 848
           SymI_HasDataProto(stg_ap_ppppp_info)                                  \
    
    849 849
           SymI_HasDataProto(stg_ap_pppppp_info)                                 \
    
    850 850
           SymI_HasDataProto(stg_ap_0_fast)                                      \
    
    851
    +      SymI_HasDataProto(stg_enter_data)                                     \
    
    851 852
           SymI_HasDataProto(stg_ap_v_fast)                                      \
    
    852 853
           SymI_HasDataProto(stg_ap_f_fast)                                      \
    
    853 854
           SymI_HasDataProto(stg_ap_d_fast)                                      \
    

  • rts/include/stg/MiscClosures.h
    ... ... @@ -302,6 +302,7 @@ RTS_RET(stg_ap_ppppp);
    302 302
     RTS_RET(stg_ap_pppppp);
    
    303 303
     
    
    304 304
     RTS_FUN_DECL(stg_ap_0_fast);
    
    305
    +RTS_FUN_DECL(stg_enter_data);
    
    305 306
     RTS_FUN_DECL(stg_ap_v_fast);
    
    306 307
     RTS_FUN_DECL(stg_ap_f_fast);
    
    307 308
     RTS_FUN_DECL(stg_ap_d_fast);