| ... |
... |
@@ -3218,6 +3218,35 @@ rebuildCase, reallyRebuildCase |
|
3218
|
3218
|
-> SimplCont
|
|
3219
|
3219
|
-> SimplM (SimplFloats, OutExpr)
|
|
3220
|
3220
|
|
|
|
3221
|
+--------------------------------------------------
|
|
|
3222
|
+-- 0. ANF-ise a manifest-value seq# argument
|
|
|
3223
|
+--------------------------------------------------
|
|
|
3224
|
+
|
|
|
3225
|
+rebuildCase (saf,env) scrut case_bndr alts@[Alt _ [_token, res] rhs] cont
|
|
|
3226
|
+ -- ANF-ise `case seq# (Con e1 .. en) s of (# s', r #) -> case r of ...`
|
|
|
3227
|
+ -- to `let a1 = e1 .. in case seq# (Con a1 .. an) s of ...`, so that
|
|
|
3228
|
+ -- simplAlt can give `r` an *expandable* unfolding `Con a1 .. an` and
|
|
|
3229
|
+ -- case-of-known-constructor can see through the seq#.
|
|
|
3230
|
+ -- Guarded on `r` being scrutinised immediately, which guarantees that the
|
|
|
3231
|
+ -- unfolding pays off; otherwise the let-floats would just be inlined back
|
|
|
3232
|
+ -- on the next iteration. See (SEQ5) in Note [seq# magic] in GHC.Types.Id.Make
|
|
|
3233
|
+ | (Var f, [ty_a, ty_s, arg, tok]) <- collectArgs scrut
|
|
|
3234
|
+ , f `hasKey` seqHashKey
|
|
|
3235
|
+ , scrutinises_res rhs
|
|
|
3236
|
+ , exprIsManifestValue arg
|
|
|
3237
|
+ , (_, con_args) <- collectArgs arg
|
|
|
3238
|
+ , any (\a -> isValArg a && not (exprIsTrivial a)) con_args
|
|
|
3239
|
+ = do { (anf_floats, arg') <- prepareRhs env NotTopLevel (fsLit "sat") arg
|
|
|
3240
|
+ ; let floats = emptyFloats env `addLetFloats` anf_floats
|
|
|
3241
|
+ env' = env `setInScopeFromF` floats
|
|
|
3242
|
+ scrut' = Var f `mkApps` [ty_a, ty_s, arg', tok]
|
|
|
3243
|
+ ; (floats2, expr') <- rebuildCase (saf,env') scrut' case_bndr alts cont
|
|
|
3244
|
+ ; return (floats `addFloats` floats2, expr') }
|
|
|
3245
|
+ where
|
|
|
3246
|
+ scrutinises_res (Case (Var v) _ _ _) = v == res
|
|
|
3247
|
+ scrutinises_res (Tick _ e) = scrutinises_res e
|
|
|
3248
|
+ scrutinises_res _ = False
|
|
|
3249
|
+
|
|
3221
|
3250
|
--------------------------------------------------
|
|
3222
|
3251
|
-- 1. Eliminate the case if there's a known constructor
|
|
3223
|
3252
|
--------------------------------------------------
|
| ... |
... |
@@ -3292,7 +3321,21 @@ rebuildCase (saf,env) scrut case_bndr alts@[Alt _ bndrs rhs] cont |
|
3292
|
3321
|
; (floats2, expr') <- simplExprF env' rhs cont
|
|
3293
|
3322
|
; return (floats1 `addFloats` floats2, expr') }
|
|
3294
|
3323
|
|
|
3295
|
|
- -- 2c. Try the seq rules if
|
|
|
3324
|
+ -- 2c. Discard a seq# on a manifest value if its result is dead:
|
|
|
3325
|
+ -- case seq# <manifest-value> s of (# s', _ #) -> rhs ==> rhs[s/s']
|
|
|
3326
|
+ -- See (SEQ5) in Note [seq# magic] in GHC.Types.Id.Make
|
|
|
3327
|
+ | [token_out, res] <- bndrs
|
|
|
3328
|
+ , isDeadBinder res, isDeadBinder case_bndr
|
|
|
3329
|
+ , (Var f, [_ty1, _ty2, arg, Var token_in]) <- collectArgs scrut
|
|
|
3330
|
+ , f `hasKey` seqHashKey
|
|
|
3331
|
+ , exprIsManifestValue arg
|
|
|
3332
|
+ , exprOkToDiscard arg
|
|
|
3333
|
+ = do { tick (CaseElim case_bndr)
|
|
|
3334
|
+ ; (floats1, env') <- simplAuxBind (saf,env) token_out (Var token_in)
|
|
|
3335
|
+ ; (floats2, expr') <- simplExprF env' rhs cont
|
|
|
3336
|
+ ; return (floats1 `addFloats` floats2, expr') }
|
|
|
3337
|
+
|
|
|
3338
|
+ -- 2d. Try the seq rules if
|
|
3296
|
3339
|
-- a) it binds only the case binder
|
|
3297
|
3340
|
-- b) a rule for seq applies
|
|
3298
|
3341
|
-- See Note [User-defined RULES for seq] in GHC.Types.Id.Make
|
| ... |
... |
@@ -3317,6 +3360,24 @@ rebuildCase (saf,env) scrut case_bndr alts cont |
|
3317
|
3360
|
| otherwise
|
|
3318
|
3361
|
= reallyRebuildCase (saf,env) scrut case_bndr alts cont
|
|
3319
|
3362
|
|
|
|
3363
|
+exprIsManifestValue :: OutExpr -> Bool
|
|
|
3364
|
+-- True of expressions that are values no matter what the context:
|
|
|
3365
|
+-- literals, lambdas, and (saturated or partial) constructor applications.
|
|
|
3366
|
+-- Unlike exprIsHNF, never true for a variable that is merely *known* to be
|
|
|
3367
|
+-- evaluated: for the seq#-discarding transformations that use this
|
|
|
3368
|
+-- predicate, such a variable carries a dependency on its binding site that
|
|
|
3369
|
+-- must not be lost. See (SEQ5) in Note [seq# magic] in GHC.Types.Id.Make.
|
|
|
3370
|
+exprIsManifestValue e = go e
|
|
|
3371
|
+ where
|
|
|
3372
|
+ go (Cast e _) = go e
|
|
|
3373
|
+ go (Tick t e) = not (tickishCounts t) && go e
|
|
|
3374
|
+ go (Lit _) = True
|
|
|
3375
|
+ go (Lam b e) = isRuntimeVar b || go e
|
|
|
3376
|
+ go (Var f) = isDataConWorkId f
|
|
|
3377
|
+ go e@(App {}) | (Var f, _) <- collectArgs e
|
|
|
3378
|
+ = isDataConWorkId f && exprIsHNF e
|
|
|
3379
|
+ go _ = False
|
|
|
3380
|
+
|
|
3320
|
3381
|
doCaseToLet :: OutExpr -- Scrutinee
|
|
3321
|
3382
|
-> InId -- Case binder
|
|
3322
|
3383
|
-> Bool
|
| ... |
... |
@@ -3590,7 +3651,21 @@ simplAlt (saf,env) scrut' _ case_bndr' bndr_swap' cont' (Alt (DataAlt con) vs rh |
|
3590
|
3651
|
con_app = mkConApp2 con inst_tys' vs'
|
|
3591
|
3652
|
env'' = addAltUnfoldings env' case_bndr' bndr_swap' con_app
|
|
3592
|
3653
|
|
|
3593
|
|
- ; rhs' <- simplAltExprC (saf,env'') rhs cont'
|
|
|
3654
|
+ -- If the scrutinee is (seq# <manifest-value> s), record that
|
|
|
3655
|
+ -- value as the unfolding of the result binder, so that
|
|
|
3656
|
+ -- case-of-known-constructor can see through the seq#.
|
|
|
3657
|
+ -- See (SEQ5) in Note [seq# magic] in GHC.Types.Id.Make
|
|
|
3658
|
+ env_seq | Just scr <- scrut'
|
|
|
3659
|
+ , isUnboxedTupleDataCon con
|
|
|
3660
|
+ , [_token, res] <- vs'
|
|
|
3661
|
+ , (Var f, [_ty1, _ty2, arg, _]) <- collectArgs scr
|
|
|
3662
|
+ , f `hasKey` seqHashKey
|
|
|
3663
|
+ , exprIsManifestValue arg
|
|
|
3664
|
+ = addBinderUnfolding env'' res $
|
|
|
3665
|
+ mkSimpleUnfolding (seUnfoldingOpts env) arg
|
|
|
3666
|
+ | otherwise = env''
|
|
|
3667
|
+
|
|
|
3668
|
+ ; rhs' <- simplAltExprC (saf,env_seq) rhs cont'
|
|
3594
|
3669
|
; return (Alt (DataAlt con) vs' rhs') }
|
|
3595
|
3670
|
|
|
3596
|
3671
|
{- Note [Adding evaluatedness info to pattern-bound variables]
|