sheaf pushed to branch wip/andreask/ticked_joins at Glasgow Haskell Compiler / GHC
Commits:
-
a3ef7ffc
by sheaf at 2026-01-26T23:12:26+01:00
5 changed files:
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Monad.hs
- compiler/GHC/Types/Id/Info.hs
Changes:
| ... | ... | @@ -915,7 +915,7 @@ lintCoreExpr (Lit lit) |
| 915 | 915 | ; return (literalType lit, zeroUE) }
|
| 916 | 916 | |
| 917 | 917 | lintCoreExpr (Cast expr co)
|
| 918 | - = do { (expr_ty, ue) <- markAllJoinsBad (lintCoreExpr expr)
|
|
| 918 | + = do { (expr_ty, ue) <- lintCoreExpr expr -- SLD TODO markAllJoinsBad (lintCoreExpr expr)
|
|
| 919 | 919 | -- markAllJoinsBad: see Note [Join points and casts]
|
| 920 | 920 | |
| 921 | 921 | ; lintCoercion co
|
| ... | ... | @@ -1146,7 +1146,7 @@ checkDeadIdOcc id |
| 1146 | 1146 | ------------------
|
| 1147 | 1147 | lintJoinBndrType :: OutType -- Type of the body
|
| 1148 | 1148 | -> OutId -- Possibly a join Id
|
| 1149 | - -> LintM ()
|
|
| 1149 | + -> LintM ()
|
|
| 1150 | 1150 | -- Checks that the return type of a join Id matches the body
|
| 1151 | 1151 | -- E.g. join j x = rhs in body
|
| 1152 | 1152 | -- The type of 'rhs' must be the same as the type of 'body'
|
| ... | ... | @@ -42,7 +42,7 @@ import GHC.Core.Coercion |
| 42 | 42 | import GHC.Core.Type
|
| 43 | 43 | import GHC.Core.TyCo.FVs ( tyCoVarsOfMCo )
|
| 44 | 44 | |
| 45 | -import GHC.Data.Maybe( orElse )
|
|
| 45 | +import GHC.Data.Maybe( orElse, isNothing )
|
|
| 46 | 46 | import GHC.Data.Graph.Directed ( SCC(..), Node(..)
|
| 47 | 47 | , stronglyConnCompFromEdgedVerticesUniq
|
| 48 | 48 | , stronglyConnCompFromEdgedVerticesUniqR )
|
| ... | ... | @@ -68,6 +68,7 @@ import GHC.Builtin.Names( runRWKey ) |
| 68 | 68 | import GHC.Unit.Module( Module )
|
| 69 | 69 | |
| 70 | 70 | import Data.List (mapAccumL)
|
| 71 | +import qualified Data.List.NonEmpty as NE
|
|
| 71 | 72 | import qualified Data.Semigroup as Semi
|
| 72 | 73 | |
| 73 | 74 | {-
|
| ... | ... | @@ -2299,7 +2300,7 @@ occ_anal_lam_tail env (Cast expr co) |
| 2299 | 2300 | _ -> usage1
|
| 2300 | 2301 | |
| 2301 | 2302 | -- usage3: see Note [Quasi join points] in GHC.Core.Opt.Simplify.Iteration.
|
| 2302 | - usage3 = markAllNonTail usage2 -- SLD TODO
|
|
| 2303 | + usage3 = markAllQuasiTail usage2 -- SLD TODO
|
|
| 2303 | 2304 | |
| 2304 | 2305 | in WUD usage3 (Cast expr' co)
|
| 2305 | 2306 | |
| ... | ... | @@ -2612,7 +2613,7 @@ occAnal env (Cast expr co) |
| 2612 | 2613 | = let (WUD usage expr') = occAnal env expr
|
| 2613 | 2614 | usage1 = addManyOccs usage (coVarsOfCo co)
|
| 2614 | 2615 | -- usage1: see Note [Gather occurrences of coercion variables]
|
| 2615 | - usage2 = markAllNonTail usage1 -- SLD TODO
|
|
| 2616 | + usage2 = markAllQuasiTail usage1 -- SLD TODO
|
|
| 2616 | 2617 | -- usage2: see Note [Quasi join points]
|
| 2617 | 2618 | in WUD usage2 (Cast expr' co)
|
| 2618 | 2619 | |
| ... | ... | @@ -3985,20 +3986,31 @@ adjustNonRecRhs mb_join_arity (WTUD (TUD rhs_ja uds) rhs) |
| 3985 | 3986 | where
|
| 3986 | 3987 | exact_join =
|
| 3987 | 3988 | case mb_join_arity of
|
| 3988 | - Nothing -> False
|
|
| 3989 | - Just ja' -> ja' == rhs_ja
|
|
| 3990 | - |
|
| 3991 | -adjustTailUsage :: Bool -- True <=> Exactly-matching join point; don't do markNonTail
|
|
| 3989 | + Nothing -> Nothing
|
|
| 3990 | + Just ja' ->
|
|
| 3991 | + if ja' == rhs_ja
|
|
| 3992 | + then Just TrueJoinPoint
|
|
| 3993 | + else Nothing
|
|
| 3994 | + |
|
| 3995 | +adjustTailUsage :: HasDebugCallStack
|
|
| 3996 | + => Maybe JoinPointType
|
|
| 3992 | 3997 | -> CoreExpr -- Rhs usage, AFTER occAnalLamTail
|
| 3993 | 3998 | -> UsageDetails
|
| 3994 | 3999 | -> UsageDetails
|
| 3995 | -adjustTailUsage exact_join rhs uds
|
|
| 4000 | +adjustTailUsage mb_join rhs uds
|
|
| 3996 | 4001 | = -- c.f. occAnal (Lam {})
|
| 3997 | 4002 | markAllInsideLamIf (not one_shot) $
|
| 3998 | - markAllNonTailIf (not exact_join) $
|
|
| 4003 | + mb_mark_nontail $
|
|
| 3999 | 4004 | uds
|
| 4000 | 4005 | where
|
| 4001 | - one_shot = isOneShotFun rhs
|
|
| 4006 | + one_shot = isOneShotFun rhs
|
|
| 4007 | + mb_mark_nontail =
|
|
| 4008 | + case mb_join of
|
|
| 4009 | + Nothing -> markAllNonTail
|
|
| 4010 | + Just join_ty ->
|
|
| 4011 | + case join_ty of
|
|
| 4012 | + QuasiJoinPoint -> markAllQuasiTail
|
|
| 4013 | + TrueJoinPoint -> id
|
|
| 4002 | 4014 | |
| 4003 | 4015 | adjustTailArity :: Maybe JoinArity -> TailUsageDetails -> UsageDetails
|
| 4004 | 4016 | adjustTailArity mb_rhs_ja (TUD ja usage) = markAllNonTailIf not_same_arity usage
|
| ... | ... | @@ -4036,11 +4048,8 @@ tagNonRecBinder :: TopLevelFlag -- At top level? |
| 4036 | 4048 | -- No-op on TyVars
|
| 4037 | 4049 | -- Precondition: OccInfo is not IAmDead
|
| 4038 | 4050 | tagNonRecBinder lvl occ bndr
|
| 4039 | - | okForJoinPoint lvl bndr tail_call_info
|
|
| 4040 | - , AlwaysTailCalled
|
|
| 4041 | - { tailCallArity = ar
|
|
| 4042 | - , tailCallJoinPointType = join_ty
|
|
| 4043 | - } <- tail_call_info
|
|
| 4051 | + | Just join_ty <- okForJoinPoint lvl bndr tail_call_info
|
|
| 4052 | + , AlwaysTailCalled { tailCallArity = ar } <- tail_call_info
|
|
| 4044 | 4053 | = (setBinderOcc occ bndr, JoinPoint join_ty ar)
|
| 4045 | 4054 | | otherwise
|
| 4046 | 4055 | = (setBinderOcc zapped_occ bndr, NotJoinPoint)
|
| ... | ... | @@ -4070,7 +4079,7 @@ tagRecBinders lvl body_uds details_s |
| 4070 | 4079 | = assertPpr (rhs_ja == joinRhsArity rhs) (ppr rhs_ja $$ ppr uds $$ ppr rhs) $
|
| 4071 | 4080 | uds
|
| 4072 | 4081 | |
| 4073 | - will_be_joins :: Bool
|
|
| 4082 | + will_be_joins :: Maybe JoinPointType
|
|
| 4074 | 4083 | will_be_joins = decideRecJoinPointHood lvl unadj_uds bndrs
|
| 4075 | 4084 | |
| 4076 | 4085 | -- 2. Adjust usage details of each RHS, taking into account the
|
| ... | ... | @@ -4108,42 +4117,50 @@ setBinderOcc occ_info bndr |
| 4108 | 4117 | --
|
| 4109 | 4118 | -- See Note [Invariants on join points] in "GHC.Core".
|
| 4110 | 4119 | decideRecJoinPointHood :: TopLevelFlag -> UsageDetails
|
| 4111 | - -> [CoreBndr] -> Bool
|
|
| 4112 | -decideRecJoinPointHood lvl usage bndrs
|
|
| 4113 | - = all ok bndrs -- Invariant 3: Either all are join points or none are
|
|
| 4120 | + -> [CoreBndr] -> Maybe JoinPointType
|
|
| 4121 | +decideRecJoinPointHood lvl usage bndrs = do
|
|
| 4122 | + bndrsNE <- NE.nonEmpty bndrs
|
|
| 4123 | + res <- Semi.sconcat <$> traverse ok bndrsNE -- Invariant 3: Either all are join points or none are
|
|
| 4124 | + pprTraceM "decideRecJoinPointHood" $
|
|
| 4125 | + vcat [ text "bndrs:" <+> ppr bndrs
|
|
| 4126 | + , text "res:" <+> ppr res ]
|
|
| 4127 | + return res
|
|
| 4114 | 4128 | where
|
| 4115 | 4129 | ok bndr = okForJoinPoint lvl bndr (lookupTailCallInfo usage bndr)
|
| 4116 | 4130 | |
| 4117 | -okForJoinPoint :: TopLevelFlag -> Id -> TailCallInfo -> Bool
|
|
| 4131 | +okForJoinPoint :: TopLevelFlag -> Id -> TailCallInfo -> Maybe JoinPointType
|
|
| 4118 | 4132 | -- See Note [Invariants on join points]; invariants cited by number below.
|
| 4119 | 4133 | -- Invariant 2 is always satisfiable by the simplifier by eta expansion.
|
| 4120 | 4134 | okForJoinPoint lvl bndr tail_call_info
|
| 4121 | - | isJoinId bndr -- A current join point should still be one!
|
|
| 4135 | + | Just join_ty <- joinId_maybe bndr
|
|
| 4136 | + -- A current join point should still be one!
|
|
| 4122 | 4137 | = warnPprTrace lost_join "Lost join point" lost_join_doc $
|
| 4123 | - True
|
|
| 4124 | - | valid_join
|
|
| 4125 | - = True
|
|
| 4138 | + Just join_ty
|
|
| 4126 | 4139 | | otherwise
|
| 4127 | - = False
|
|
| 4140 | + = mb_valid_join
|
|
| 4128 | 4141 | where
|
| 4129 | - valid_join | NotTopLevel <- lvl
|
|
| 4130 | - , AlwaysTailCalled { tailCallArity = arity } <- tail_call_info
|
|
| 4131 | - |
|
| 4132 | - , -- Invariant 1 as applied to LHSes of rules
|
|
| 4133 | - all (ok_rule arity) (idCoreRules bndr)
|
|
| 4134 | - |
|
| 4135 | - -- Invariant 2a: stable unfoldings
|
|
| 4136 | - -- See Note [Join points and INLINE pragmas]
|
|
| 4137 | - , ok_unfolding arity (realIdUnfolding bndr)
|
|
| 4138 | - |
|
| 4139 | - -- Invariant 4: Satisfies polymorphism rule
|
|
| 4140 | - , isValidJoinPointType arity (idType bndr)
|
|
| 4141 | - = True
|
|
| 4142 | - | otherwise
|
|
| 4143 | - = False
|
|
| 4142 | + mb_valid_join
|
|
| 4143 | + | NotTopLevel <- lvl
|
|
| 4144 | + , AlwaysTailCalled
|
|
| 4145 | + { tailCallArity = arity
|
|
| 4146 | + , tailCallJoinPointType = join_ty
|
|
| 4147 | + } <- tail_call_info
|
|
| 4148 | + |
|
| 4149 | + , -- Invariant 1 as applied to LHSes of rules
|
|
| 4150 | + all (ok_rule arity) (idCoreRules bndr)
|
|
| 4151 | + |
|
| 4152 | + -- Invariant 2a: stable unfoldings
|
|
| 4153 | + -- See Note [Join points and INLINE pragmas]
|
|
| 4154 | + , ok_unfolding arity (realIdUnfolding bndr)
|
|
| 4155 | + |
|
| 4156 | + -- Invariant 4: Satisfies polymorphism rule
|
|
| 4157 | + , isValidJoinPointType arity (idType bndr)
|
|
| 4158 | + = Just join_ty
|
|
| 4159 | + | otherwise
|
|
| 4160 | + = Nothing
|
|
| 4144 | 4161 | |
| 4145 | 4162 | lost_join | JoinPoint { joinPointArity = ja } <- idJoinPointHood bndr
|
| 4146 | - = not valid_join ||
|
|
| 4163 | + = isNothing mb_valid_join ||
|
|
| 4147 | 4164 | (case tail_call_info of -- Valid join but arity differs
|
| 4148 | 4165 | AlwaysTailCalled { tailCallArity = ja' } -> ja /= ja'
|
| 4149 | 4166 | _ -> False)
|
| ... | ... | @@ -2056,6 +2056,17 @@ is a join point, and what 'cont' is, in a value of type MaybeJoinCont |
| 2056 | 2056 | of a SpecConstr-generated RULE for a join point.
|
| 2057 | 2057 | -}
|
| 2058 | 2058 | |
| 2059 | +-- SLD TODO horrible logic that must be removed
|
|
| 2060 | +peelJoinResTy :: Int -> Type -> Type
|
|
| 2061 | +peelJoinResTy 0 ty = ty
|
|
| 2062 | +peelJoinResTy n ty
|
|
| 2063 | + | Just (_bndr, inner_ty) <- splitForAllTyCoVar_maybe ty
|
|
| 2064 | + = peelJoinResTy n inner_ty
|
|
| 2065 | + | Just (_, _mult, _arg, res_ty) <- splitFunTy_maybe ty
|
|
| 2066 | + = peelJoinResTy (n-1) res_ty
|
|
| 2067 | + | otherwise
|
|
| 2068 | + = ty
|
|
| 2069 | + |
|
| 2059 | 2070 | simplNonRecJoinPoint :: SimplEnv -> InId -> InExpr
|
| 2060 | 2071 | -> InExpr -> SimplCont
|
| 2061 | 2072 | -> SimplM (SimplFloats, OutExpr)
|
| ... | ... | @@ -2064,8 +2075,12 @@ simplNonRecJoinPoint env bndr rhs body cont |
| 2064 | 2075 | wrapJoinCont do_case_case env cont $ \ env cont ->
|
| 2065 | 2076 | do { -- We push join_cont into the join RHS and the body;
|
| 2066 | 2077 | -- and wrap wrap_cont around the whole thing
|
| 2067 | - ; let mult = contHoleScaling cont
|
|
| 2068 | - res_ty = contResultType cont
|
|
| 2078 | + ; let (mult, res_ty)
|
|
| 2079 | + -- SLD TODO
|
|
| 2080 | + | Just QuasiJoinPoint <- occInfoJoinPointType_maybe (idOccInfo bndr)
|
|
| 2081 | + = (idMult bndr, peelJoinResTy (idJoinArity bndr) $ substTy env (idType bndr))
|
|
| 2082 | + | otherwise
|
|
| 2083 | + = (contHoleScaling cont, contResultType cont)
|
|
| 2069 | 2084 | ; (env1, bndr1) <- simplNonRecJoinBndr env bndr mult res_ty
|
| 2070 | 2085 | ; (env2, bndr2) <- addBndrRules env1 bndr bndr1 (BC_Join NonRecursive cont)
|
| 2071 | 2086 | ; (floats1, env3) <- simplJoinBind NonRecursive cont (bndr,env) (bndr2,env2) (rhs,env)
|
| ... | ... | @@ -2084,8 +2099,13 @@ simplRecJoinPoint :: SimplEnv -> [(InId, InExpr)] |
| 2084 | 2099 | simplRecJoinPoint env pairs body cont
|
| 2085 | 2100 | = wrapJoinCont do_case_case env cont $ \ env cont ->
|
| 2086 | 2101 | do { let bndrs = map fst pairs
|
| 2087 | - mult = contHoleScaling cont
|
|
| 2088 | - res_ty = contResultType cont
|
|
| 2102 | + (mult, res_ty)
|
|
| 2103 | + -- SLD TODO
|
|
| 2104 | + | [b] <- bndrs
|
|
| 2105 | + , Just QuasiJoinPoint <- occInfoJoinPointType_maybe (idOccInfo b)
|
|
| 2106 | + = (idMult b, peelJoinResTy (idJoinArity b) $ substTy env (idType b))
|
|
| 2107 | + | otherwise
|
|
| 2108 | + = (contHoleScaling cont, contResultType cont)
|
|
| 2089 | 2109 | ; env1 <- simplRecJoinBndrs env bndrs mult res_ty
|
| 2090 | 2110 | -- NB: bndrs' don't have unfoldings or rules
|
| 2091 | 2111 | -- We add them as we go down
|
| ... | ... | @@ -2135,7 +2155,7 @@ trimJoinCont _ NotJoinPoint cont |
| 2135 | 2155 | = cont -- Not a jump
|
| 2136 | 2156 | trimJoinCont var (JoinPoint { joinPointType = join_ty, joinPointArity = arity }) cont
|
| 2137 | 2157 | | QuasiJoinPoint <- join_ty
|
| 2138 | - -- As per Note [Quasi join points], don't do any trimming for quasi join points.
|
|
| 2158 | + -- SLD TODO
|
|
| 2139 | 2159 | = cont
|
| 2140 | 2160 | | otherwise
|
| 2141 | 2161 | = trim arity cont
|
| ... | ... | @@ -214,7 +214,7 @@ newJoinId bndrs body_ty |
| 214 | 214 | -- arity: See Note [Invariants on join points] invariant 2b, in GHC.Core
|
| 215 | 215 | join_arity = length bndrs
|
| 216 | 216 | details = JoinId
|
| 217 | - { joinIdType = TrueJoinPoint -- SLD TODO this is very suspicious
|
|
| 217 | + { joinIdType = TrueJoinPoint -- SLD TODO this is suspicious
|
|
| 218 | 218 | , joinIdArity = join_arity
|
| 219 | 219 | , joinIdCbvMarks = Nothing
|
| 220 | 220 | }
|
| ... | ... | @@ -441,7 +441,7 @@ pprIdDetails other = brackets (pp other) |
| 441 | 441 | pp CoVarId = text "CoVarId"
|
| 442 | 442 | pp (JoinId ty arity marks) = quasi <> text "JoinId" <> parens (int arity) <> parens (ppr marks)
|
| 443 | 443 | where
|
| 444 | - quasi = case ty of { QuasiJoinPoint -> text "quasi"; TrueJoinPoint -> empty }
|
|
| 444 | + quasi = case ty of { QuasiJoinPoint -> text "Quasi"; TrueJoinPoint -> empty }
|
|
| 445 | 445 | |
| 446 | 446 | {-
|
| 447 | 447 | ************************************************************************
|