sheaf pushed to branch wip/andreask/ticked_joins at Glasgow Haskell Compiler / GHC
Commits:
-
8b8e2154
by sheaf at 2026-01-10T11:31:45+01:00
8 changed files:
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Types/Basic.hs
Changes:
| ... | ... | @@ -672,7 +672,7 @@ lintRhs :: Id -> CoreExpr -> LintM (OutType, UsageEnv) |
| 672 | 672 | lintRhs bndr rhs
|
| 673 | 673 | | JoinPoint arity <- idJoinPointHood bndr
|
| 674 | 674 | = lintJoinLams arity (Just bndr) rhs
|
| 675 | - | AlwaysTailCalled arity <- tailCallInfo (idOccInfo bndr)
|
|
| 675 | + | AlwaysTailCalled arity _ <- tailCallInfo (idOccInfo bndr)
|
|
| 676 | 676 | = lintJoinLams arity Nothing rhs
|
| 677 | 677 | |
| 678 | 678 | -- Allow applications of the data constructor @StaticPtr@ at the top
|
| ... | ... | @@ -2585,7 +2585,13 @@ But it is not necessary to gather CoVars from the types of other binders. |
| 2585 | 2585 | occAnal env (Tick tickish body)
|
| 2586 | 2586 | = WUD usage' (Tick tickish body')
|
| 2587 | 2587 | where
|
| 2588 | - WUD usage body' = occAnal env body
|
|
| 2588 | + WUD usage body' = occAnal env' body
|
|
| 2589 | + |
|
| 2590 | + env' = case tickish of
|
|
| 2591 | + -- Set that we are inside a profiling tick
|
|
| 2592 | + -- SLD TODO: explain why we need this info
|
|
| 2593 | + ProfNote {} -> setInProfTick env
|
|
| 2594 | + _ -> env
|
|
| 2589 | 2595 | |
| 2590 | 2596 | usage'
|
| 2591 | 2597 | | tickishCanScopeJoin tickish
|
| ... | ... | @@ -2809,6 +2815,13 @@ occAnalApp env (fun, args, ticks) |
| 2809 | 2815 | in WUD (markAllNonTail (fun_uds `andUDs` args_uds)) app_out
|
| 2810 | 2816 | |
| 2811 | 2817 | where
|
| 2818 | + -- SLD TODO
|
|
| 2819 | + -- !_ = pprTrace "occAnalApp fallback: marking all non-tail"
|
|
| 2820 | + -- ( vcat [ text "fun:" <+> ppr fun
|
|
| 2821 | + -- , text "args:" <+> ppr args
|
|
| 2822 | + -- , text "ticks:" <+> ppr ticks
|
|
| 2823 | + -- ])
|
|
| 2824 | + -- ()
|
|
| 2812 | 2825 | !(WUD args_uds app') = occAnalArgs env fun' args []
|
| 2813 | 2826 | !(WUD fun_uds fun') = occAnal (addAppCtxt env args) fun
|
| 2814 | 2827 | -- The addAppCtxt is a bit cunning. One iteration of the simplifier
|
| ... | ... | @@ -2929,6 +2942,7 @@ scrutinised y). |
| 2929 | 2942 | |
| 2930 | 2943 | data OccEnv
|
| 2931 | 2944 | = OccEnv { occ_encl :: !OccEncl -- Enclosing context information
|
| 2945 | + , occ_prof_ticks :: !Int
|
|
| 2932 | 2946 | , occ_one_shots :: !OneShots -- See Note [OneShots]
|
| 2933 | 2947 | , occ_unf_act :: Id -> Bool -- Which Id unfoldings are active
|
| 2934 | 2948 | , occ_rule_act :: ActivationGhc -> Bool -- Which rules are active
|
| ... | ... | @@ -2994,6 +3008,7 @@ type OneShots = [OneShotInfo] |
| 2994 | 3008 | initOccEnv :: OccEnv
|
| 2995 | 3009 | initOccEnv
|
| 2996 | 3010 | = OccEnv { occ_encl = OccVanilla
|
| 3011 | + , occ_prof_ticks = 0
|
|
| 2997 | 3012 | , occ_one_shots = []
|
| 2998 | 3013 | |
| 2999 | 3014 | -- To be conservative, we say that all
|
| ... | ... | @@ -3072,6 +3087,9 @@ setTailCtxt !env = env { occ_encl = OccVanilla } |
| 3072 | 3087 | -- Preserve occ_one_shots, occ_join points
|
| 3073 | 3088 | -- Do not use OccRhs for the RHS of a join point (which is a tail ctxt):
|
| 3074 | 3089 | |
| 3090 | +setInProfTick :: OccEnv -> OccEnv
|
|
| 3091 | +setInProfTick !env = env { occ_prof_ticks = 1 + occ_prof_ticks env }
|
|
| 3092 | + |
|
| 3075 | 3093 | mkRhsOccEnv :: OccEnv -> RecFlag -> OccEncl -> JoinPointHood -> Id -> CoreExpr -> OccEnv
|
| 3076 | 3094 | -- See Note [The OccEnv for a right hand side]
|
| 3077 | 3095 | -- For a join point:
|
| ... | ... | @@ -3813,7 +3831,7 @@ mkOneOcc !env id int_cxt arity |
| 3813 | 3831 | where
|
| 3814 | 3832 | occ = OneOccL { lo_n_br = 1
|
| 3815 | 3833 | , lo_int_cxt = int_cxt
|
| 3816 | - , lo_tail = AlwaysTailCalled arity }
|
|
| 3834 | + , lo_tail = AlwaysTailCalled arity (occ_prof_ticks env) }
|
|
| 3817 | 3835 | |
| 3818 | 3836 | -- Add several occurrences, assumed not to be tail calls
|
| 3819 | 3837 | add_many_occ :: Var -> OccInfoEnv -> OccInfoEnv
|
| ... | ... | @@ -3866,13 +3884,20 @@ delBndrsFromUDs bndrs (UD { ud_env = env, ud_z_many = z_many |
| 3866 | 3884 | , ud_z_tail = z_tail `delVarEnvList` bndrs }
|
| 3867 | 3885 | |
| 3868 | 3886 | markAllMany, markAllInsideLam, markAllNonTail, markAllManyNonTail
|
| 3869 | - :: UsageDetails -> UsageDetails
|
|
| 3887 | + :: HasDebugCallStack => UsageDetails -> UsageDetails
|
|
| 3870 | 3888 | markAllMany ud@(UD { ud_env = env }) = ud { ud_z_many = env }
|
| 3871 | 3889 | markAllInsideLam ud@(UD { ud_env = env }) = ud { ud_z_in_lam = env }
|
| 3872 | -markAllNonTail ud@(UD { ud_env = env }) = ud { ud_z_tail = env }
|
|
| 3873 | 3890 | markAllManyNonTail = markAllMany . markAllNonTail -- effectively sets to noOccInfo
|
| 3874 | 3891 | |
| 3875 | -markAllInsideLamIf, markAllNonTailIf :: Bool -> UsageDetails -> UsageDetails
|
|
| 3892 | +markAllNonTail ud@(UD { ud_env = env }) =
|
|
| 3893 | + if isNullUFM env
|
|
| 3894 | + then
|
|
| 3895 | + ud { ud_z_tail = env }
|
|
| 3896 | + else
|
|
| 3897 | + -- SLD TODO pprTrace "markAllNonTail" ( text "zapping:" <+> ppr env $$ callStackDoc ) $
|
|
| 3898 | + ud { ud_z_tail = env }
|
|
| 3899 | + |
|
| 3900 | +markAllInsideLamIf, markAllNonTailIf :: HasDebugCallStack => Bool -> UsageDetails -> UsageDetails
|
|
| 3876 | 3901 | |
| 3877 | 3902 | markAllInsideLamIf True ud = markAllInsideLam ud
|
| 3878 | 3903 | markAllInsideLamIf False ud = ud
|
| ... | ... | @@ -3969,7 +3994,7 @@ adjustNonRecRhs mb_join_arity (WTUD (TUD rhs_ja uds) rhs) |
| 3969 | 3994 | where
|
| 3970 | 3995 | exact_join = mb_join_arity == JoinPoint rhs_ja
|
| 3971 | 3996 | |
| 3972 | -adjustTailUsage :: Bool -- True <=> Exactly-matching join point; don't do markNonTail
|
|
| 3997 | +adjustTailUsage :: HasDebugCallStack => Bool -- True <=> Exactly-matching join point; don't do markNonTail
|
|
| 3973 | 3998 | -> CoreExpr -- Rhs usage, AFTER occAnalLamTail
|
| 3974 | 3999 | -> UsageDetails
|
| 3975 | 4000 | -> UsageDetails
|
| ... | ... | @@ -3981,7 +4006,7 @@ adjustTailUsage exact_join rhs uds |
| 3981 | 4006 | where
|
| 3982 | 4007 | one_shot = isOneShotFun rhs
|
| 3983 | 4008 | |
| 3984 | -adjustTailArity :: JoinPointHood -> TailUsageDetails -> UsageDetails
|
|
| 4009 | +adjustTailArity :: HasDebugCallStack => JoinPointHood -> TailUsageDetails -> UsageDetails
|
|
| 3985 | 4010 | adjustTailArity mb_rhs_ja (TUD ja usage)
|
| 3986 | 4011 | = markAllNonTailIf (mb_rhs_ja /= JoinPoint ja) usage
|
| 3987 | 4012 | |
| ... | ... | @@ -4015,7 +4040,7 @@ tagNonRecBinder :: TopLevelFlag -- At top level? |
| 4015 | 4040 | -- Precondition: OccInfo is not IAmDead
|
| 4016 | 4041 | tagNonRecBinder lvl occ bndr
|
| 4017 | 4042 | | okForJoinPoint lvl bndr tail_call_info
|
| 4018 | - , AlwaysTailCalled ar <- tail_call_info
|
|
| 4043 | + , AlwaysTailCalled ar _ <- tail_call_info
|
|
| 4019 | 4044 | = (setBinderOcc occ bndr, JoinPoint ar)
|
| 4020 | 4045 | | otherwise
|
| 4021 | 4046 | = (setBinderOcc zapped_occ bndr, NotJoinPoint)
|
| ... | ... | @@ -4102,7 +4127,7 @@ okForJoinPoint lvl bndr tail_call_info |
| 4102 | 4127 | = False
|
| 4103 | 4128 | where
|
| 4104 | 4129 | valid_join | NotTopLevel <- lvl
|
| 4105 | - , AlwaysTailCalled arity <- tail_call_info
|
|
| 4130 | + , AlwaysTailCalled arity _ <- tail_call_info
|
|
| 4106 | 4131 | |
| 4107 | 4132 | , -- Invariant 1 as applied to LHSes of rules
|
| 4108 | 4133 | all (ok_rule arity) (idCoreRules bndr)
|
| ... | ... | @@ -4120,8 +4145,8 @@ okForJoinPoint lvl bndr tail_call_info |
| 4120 | 4145 | lost_join | JoinPoint ja <- idJoinPointHood bndr
|
| 4121 | 4146 | = not valid_join ||
|
| 4122 | 4147 | (case tail_call_info of -- Valid join but arity differs
|
| 4123 | - AlwaysTailCalled ja' -> ja /= ja'
|
|
| 4124 | - _ -> False)
|
|
| 4148 | + AlwaysTailCalled ja' _ -> ja /= ja'
|
|
| 4149 | + _ -> False)
|
|
| 4125 | 4150 | | otherwise = False
|
| 4126 | 4151 | |
| 4127 | 4152 | ok_rule _ BuiltinRule{} = False -- only possible with plugin shenanigans
|
| ... | ... | @@ -4143,7 +4168,7 @@ okForJoinPoint lvl bndr tail_call_info |
| 4143 | 4168 | , text "tc:" <+> ppr tail_call_info
|
| 4144 | 4169 | , text "rules:" <+> ppr (idCoreRules bndr)
|
| 4145 | 4170 | , case tail_call_info of
|
| 4146 | - AlwaysTailCalled arity ->
|
|
| 4171 | + AlwaysTailCalled arity _ ->
|
|
| 4147 | 4172 | vcat [ text "ok_unf:" <+> ppr (ok_unfolding arity (realIdUnfolding bndr))
|
| 4148 | 4173 | , text "ok_type:" <+> ppr (isValidJoinPointType arity (idType bndr)) ]
|
| 4149 | 4174 | _ -> empty ]
|
| ... | ... | @@ -4206,6 +4231,6 @@ orLocalOcc (OneOccL { lo_n_br = nbr1, lo_int_cxt = int_cxt1, lo_tail = tci1 }) |
| 4206 | 4231 | orLocalOcc occ1 occ2 = andLocalOcc occ1 occ2
|
| 4207 | 4232 | |
| 4208 | 4233 | andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
|
| 4209 | -andTailCallInfo info@(AlwaysTailCalled arity1) (AlwaysTailCalled arity2)
|
|
| 4210 | - | arity1 == arity2 = info
|
|
| 4234 | +andTailCallInfo (AlwaysTailCalled arity1 p1) (AlwaysTailCalled arity2 p2)
|
|
| 4235 | + | arity1 == arity2 = AlwaysTailCalled arity1 (max p1 p2)
|
|
| 4211 | 4236 | andTailCallInfo _ _ = NoTailCallInfo |
| ... | ... | @@ -201,6 +201,8 @@ data SimplEnv |
| 201 | 201 | |
| 202 | 202 | , seCaseDepth :: !Int -- Depth of multi-branch case alternatives
|
| 203 | 203 | |
| 204 | + , seProfTicks :: !Int -- SLD TODO
|
|
| 205 | + |
|
| 204 | 206 | , seInlineDepth :: !Int -- 0 initially, 1 when we inline an already-simplified
|
| 205 | 207 | -- unfolding, and simplify again; and so on
|
| 206 | 208 | -- See Note [Inline depth]
|
| ... | ... | @@ -588,6 +590,7 @@ mkSimplEnv mode fam_envs |
| 588 | 590 | , seIdSubst = emptyVarEnv
|
| 589 | 591 | , seRecIds = emptyUnVarSet
|
| 590 | 592 | , seCaseDepth = 0
|
| 593 | + , seProfTicks = 0
|
|
| 591 | 594 | , seInlineDepth = 0 }
|
| 592 | 595 | -- The top level "enclosing CC" is "SUBSUMED".
|
| 593 | 596 |
| ... | ... | @@ -39,7 +39,7 @@ import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe |
| 39 | 39 | , pushCoTyArg, pushCoValArg, exprIsDeadEnd
|
| 40 | 40 | , typeArity, arityTypeArity, etaExpandAT )
|
| 41 | 41 | import GHC.Core.SimpleOpt ( exprIsConApp_maybe, joinPointBinding_maybe, joinPointBindings_maybe )
|
| 42 | -import GHC.Core.FVs ( mkRuleInfo {- exprsFreeIds -} )
|
|
| 42 | +import GHC.Core.FVs ( mkRuleInfo )
|
|
| 43 | 43 | import GHC.Core.Rules ( lookupRule, getRules )
|
| 44 | 44 | import GHC.Core.Multiplicity
|
| 45 | 45 | |
| ... | ... | @@ -57,10 +57,11 @@ import GHC.Types.Unique ( hasKey ) |
| 57 | 57 | import GHC.Types.Basic
|
| 58 | 58 | import GHC.Types.Tickish
|
| 59 | 59 | import GHC.Types.Var ( isTyCoVar )
|
| 60 | + |
|
| 60 | 61 | import GHC.Builtin.Types.Prim( realWorldStatePrimTy )
|
| 61 | 62 | import GHC.Builtin.Names( runRWKey, seqHashKey )
|
| 62 | 63 | |
| 63 | -import GHC.Data.Maybe ( isNothing, orElse, mapMaybe )
|
|
| 64 | +import GHC.Data.Maybe ( isNothing, orElse, fromMaybe, mapMaybe )
|
|
| 64 | 65 | import GHC.Data.FastString
|
| 65 | 66 | import GHC.Unit.Module ( moduleName )
|
| 66 | 67 | import GHC.Utils.Outputable
|
| ... | ... | @@ -1442,7 +1443,10 @@ simplTick env tickish expr cont |
| 1442 | 1443 | |
| 1443 | 1444 | no_floating_past_tick =
|
| 1444 | 1445 | do { let (inc,outc) = splitCont cont
|
| 1445 | - ; (floats, expr1) <- simplExprF env expr inc
|
|
| 1446 | + env' = case tickish of
|
|
| 1447 | + ProfNote {} -> env { seProfTicks = seProfTicks env + 1 }
|
|
| 1448 | + _ -> env
|
|
| 1449 | + ; (floats, expr1) <- simplExprF env' expr inc
|
|
| 1446 | 1450 | ; let expr2 = wrapFloats floats expr1
|
| 1447 | 1451 | tickish' = simplTickish env tickish
|
| 1448 | 1452 | ; rebuild env (mkTick tickish' expr2) outc
|
| ... | ... | @@ -2051,8 +2055,8 @@ simplNonRecJoinPoint :: SimplEnv -> InId -> InExpr |
| 2051 | 2055 | -> InExpr -> SimplCont
|
| 2052 | 2056 | -> SimplM (SimplFloats, OutExpr)
|
| 2053 | 2057 | simplNonRecJoinPoint env bndr rhs body cont
|
| 2054 | - = assert (isJoinId bndr ) $
|
|
| 2055 | - wrapJoinCont env cont $ \ env cont ->
|
|
| 2058 | + = assert (isJoinId bndr) $
|
|
| 2059 | + wrapJoinCont do_case_case env cont $ \ env cont ->
|
|
| 2056 | 2060 | do { -- We push join_cont into the join RHS and the body;
|
| 2057 | 2061 | -- and wrap wrap_cont around the whole thing
|
| 2058 | 2062 | ; let mult = contHoleScaling cont
|
| ... | ... | @@ -2062,14 +2066,19 @@ simplNonRecJoinPoint env bndr rhs body cont |
| 2062 | 2066 | ; (floats1, env3) <- simplJoinBind NonRecursive cont (bndr,env) (bndr2,env2) (rhs,env)
|
| 2063 | 2067 | ; (floats2, body') <- simplExprF env3 body cont
|
| 2064 | 2068 | ; return (floats1 `addFloats` floats2, body') }
|
| 2069 | + where
|
|
| 2070 | + do_case_case
|
|
| 2071 | + | Just occMaxProfTicks <- occursUnderProfTick (idOccInfo bndr)
|
|
| 2072 | + , occMaxProfTicks > seProfTicks env
|
|
| 2073 | + = False
|
|
| 2074 | + | otherwise
|
|
| 2075 | + = seCaseCase env
|
|
| 2065 | 2076 | |
| 2066 | - |
|
| 2067 | -------------------
|
|
| 2068 | 2077 | simplRecJoinPoint :: SimplEnv -> [(InId, InExpr)]
|
| 2069 | 2078 | -> InExpr -> SimplCont
|
| 2070 | 2079 | -> SimplM (SimplFloats, OutExpr)
|
| 2071 | 2080 | simplRecJoinPoint env pairs body cont
|
| 2072 | - = wrapJoinCont env cont $ \ env cont ->
|
|
| 2081 | + = wrapJoinCont do_case_case env cont $ \ env cont ->
|
|
| 2073 | 2082 | do { let bndrs = map fst pairs
|
| 2074 | 2083 | mult = contHoleScaling cont
|
| 2075 | 2084 | res_ty = contResultType cont
|
| ... | ... | @@ -2079,30 +2088,38 @@ simplRecJoinPoint env pairs body cont |
| 2079 | 2088 | ; (floats1, env2) <- simplRecBind env1 (BC_Join Recursive cont) pairs
|
| 2080 | 2089 | ; (floats2, body') <- simplExprF env2 body cont
|
| 2081 | 2090 | ; return (floats1 `addFloats` floats2, body') }
|
| 2091 | + where
|
|
| 2092 | + do_case_case
|
|
| 2093 | + | any ((seProfTicks env <) . fromMaybe 0 . occursUnderProfTick . idOccInfo . fst) pairs
|
|
| 2094 | + = False
|
|
| 2095 | + | otherwise
|
|
| 2096 | + = seCaseCase env
|
|
| 2082 | 2097 | |
| 2083 | 2098 | --------------------
|
| 2084 | -wrapJoinCont :: SimplEnv -> SimplCont
|
|
| 2099 | +wrapJoinCont :: Bool
|
|
| 2100 | + -> SimplEnv -> SimplCont
|
|
| 2085 | 2101 | -> (SimplEnv -> SimplCont -> SimplM (SimplFloats, OutExpr))
|
| 2086 | 2102 | -> SimplM (SimplFloats, OutExpr)
|
| 2087 | 2103 | -- Deal with making the continuation duplicable if necessary,
|
| 2088 | 2104 | -- and with the no-case-of-case situation.
|
| 2089 | -wrapJoinCont env cont thing_inside
|
|
| 2105 | +wrapJoinCont do_case_case env cont thing_inside
|
|
| 2090 | 2106 | | contIsStop cont -- Common case; no need for fancy footwork
|
| 2091 | 2107 | = thing_inside env cont
|
| 2092 | 2108 | |
| 2093 | - | not (seCaseCase env)
|
|
| 2094 | - -- See Note [Join points with -fno-case-of-case]
|
|
| 2095 | - = do { (floats1, expr1) <- thing_inside env (mkBoringStop (contHoleType cont))
|
|
| 2096 | - ; let (floats2, expr2) = wrapJoinFloatsX floats1 expr1
|
|
| 2097 | - ; (floats3, expr3) <- rebuild (env `setInScopeFromF` floats2) expr2 cont
|
|
| 2098 | - ; return (floats2 `addFloats` floats3, expr3) }
|
|
| 2099 | - |
|
| 2100 | - | otherwise
|
|
| 2101 | - -- Normal case; see Note [Join points and case-of-case]
|
|
| 2109 | + | do_case_case
|
|
| 2110 | + -- Normal situation: do the "case-of-case" transformation.
|
|
| 2111 | + -- See Note [Join points and case-of-case].
|
|
| 2102 | 2112 | = do { (floats1, cont') <- mkDupableCont env cont
|
| 2103 | 2113 | ; (floats2, result) <- thing_inside (env `setInScopeFromF` floats1) cont'
|
| 2104 | 2114 | ; return (floats1 `addFloats` floats2, result) }
|
| 2105 | 2115 | |
| 2116 | + | otherwise
|
|
| 2117 | + -- No "case-of-case" transformation.
|
|
| 2118 | + -- See Note [Join points with -fno-case-of-case].
|
|
| 2119 | + = do { (floats1, expr1) <- thing_inside env (mkBoringStop (contHoleType cont))
|
|
| 2120 | + ; let (floats2, expr2) = wrapJoinFloatsX floats1 expr1
|
|
| 2121 | + ; (floats3, expr3) <- rebuild (env `setInScopeFromF` floats2) expr2 cont
|
|
| 2122 | + ; return (floats2 `addFloats` floats3, expr3) }
|
|
| 2106 | 2123 | |
| 2107 | 2124 | --------------------
|
| 2108 | 2125 | trimJoinCont :: Id -- Used only in error message
|
| ... | ... | @@ -2151,13 +2168,13 @@ evaluation context E): |
| 2151 | 2168 | |
| 2152 | 2169 | As is evident from the example, there are two components to this behavior:
|
| 2153 | 2170 | |
| 2154 | - 1. When entering the RHS of a join point, copy the context inside.
|
|
| 2155 | - 2. When a join point is invoked, discard the outer context.
|
|
| 2171 | + (wrapJoinCont) When entering the RHS of a join point, copy the context inside.
|
|
| 2172 | + (trimJoinCont) When a join point is invoked, discard the outer context.
|
|
| 2156 | 2173 | |
| 2157 | 2174 | We need to be very careful here to remain consistent---neither part is
|
| 2158 | 2175 | optional!
|
| 2159 | 2176 | |
| 2160 | -We need do make the continuation E duplicable (since we are duplicating it)
|
|
| 2177 | +We need to make the continuation E duplicable (since we are duplicating it)
|
|
| 2161 | 2178 | with mkDupableCont.
|
| 2162 | 2179 | |
| 2163 | 2180 | |
| ... | ... | @@ -2184,7 +2201,8 @@ case-of-case we may then end up with this totally bogus result |
| 2184 | 2201 | This would be OK in the language of the paper, but not in GHC: j is no longer
|
| 2185 | 2202 | a join point. We can only do the "push continuation into the RHS of the
|
| 2186 | 2203 | join point j" if we also push the continuation right down to the /jumps/ to
|
| 2187 | -j, so that it can evaporate there. If we are doing case-of-case, we'll get to
|
|
| 2204 | +j, so that it can evaporate there (trimJoinCont). Then, if we are doing
|
|
| 2205 | +case-of-case, we'll get to
|
|
| 2188 | 2206 | |
| 2189 | 2207 | join x = case <j-rhs> of <outer-alts> in
|
| 2190 | 2208 | case y of
|
| ... | ... | @@ -1076,7 +1076,7 @@ joinPointBinding_maybe bndr rhs |
| 1076 | 1076 | | isJoinId bndr
|
| 1077 | 1077 | = Just (bndr, rhs)
|
| 1078 | 1078 | |
| 1079 | - | AlwaysTailCalled join_arity <- tailCallInfo (idOccInfo bndr)
|
|
| 1079 | + | AlwaysTailCalled join_arity _ <- tailCallInfo (idOccInfo bndr)
|
|
| 1080 | 1080 | , (bndrs, body) <- etaExpandToJoinPoint join_arity rhs
|
| 1081 | 1081 | , let str_sig = idDmdSig bndr
|
| 1082 | 1082 | str_arity = count isId bndrs -- Strictness demands are for Ids only
|
| ... | ... | @@ -1977,7 +1977,7 @@ altsAreExhaustive (Alt con1 _ _ : alts) |
| 1977 | 1977 | -- Takes the function we are applying as argument.
|
| 1978 | 1978 | etaExpansionTick :: Id -> GenTickish pass -> Bool
|
| 1979 | 1979 | etaExpansionTick id t
|
| 1980 | - = hasNoBinding id &&
|
|
| 1980 | + = ( hasNoBinding id || isJoinId id ) && -- SLD TODO
|
|
| 1981 | 1981 | ( tickishFloatable t || isProfTick t )
|
| 1982 | 1982 | |
| 1983 | 1983 | {- Note [exprOkForSpeculation and type classes]
|
| ... | ... | @@ -1130,7 +1130,10 @@ cpeApp top_env expr |
| 1130 | 1130 | hd = getIdFromTrivialExpr_maybe e2
|
| 1131 | 1131 | -- Determine number of required arguments. See Note [Ticks and mandatory eta expansion]
|
| 1132 | 1132 | min_arity = case hd of
|
| 1133 | - Just v_hd -> if hasNoBinding v_hd then Just $! (idArity v_hd) else Nothing
|
|
| 1133 | + Just v_hd ->
|
|
| 1134 | + if hasNoBinding v_hd || isJoinId v_hd -- SLD TODO (re-use cantEtaReduceFun?)
|
|
| 1135 | + then Just $! idArity v_hd
|
|
| 1136 | + else Nothing
|
|
| 1134 | 1137 | Nothing -> Nothing
|
| 1135 | 1138 | -- ; pprTraceM "cpe_app:stricts:" (ppr v <+> ppr args $$ ppr stricts $$ ppr (idCbvMarks_maybe v))
|
| 1136 | 1139 | ; (app, floats, unsat_ticks) <- rebuild_app env args e2 emptyFloats stricts min_arity
|
| ... | ... | @@ -70,7 +70,7 @@ module GHC.Types.Basic ( |
| 70 | 70 | BranchCount, oneBranch,
|
| 71 | 71 | InterestingCxt(..),
|
| 72 | 72 | TailCallInfo(..), tailCallInfo, zapOccTailCallInfo,
|
| 73 | - isAlwaysTailCalled,
|
|
| 73 | + isAlwaysTailCalled, occursUnderProfTick,
|
|
| 74 | 74 | |
| 75 | 75 | EP(..),
|
| 76 | 76 | |
| ... | ... | @@ -1150,7 +1150,7 @@ instance Monoid InsideLam where |
| 1150 | 1150 | |
| 1151 | 1151 | -----------------
|
| 1152 | 1152 | data TailCallInfo
|
| 1153 | - = AlwaysTailCalled {-# UNPACK #-} !JoinArity -- See Note [TailCallInfo]
|
|
| 1153 | + = AlwaysTailCalled {-# UNPACK #-} !JoinArity !Int-- See Note [TailCallInfo]
|
|
| 1154 | 1154 | | NoTailCallInfo
|
| 1155 | 1155 | deriving (Eq)
|
| 1156 | 1156 | |
| ... | ... | @@ -1167,9 +1167,15 @@ isAlwaysTailCalled occ |
| 1167 | 1167 | = case tailCallInfo occ of AlwaysTailCalled{} -> True
|
| 1168 | 1168 | NoTailCallInfo -> False
|
| 1169 | 1169 | |
| 1170 | +occursUnderProfTick :: OccInfo -> Maybe Int
|
|
| 1171 | +occursUnderProfTick occ =
|
|
| 1172 | + case tailCallInfo occ of
|
|
| 1173 | + AlwaysTailCalled _ b -> Just b
|
|
| 1174 | + NoTailCallInfo -> Nothing
|
|
| 1175 | + |
|
| 1170 | 1176 | instance Outputable TailCallInfo where
|
| 1171 | - ppr (AlwaysTailCalled ar) = sep [ text "Tail", int ar ]
|
|
| 1172 | - ppr _ = empty
|
|
| 1177 | + ppr (AlwaysTailCalled ar b) = sep [ text "Tail", brackets (int b), int ar ]
|
|
| 1178 | + ppr _ = text "NoTailCallInfo" --empty
|
|
| 1173 | 1179 | |
| 1174 | 1180 | -----------------
|
| 1175 | 1181 | strongLoopBreaker, weakLoopBreaker :: OccInfo
|
| ... | ... | @@ -1217,7 +1223,8 @@ instance Outputable OccInfo where |
| 1217 | 1223 | pp_tail = pprShortTailCallInfo tail_info
|
| 1218 | 1224 | |
| 1219 | 1225 | pprShortTailCallInfo :: TailCallInfo -> SDoc
|
| 1220 | -pprShortTailCallInfo (AlwaysTailCalled ar) = char 'T' <> brackets (int ar)
|
|
| 1226 | +pprShortTailCallInfo (AlwaysTailCalled ar p)
|
|
| 1227 | + = char 'T' <> (brackets (text "P" <+> int p)) <> brackets (int ar)
|
|
| 1221 | 1228 | pprShortTailCallInfo NoTailCallInfo = empty
|
| 1222 | 1229 | |
| 1223 | 1230 | {-
|