sheaf pushed to branch wip/andreask/ticked_joins at Glasgow Haskell Compiler / GHC
Commits:
19 changed files:
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Exitify.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Monad.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
Changes:
| ... | ... | @@ -935,7 +935,12 @@ lintCoreExpr (Tick tickish expr) |
| 935 | 935 | -- ; when block_joins
|
| 936 | 936 | ; pure r}
|
| 937 | 937 | where
|
| 938 | - block_joins = not (tickishCanScopeJoin tickish)
|
|
| 938 | + block_joins
|
|
| 939 | + | ProfNote {} <- tickish
|
|
| 940 | + = False -- Turns a true join point into a quasi join point.
|
|
| 941 | + -- SLD TODO: proper Core Lint support for quasi join points.
|
|
| 942 | + | otherwise
|
|
| 943 | + = not (tickishCanScopeJoin tickish)
|
|
| 939 | 944 | -- TODO Consider whether this is the correct rule. It is consistent with
|
| 940 | 945 | -- the simplifier's behaviour - cost-centre-scoped ticks become part of
|
| 941 | 946 | -- the continuation, and thus they behave like part of an evaluation
|
| ... | ... | @@ -1021,22 +1026,27 @@ lintCoreExpr e@(App _ _) |
| 1021 | 1026 | |
| 1022 | 1027 | ; return app_pair}
|
| 1023 | 1028 | where
|
| 1024 | - skipTick t = case collectFunSimple e of
|
|
| 1025 | - (Var v) -> etaExpansionTick v t
|
|
| 1026 | - _ -> tickishFloatable t
|
|
| 1027 | - (fun, args, _source_ticks) = collectArgsTicks skipTick e
|
|
| 1028 | - -- We must look through source ticks to avoid #21152, for example:
|
|
| 1029 | + skipTick t =
|
|
| 1030 | + case collectFunSimple e of
|
|
| 1031 | + Var v -> canCollectArgsThroughTick v t
|
|
| 1032 | + _ -> tickishFloatable t
|
|
| 1033 | + (fun, args, _ticks) = collectArgsTicks skipTick e
|
|
| 1034 | + -- We must look through ticks, using similar logic as CorePrep does,
|
|
| 1035 | + -- otherwise we may fail to spot a saturated application.
|
|
| 1036 | + --
|
|
| 1037 | + -- 1. Look through floatable ticks, as per Note [Eta expansion and source notes]
|
|
| 1038 | + -- in GHC.Core.Opt.Arity. We need to do this to avoid e.g.:
|
|
| 1039 | + --
|
|
| 1040 | + -- reallyUnsafePtrEquality
|
|
| 1041 | + -- = \ @a ->
|
|
| 1042 | + -- (src<loc> reallyUnsafePtrEquality#)
|
|
| 1043 | + -- @Lifted @a @Lifted @a
|
|
| 1029 | 1044 | --
|
| 1030 | - -- reallyUnsafePtrEquality
|
|
| 1031 | - -- = \ @a ->
|
|
| 1032 | - -- (src<loc> reallyUnsafePtrEquality#)
|
|
| 1033 | - -- @Lifted @a @Lifted @a
|
|
| 1045 | + -- 2. Look through profiling ticks when the head of the application must
|
|
| 1046 | + -- always remain saturated (e.g. a primop or a join point), as per
|
|
| 1047 | + -- Note [Ticks and mandatory eta expansion] in GHC.CoreToStg.Prep.
|
|
| 1034 | 1048 | --
|
| 1035 | - -- To do this, we use `collectArgsTicks tickishFloatable` to match
|
|
| 1036 | - -- the eta expansion behaviour, as per Note [Eta expansion and source notes]
|
|
| 1037 | - -- in GHC.Core.Opt.Arity.
|
|
| 1038 | - -- Sadly this was not quite enough. So we now also accept things that CorePrep will allow.
|
|
| 1039 | - -- See Note [Ticks and mandatory eta expansion]
|
|
| 1049 | + -- To do this, we use 'canCollectArgsThroughTick', as CorePrep does.
|
|
| 1040 | 1050 | |
| 1041 | 1051 | lintCoreExpr (Lam var expr)
|
| 1042 | 1052 | = markAllJoinsBad $
|
| ... | ... | @@ -226,7 +226,7 @@ exitifyRec in_scope pairs |
| 226 | 226 | let rhs = mkLams abs_vars e
|
| 227 | 227 | avoid = in_scope `extendInScopeSetList` captured
|
| 228 | 228 | -- Remember this binding under a suitable name
|
| 229 | - ; v <- addExit avoid TrueJoinPoint (length abs_vars) rhs
|
|
| 229 | + ; v <- addExit avoid (length abs_vars) rhs
|
|
| 230 | 230 | -- And jump to it from here
|
| 231 | 231 | ; return $ mkVarApps (Var v) abs_vars }
|
| 232 | 232 | |
| ... | ... | @@ -262,7 +262,7 @@ exitifyRec in_scope pairs |
| 262 | 262 | -- * the free variables of the whole joinrec
|
| 263 | 263 | -- * any bound variables (captured)
|
| 264 | 264 | -- * any exit join points created so far.
|
| 265 | -mkExitJoinId :: InScopeSet -> Type -> JoinType -> JoinArity -> ExitifyM JoinId
|
|
| 265 | +mkExitJoinId :: InScopeSet -> Type -> JoinPointType -> JoinArity -> ExitifyM JoinId
|
|
| 266 | 266 | mkExitJoinId in_scope ty join_ty join_arity = do
|
| 267 | 267 | fs <- get
|
| 268 | 268 | let avoid = in_scope `extendInScopeSetList` (map fst fs)
|
| ... | ... | @@ -273,11 +273,11 @@ mkExitJoinId in_scope ty join_ty join_arity = do |
| 273 | 273 | asJoinId (mkSysLocal (fsLit "exit") initExitJoinUnique ManyTy ty)
|
| 274 | 274 | join_ty join_arity
|
| 275 | 275 | |
| 276 | -addExit :: InScopeSet -> JoinType -> JoinArity -> CoreExpr -> ExitifyM JoinId
|
|
| 277 | -addExit in_scope join_ty join_arity rhs = do
|
|
| 276 | +addExit :: InScopeSet -> JoinArity -> CoreExpr -> ExitifyM JoinId
|
|
| 277 | +addExit in_scope join_arity rhs = do
|
|
| 278 | 278 | -- Pick a suitable name
|
| 279 | 279 | let ty = exprType rhs
|
| 280 | - v <- mkExitJoinId in_scope ty join_ty join_arity
|
|
| 280 | + v <- mkExitJoinId in_scope ty TrueJoinPoint join_arity
|
|
| 281 | 281 | fs <- get
|
| 282 | 282 | put ((v,rhs):fs)
|
| 283 | 283 | return v
|
| ... | ... | @@ -1126,7 +1126,7 @@ occAnalNonRecRhs !env lvl imp_rule_edges mb_join bndr rhs |
| 1126 | 1126 | -- returned by of occAnalLamTail. It's totally OK for them to mismatch;
|
| 1127 | 1127 | -- hence adjust the UDs from the RHS
|
| 1128 | 1128 | |
| 1129 | - WUD adj_rhs_uds final_rhs = adjustNonRecRhs mb_join $
|
|
| 1129 | + WUD adj_rhs_uds final_rhs = adjustNonRecRhs (joinPointHoodArity mb_join) $
|
|
| 1130 | 1130 | occAnalLamTail rhs_env rhs
|
| 1131 | 1131 | final_bndr_with_rules
|
| 1132 | 1132 | | noBinderSwaps env = bndr -- See Note [Unfoldings and rules]
|
| ... | ... | @@ -1140,7 +1140,8 @@ occAnalNonRecRhs !env lvl imp_rule_edges mb_join bndr rhs |
| 1140 | 1140 | -- See Note [Join points and unfoldings/rules]
|
| 1141 | 1141 | unf = idUnfolding bndr
|
| 1142 | 1142 | WTUD unf_tuds unf1 = occAnalUnfolding rhs_env unf
|
| 1143 | - adj_unf_uds = adjustTailArity mb_join unf_tuds
|
|
| 1143 | + adj_unf_uds = adjustTailArity mb_join_arity unf_tuds
|
|
| 1144 | + mb_join_arity = joinPointHoodArity mb_join
|
|
| 1144 | 1145 | |
| 1145 | 1146 | --------- Rules ---------
|
| 1146 | 1147 | -- See Note [Rules are extra RHSs] and Note [Rule dependency info]
|
| ... | ... | @@ -1160,7 +1161,7 @@ occAnalNonRecRhs !env lvl imp_rule_edges mb_join bndr rhs |
| 1160 | 1161 | |
| 1161 | 1162 | adj_rule_uds :: [UsageDetails]
|
| 1162 | 1163 | adj_rule_uds = imp_rule_uds ++
|
| 1163 | - [ l `andUDs` adjustTailArity mb_join r
|
|
| 1164 | + [ l `andUDs` adjustTailArity mb_join_arity r
|
|
| 1164 | 1165 | | (_,l,r) <- rules_w_uds ]
|
| 1165 | 1166 | |
| 1166 | 1167 | mkNonRecRhsCtxt :: TopLevelFlag -> Id -> Unfolding -> OccEncl
|
| ... | ... | @@ -1215,7 +1216,7 @@ occAnalRec !_ lvl |
| 1215 | 1216 | = WUD body_uds binds
|
| 1216 | 1217 | | otherwise
|
| 1217 | 1218 | = let (bndr', mb_join) = tagNonRecBinder lvl occ bndr
|
| 1218 | - !(WUD rhs_uds' rhs') = adjustNonRecRhs mb_join wtuds
|
|
| 1219 | + !(WUD rhs_uds' rhs') = adjustNonRecRhs (joinPointHoodArity mb_join) wtuds
|
|
| 1219 | 1220 | in WUD (body_uds `andUDs` rhs_uds')
|
| 1220 | 1221 | (NonRec bndr' rhs' : binds)
|
| 1221 | 1222 | where
|
| ... | ... | @@ -1831,7 +1832,7 @@ makeNode !env imp_rule_edges bndr_set (bndr, rhs) |
| 1831 | 1832 | unf = realIdUnfolding bndr -- realIdUnfolding: Ignore loop-breaker-ness
|
| 1832 | 1833 | -- here because that is what we are setting!
|
| 1833 | 1834 | WTUD unf_tuds unf' = occAnalUnfolding rhs_env unf
|
| 1834 | - adj_unf_uds = adjustTailArity (JoinPoint True rhs_ja) unf_tuds
|
|
| 1835 | + adj_unf_uds = adjustTailArity (Just rhs_ja) unf_tuds
|
|
| 1835 | 1836 | -- `rhs_ja` is `joinRhsArity rhs` and is the prediction for source MAr
|
| 1836 | 1837 | -- of Note [Join arity prediction based on joinRhsArity]
|
| 1837 | 1838 | |
| ... | ... | @@ -1846,7 +1847,7 @@ makeNode !env imp_rule_edges bndr_set (bndr, rhs) |
| 1846 | 1847 | -- `rhs_ja` is `joinRhsArity rhs'` and is the prediction for source MAr
|
| 1847 | 1848 | -- of Note [Join arity prediction based on joinRhsArity]
|
| 1848 | 1849 | rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
|
| 1849 | - rules_w_uds = [ (r,l,adjustTailArity (JoinPoint True rhs_ja) rhs_wuds)
|
|
| 1850 | + rules_w_uds = [ (r,l,adjustTailArity (Just rhs_ja) rhs_wuds)
|
|
| 1850 | 1851 | | rule <- idCoreRules bndr
|
| 1851 | 1852 | , let (r,l,rhs_wuds) = occAnalRule rhs_env rule ]
|
| 1852 | 1853 | rules' = map fstOf3 rules_w_uds
|
| ... | ... | @@ -2298,7 +2299,7 @@ occ_anal_lam_tail env (Cast expr co) |
| 2298 | 2299 | _ -> usage1
|
| 2299 | 2300 | |
| 2300 | 2301 | -- usage3: see Note [Quasi join points] in GHC.Core.Opt.Simplify.Iteration.
|
| 2301 | - usage3 = markAllQuasiTail usage2
|
|
| 2302 | + usage3 = markAllQuasiTail usage2 -- SLD TODO
|
|
| 2302 | 2303 | |
| 2303 | 2304 | in WUD usage3 (Cast expr' co)
|
| 2304 | 2305 | |
| ... | ... | @@ -2606,19 +2607,11 @@ occAnal env (Tick tickish body) |
| 2606 | 2607 | |
| 2607 | 2608 | usage_lam = markAllNonTail (markAllInsideLam usage)
|
| 2608 | 2609 | |
| 2609 | - -- TODO There may be ways to make ticks and join points play
|
|
| 2610 | - -- nicer together, but right now there are problems:
|
|
| 2611 | - -- let j x = ... in tick<t> (j 1)
|
|
| 2612 | - -- Making j a join point may cause the simplifier to drop t
|
|
| 2613 | - -- (if the tick is put into the continuation). So we don't
|
|
| 2614 | - -- count j 1 as a tail call.
|
|
| 2615 | - -- See #14242.
|
|
| 2616 | - |
|
| 2617 | 2610 | occAnal env (Cast expr co)
|
| 2618 | 2611 | = let (WUD usage expr') = occAnal env expr
|
| 2619 | 2612 | usage1 = addManyOccs usage (coVarsOfCo co)
|
| 2620 | 2613 | -- usage1: see Note [Gather occurrences of coercion variables]
|
| 2621 | - usage2 = markAllQuasiTail usage1
|
|
| 2614 | + usage2 = markAllQuasiTail usage1 -- SLD TODO
|
|
| 2622 | 2615 | -- usage2: see Note [Quasi join points]
|
| 2623 | 2616 | in WUD usage2 (Cast expr' co)
|
| 2624 | 2617 | |
| ... | ... | @@ -2626,7 +2619,7 @@ occAnal env app@(App _ _) |
| 2626 | 2619 | = occAnalApp env (collectArgsTicks tickishFloatable app)
|
| 2627 | 2620 | |
| 2628 | 2621 | occAnal env expr@(Lam {})
|
| 2629 | - = adjustNonRecRhs NotJoinPoint $ -- NotJoinPoint <=> markAllManyNonTail
|
|
| 2622 | + = adjustNonRecRhs Nothing $ -- Nothing <=> markAllManyNonTail
|
|
| 2630 | 2623 | occAnalLamTail env expr
|
| 2631 | 2624 | |
| 2632 | 2625 | occAnal env (Case scrut bndr ty alts)
|
| ... | ... | @@ -2754,7 +2747,8 @@ occAnalApp env (Var fun, args, ticks) |
| 2754 | 2747 | -- This caused #18296
|
| 2755 | 2748 | | fun `hasKey` runRWKey
|
| 2756 | 2749 | , [t1, t2, arg] <- args
|
| 2757 | - , WUD usage arg' <- adjustNonRecRhs (JoinPoint True 1) $ occAnalLamTail env arg
|
|
| 2750 | + , WUD usage arg' <- adjustNonRecRhs (Just 1) $ occAnalLamTail env arg
|
|
| 2751 | + -- SLD TODO TrueJoinPoint OK here??
|
|
| 2758 | 2752 | = let app_out = mkTicks ticks $ mkApps (Var fun) [t1, t2, arg']
|
| 2759 | 2753 | in WUD usage app_out
|
| 2760 | 2754 | |
| ... | ... | @@ -3814,8 +3808,8 @@ mkOneOcc !env id int_cxt arity |
| 3814 | 3808 | , lo_tail =
|
| 3815 | 3809 | AlwaysTailCalled
|
| 3816 | 3810 | { tailCallArity = arity
|
| 3817 | - , trueTailCall = True
|
|
| 3818 | - -- ^ Start off as a true join point.
|
|
| 3811 | + , tailCallJoinPointType = TrueJoinPoint
|
|
| 3812 | + -- Start off as a true join point.
|
|
| 3819 | 3813 | -- Updated by occurrence analysis.
|
| 3820 | 3814 | --
|
| 3821 | 3815 | -- See Note [Quasi join points] in GHC.Core.Opt.Simplify.Iteration.
|
| ... | ... | @@ -3903,7 +3897,11 @@ maybeZapTailCallInfo tail_info0 z_tail id_unique = |
| 3903 | 3897 | Just MarkNonTail -> NoTailCallInfo
|
| 3904 | 3898 | |
| 3905 | 3899 | -- See Note [Quasi join points] in GHC.Core.Opt.Simplify.Iteration.
|
| 3906 | - Just MarkQuasi -> tail_info0 { trueTailCall = False }
|
|
| 3900 | + Just MarkQuasi ->
|
|
| 3901 | + case tail_info0 of
|
|
| 3902 | + NoTailCallInfo -> NoTailCallInfo
|
|
| 3903 | + atc@AlwaysTailCalled {} ->
|
|
| 3904 | + atc { tailCallJoinPointType = QuasiJoinPoint }
|
|
| 3907 | 3905 | |
| 3908 | 3906 | Nothing -> tail_info0
|
| 3909 | 3907 | |
| ... | ... | @@ -3974,7 +3972,7 @@ lookupOccInfoByUnique (UD { ud_env = env |
| 3974 | 3972 | -------------------
|
| 3975 | 3973 | -- See Note [Adjusting right-hand sides]
|
| 3976 | 3974 | |
| 3977 | -adjustNonRecRhs :: JoinPointHood
|
|
| 3975 | +adjustNonRecRhs :: Maybe JoinArity
|
|
| 3978 | 3976 | -> WithTailUsageDetails CoreExpr
|
| 3979 | 3977 | -> WithUsageDetails CoreExpr
|
| 3980 | 3978 | -- ^ This function concentrates shared logic between occAnalNonRecBind and the
|
| ... | ... | @@ -3985,8 +3983,8 @@ adjustNonRecRhs mb_join_arity (WTUD (TUD rhs_ja uds) rhs) |
| 3985 | 3983 | where
|
| 3986 | 3984 | exact_join =
|
| 3987 | 3985 | case mb_join_arity of
|
| 3988 | - NotJoinPoint -> False
|
|
| 3989 | - JoinPoint { joinPointArity = ja' } -> ja' == rhs_ja
|
|
| 3986 | + Nothing -> False
|
|
| 3987 | + Just ja' -> ja' == rhs_ja
|
|
| 3990 | 3988 | |
| 3991 | 3989 | adjustTailUsage :: Bool -- True <=> Exactly-matching join point; don't do markNonTail
|
| 3992 | 3990 | -> CoreExpr -- Rhs usage, AFTER occAnalLamTail
|
| ... | ... | @@ -4000,12 +3998,12 @@ adjustTailUsage exact_join rhs uds |
| 4000 | 3998 | where
|
| 4001 | 3999 | one_shot = isOneShotFun rhs
|
| 4002 | 4000 | |
| 4003 | -adjustTailArity :: JoinPointHood -> TailUsageDetails -> UsageDetails
|
|
| 4001 | +adjustTailArity :: Maybe JoinArity -> TailUsageDetails -> UsageDetails
|
|
| 4004 | 4002 | adjustTailArity mb_rhs_ja (TUD ja usage) = markAllNonTailIf not_same_arity usage
|
| 4005 | 4003 | where
|
| 4006 | 4004 | not_same_arity = case mb_rhs_ja of
|
| 4007 | - NotJoinPoint -> True
|
|
| 4008 | - JoinPoint { joinPointArity = ja' } -> ja' /= ja
|
|
| 4005 | + Nothing -> True
|
|
| 4006 | + Just ja' -> ja' /= ja
|
|
| 4009 | 4007 | |
| 4010 | 4008 | type IdWithOccInfo = Id
|
| 4011 | 4009 | |
| ... | ... | @@ -4037,8 +4035,11 @@ tagNonRecBinder :: TopLevelFlag -- At top level? |
| 4037 | 4035 | -- Precondition: OccInfo is not IAmDead
|
| 4038 | 4036 | tagNonRecBinder lvl occ bndr
|
| 4039 | 4037 | | okForJoinPoint lvl bndr tail_call_info
|
| 4040 | - , AlwaysTailCalled { tailCallArity = ar, trueTailCall = true } <- tail_call_info
|
|
| 4041 | - = (setBinderOcc occ bndr, JoinPoint true ar)
|
|
| 4038 | + , AlwaysTailCalled
|
|
| 4039 | + { tailCallArity = ar
|
|
| 4040 | + , tailCallJoinPointType = join_ty
|
|
| 4041 | + } <- tail_call_info
|
|
| 4042 | + = (setBinderOcc occ bndr, JoinPoint join_ty ar)
|
|
| 4042 | 4043 | | otherwise
|
| 4043 | 4044 | = (setBinderOcc zapped_occ bndr, NotJoinPoint)
|
| 4044 | 4045 | where
|
| ... | ... | @@ -4229,5 +4230,5 @@ orLocalOcc occ1 occ2 = andLocalOcc occ1 occ2 |
| 4229 | 4230 | |
| 4230 | 4231 | andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
|
| 4231 | 4232 | andTailCallInfo (AlwaysTailCalled arity1 true1) (AlwaysTailCalled arity2 true2)
|
| 4232 | - | arity1 == arity2 = AlwaysTailCalled arity1 (true1 && true2)
|
|
| 4233 | + | arity1 == arity2 = AlwaysTailCalled arity1 (true1 Semi.<> true2)
|
|
| 4233 | 4234 | andTailCallInfo _ _ = NoTailCallInfo |
| ... | ... | @@ -1889,11 +1889,10 @@ newPolyBndrs dest_lvl |
| 1889 | 1889 | dest_is_top = isTopLvl dest_lvl
|
| 1890 | 1890 | transfer_join_info bndr new_bndr
|
| 1891 | 1891 | | JoinPoint
|
| 1892 | - { isTrueJoinPoint = true_join
|
|
| 1892 | + { joinPointType = join_ty
|
|
| 1893 | 1893 | , joinPointArity = join_arity }
|
| 1894 | 1894 | <- idJoinPointHood bndr
|
| 1895 | 1895 | , not dest_is_top
|
| 1896 | - , let join_ty = if true_join then TrueJoinPoint else QuasiJoinPoint
|
|
| 1897 | 1896 | = asJoinId new_bndr
|
| 1898 | 1897 | join_ty
|
| 1899 | 1898 | ( join_arity + length abs_vars )
|
| ... | ... | @@ -493,8 +493,8 @@ instance Outputable SimplSR where |
| 493 | 493 | where
|
| 494 | 494 | pp_mj = case mj of
|
| 495 | 495 | NotJoinPoint -> empty
|
| 496 | - JoinPoint true_join n
|
|
| 497 | - -> (if true_join then empty else text "[Quasi]") <> parens (int n)
|
|
| 496 | + JoinPoint { joinPointType = join_ty, joinPointArity = n }
|
|
| 497 | + -> ppr join_ty <> parens (int n)
|
|
| 498 | 498 | |
| 499 | 499 | ppr (ContEx _tv _cv _id e) = vcat [text "ContEx" <+> ppr e {-,
|
| 500 | 500 | ppr (filter_env tv), ppr (filter_env id) -}]
|
| ... | ... | @@ -2073,7 +2073,7 @@ simplNonRecJoinPoint env bndr rhs body cont |
| 2073 | 2073 | ; return (floats1 `addFloats` floats2, body') }
|
| 2074 | 2074 | where
|
| 2075 | 2075 | do_case_case
|
| 2076 | - | Just True <- occInfoIsTrueJoinPoint (idOccInfo bndr)
|
|
| 2076 | + | Just TrueJoinPoint <- occInfoJoinPointType_maybe (idOccInfo bndr)
|
|
| 2077 | 2077 | = seCaseCase env
|
| 2078 | 2078 | | otherwise
|
| 2079 | 2079 | = False
|
| ... | ... | @@ -2094,7 +2094,7 @@ simplRecJoinPoint env pairs body cont |
| 2094 | 2094 | ; return (floats1 `addFloats` floats2, body') }
|
| 2095 | 2095 | where
|
| 2096 | 2096 | do_case_case =
|
| 2097 | - if all ((== Just True) . occInfoIsTrueJoinPoint . idOccInfo . fst) pairs
|
|
| 2097 | + if all ((== Just TrueJoinPoint) . occInfoJoinPointType_maybe . idOccInfo . fst) pairs
|
|
| 2098 | 2098 | then seCaseCase env
|
| 2099 | 2099 | else False
|
| 2100 | 2100 | |
| ... | ... | @@ -2133,10 +2133,12 @@ trimJoinCont :: Id -- Used only in error message |
| 2133 | 2133 | |
| 2134 | 2134 | trimJoinCont _ NotJoinPoint cont
|
| 2135 | 2135 | = cont -- Not a jump
|
| 2136 | -trimJoinCont var (JoinPoint { isTrueJoinPoint = true_join, joinPointArity = arity }) cont
|
|
| 2137 | - = assertPpr true_join
|
|
| 2138 | - (text "trimJoinCont: unexpected quasi join point:" <+> ppr var) $
|
|
| 2139 | - trim arity cont
|
|
| 2136 | +trimJoinCont var (JoinPoint { joinPointType = join_ty, joinPointArity = arity }) cont
|
|
| 2137 | + | QuasiJoinPoint <- join_ty
|
|
| 2138 | + -- SLD TODO: not sure why we can end up here. Needs further investigation.
|
|
| 2139 | + = cont
|
|
| 2140 | + | otherwise
|
|
| 2141 | + = trim arity cont
|
|
| 2140 | 2142 | where
|
| 2141 | 2143 | trim 0 cont@(Stop {})
|
| 2142 | 2144 | = cont
|
| ... | ... | @@ -2246,7 +2248,7 @@ Note [Join points and case-of-case]: |
| 2246 | 2248 | This transformation is not valid if the occurrences of 'j' in 'body' appear:
|
| 2247 | 2249 | |
| 2248 | 2250 | 1. under casts (see #26422)
|
| 2249 | - 2. under profiling ticks (see #26693, #26157, #26642)
|
|
| 2251 | + 2. under profiling ticks (see #14242, #26157, #26642, #26693)
|
|
| 2250 | 2252 | |
| 2251 | 2253 | For example, consider (a minimisation of) the program in #26693:
|
| 2252 | 2254 | |
| ... | ... | @@ -2312,7 +2314,7 @@ we proceed as follows: |
| 2312 | 2314 | 2. In the simplifier, when we come across a join point binding (in either
|
| 2313 | 2315 | 'simplNonRecJoinPoint' or 'simplRecJoinPoint'), we retrieve the information
|
| 2314 | 2316 | of whether this is a true join point or a quasi join point using
|
| 2315 | - 'occInfoIsTrueJoinPoint'.
|
|
| 2317 | + 'occInfoJoinPointType_maybe'.
|
|
| 2316 | 2318 | |
| 2317 | 2319 | If we are dealing with a quasi join point, we switch off the case-of-case
|
| 2318 | 2320 | transformation.
|
| ... | ... | @@ -25,7 +25,7 @@ import GHC.Prelude |
| 25 | 25 | import GHC.Types.Var ( Var, isId, mkLocalVar )
|
| 26 | 26 | import GHC.Types.Name ( mkSystemVarName )
|
| 27 | 27 | import GHC.Types.Id ( Id, mkSysLocalOrCoVarM )
|
| 28 | -import GHC.Types.Id.Info ( IdDetails(..), vanillaIdInfo, setArityInfo, JoinType (..) )
|
|
| 28 | +import GHC.Types.Id.Info ( IdDetails(..), vanillaIdInfo, setArityInfo )
|
|
| 29 | 29 | import GHC.Core.Type ( Type, Mult )
|
| 30 | 30 | import GHC.Core.Opt.Stats
|
| 31 | 31 | import GHC.Core.Rules
|
| ... | ... | @@ -46,7 +46,7 @@ import GHC.Types.InlinePragma |
| 46 | 46 | import GHC.Types.Error (DiagnosticReason(..))
|
| 47 | 47 | import GHC.Types.Literal ( litIsLifted )
|
| 48 | 48 | import GHC.Types.Id
|
| 49 | -import GHC.Types.Id.Info ( IdDetails(..), JoinType (..) )
|
|
| 49 | +import GHC.Types.Id.Info ( IdDetails(..) )
|
|
| 50 | 50 | import GHC.Types.Id.Make ( voidArgId, voidPrimId )
|
| 51 | 51 | import GHC.Types.Var.Env
|
| 52 | 52 | import GHC.Types.Var.Set
|
| ... | ... | @@ -1993,9 +1993,8 @@ spec_one env fn arg_bndrs body (call_pat, rule_number) |
| 1993 | 1993 | spec_id_ty = mkLamTypes spec_lam_args spec_body_ty
|
| 1994 | 1994 | spec_arity = count isId spec_lam_args
|
| 1995 | 1995 | spec_join_arity
|
| 1996 | - | Just ty <- joinId_maybe fn
|
|
| 1997 | - , let is_true = case ty of { TrueJoinPoint -> True; QuasiJoinPoint -> False }
|
|
| 1998 | - = JoinPoint { isTrueJoinPoint = is_true, joinPointArity = length spec_call_args }
|
|
| 1996 | + | Just join_ty <- joinId_maybe fn
|
|
| 1997 | + = JoinPoint { joinPointType = join_ty, joinPointArity = length spec_call_args }
|
|
| 1999 | 1998 | | otherwise
|
| 2000 | 1999 | = NotJoinPoint
|
| 2001 | 2000 | spec_id = setCbvCandidate $
|
| ... | ... | @@ -844,10 +844,10 @@ mkWWBindPair ww_opts fn_id fn_info fn_args fn_body work_uniq div |
| 844 | 844 | -- inl_rule: it does not make sense for workers to be constructorlike.
|
| 845 | 845 | |
| 846 | 846 | work_join_arity
|
| 847 | - | Just ty <- joinId_maybe fn_id =
|
|
| 848 | - let true_join = case ty of { TrueJoinPoint -> True; QuasiJoinPoint -> False }
|
|
| 849 | - in JoinPoint true_join join_arity
|
|
| 850 | - | otherwise = NotJoinPoint
|
|
| 847 | + | Just join_ty <- joinId_maybe fn_id
|
|
| 848 | + = JoinPoint join_ty join_arity
|
|
| 849 | + | otherwise
|
|
| 850 | + = NotJoinPoint
|
|
| 851 | 851 | -- worker is join point iff wrapper is join point
|
| 852 | 852 | -- (see Note [Don't w/w join points for CPR])
|
| 853 | 853 |
| ... | ... | @@ -308,13 +308,21 @@ ppr_expr add_par (Let bind expr) |
| 308 | 308 | sep [hang (keyword bind <+> char '{') 2 (ppr_bind noAnn bind <+> text "} in"),
|
| 309 | 309 | pprCoreExpr expr]
|
| 310 | 310 | where
|
| 311 | - keyword (NonRec b _)
|
|
| 312 | - | isJoinPoint (bndrIsJoin_maybe b) = text "join"
|
|
| 313 | - | otherwise = text "let"
|
|
| 314 | - keyword (Rec pairs)
|
|
| 315 | - | ((b,_):_) <- pairs
|
|
| 316 | - , isJoinPoint (bndrIsJoin_maybe b) = text "joinrec"
|
|
| 317 | - | otherwise = text "letrec"
|
|
| 311 | + keyword (NonRec b _) =
|
|
| 312 | + case bndrIsJoin_maybe b of
|
|
| 313 | + NotJoinPoint -> text "let"
|
|
| 314 | + JoinPoint { joinPointType = join_ty } ->
|
|
| 315 | + case join_ty of
|
|
| 316 | + TrueJoinPoint -> text "join"
|
|
| 317 | + QuasiJoinPoint -> text "quasijoin"
|
|
| 318 | + keyword (Rec ((b,_):_)) =
|
|
| 319 | + case bndrIsJoin_maybe b of
|
|
| 320 | + NotJoinPoint -> text "letrec"
|
|
| 321 | + JoinPoint { joinPointType = join_ty } ->
|
|
| 322 | + case join_ty of
|
|
| 323 | + TrueJoinPoint -> text "joinrec"
|
|
| 324 | + QuasiJoinPoint -> text "quasijoinrec"
|
|
| 325 | + keyword (Rec _) = text "letrec"
|
|
| 318 | 326 | |
| 319 | 327 | ppr_expr add_par (Tick tickish expr)
|
| 320 | 328 | = sdocOption sdocSuppressTicks $ \case
|
| ... | ... | @@ -38,7 +38,10 @@ import GHC.Core.Coercion hiding ( substCo, substCoVarBndr ) |
| 38 | 38 | |
| 39 | 39 | import GHC.Types.Literal
|
| 40 | 40 | import GHC.Types.Id
|
| 41 | -import GHC.Types.Id.Info ( realUnfoldingInfo, setUnfoldingInfo, setRuleInfo, IdInfo (..), JoinType (..) )
|
|
| 41 | +import GHC.Types.Id.Info
|
|
| 42 | + ( IdInfo(..)
|
|
| 43 | + , realUnfoldingInfo, setUnfoldingInfo, setRuleInfo
|
|
| 44 | + )
|
|
| 42 | 45 | import GHC.Types.InlinePragma ( isAlwaysActive )
|
| 43 | 46 | import GHC.Types.Var ( isNonCoVarId )
|
| 44 | 47 | import GHC.Types.Var.Set
|
| ... | ... | @@ -1078,12 +1081,11 @@ joinPointBinding_maybe bndr rhs |
| 1078 | 1081 | |
| 1079 | 1082 | | AlwaysTailCalled
|
| 1080 | 1083 | { tailCallArity = join_arity
|
| 1081 | - , trueTailCall = is_true_tail }
|
|
| 1084 | + , tailCallJoinPointType = join_ty }
|
|
| 1082 | 1085 | <- tailCallInfo (idOccInfo bndr)
|
| 1083 | 1086 | , (bndrs, body) <- etaExpandToJoinPoint join_arity rhs
|
| 1084 | 1087 | , let str_sig = idDmdSig bndr
|
| 1085 | 1088 | str_arity = count isId bndrs -- Strictness demands are for Ids only
|
| 1086 | - join_ty = if is_true_tail then TrueJoinPoint else QuasiJoinPoint
|
|
| 1087 | 1089 | join_bndr =
|
| 1088 | 1090 | (asJoinId bndr join_ty join_arity)
|
| 1089 | 1091 | `setIdDmdSig` etaConvertDmdSig str_arity str_sig
|
| ... | ... | @@ -34,7 +34,7 @@ module GHC.Core.Utils ( |
| 34 | 34 | exprIsTickedString, exprIsTickedString_maybe,
|
| 35 | 35 | exprIsTopLevelBindable,
|
| 36 | 36 | exprIsUnaryClassFun, isUnaryClassId,
|
| 37 | - altsAreExhaustive, etaExpansionTick,
|
|
| 37 | + altsAreExhaustive, canCollectArgsThroughTick,
|
|
| 38 | 38 | cantEtaReduceFun,
|
| 39 | 39 | |
| 40 | 40 | -- * Equality
|
| ... | ... | @@ -2076,14 +2076,17 @@ altsAreExhaustive (Alt con1 _ _ : alts) |
| 2076 | 2076 | -- we behave conservatively here -- I don't think it's important
|
| 2077 | 2077 | -- enough to deserve special treatment
|
| 2078 | 2078 | |
| 2079 | --- | Should we look past this tick when eta-expanding the given function?
|
|
| 2079 | +-- | Should we look past this tick when collecting arguments
|
|
| 2080 | +-- for the given function?
|
|
| 2080 | 2081 | --
|
| 2081 | 2082 | -- See Note [Ticks and mandatory eta expansion]
|
| 2082 | --- Takes the function we are applying as argument.
|
|
| 2083 | -etaExpansionTick :: Id -> GenTickish pass -> Bool
|
|
| 2084 | -etaExpansionTick id t
|
|
| 2085 | - = ( cantEtaReduceFun id ) &&
|
|
| 2086 | - ( tickishFloatable t || isProfTick t )
|
|
| 2083 | +canCollectArgsThroughTick
|
|
| 2084 | + :: Id -- ^ function at the head of the application
|
|
| 2085 | + -> GenTickish pass -- ^ tick we want to collect arguments past
|
|
| 2086 | + -> Bool
|
|
| 2087 | +canCollectArgsThroughTick id t
|
|
| 2088 | + = tickishFloatable t
|
|
| 2089 | + || (cantEtaReduceFun id && isProfTick t)
|
|
| 2087 | 2090 | |
| 2088 | 2091 | -- | Can we eta-reduce the given function?
|
| 2089 | 2092 | -- See Note [Eta reduction soundness], criteria (B), (J), and (W).
|
| ... | ... | @@ -1052,8 +1052,8 @@ cpeApp top_env expr |
| 1052 | 1052 | -- floating the tick which isn't optimal for perf. But this only makes
|
| 1053 | 1053 | -- a difference if we have a non-floatable tick which is somewhat rare.
|
| 1054 | 1054 | | Var vh <- head
|
| 1055 | - , Var head' <- lookupCorePrepEnv top_env vh
|
|
| 1056 | - , etaExpansionTick head' tickish
|
|
| 1055 | + , Just head' <- getIdFromTrivialExpr_maybe (lookupCorePrepEnv top_env vh)
|
|
| 1056 | + , canCollectArgsThroughTick head' tickish
|
|
| 1057 | 1057 | = (head,as')
|
| 1058 | 1058 | where
|
| 1059 | 1059 | (head,as') = go fun (AITick tickish : as)
|
| ... | ... | @@ -24,7 +24,7 @@ module GHC.Types.Basic ( |
| 24 | 24 | ConTag, ConTagZ, fIRST_TAG,
|
| 25 | 25 | |
| 26 | 26 | Arity, VisArity, RepArity, JoinArity, FullArgCount,
|
| 27 | - JoinPointHood(..), isJoinPoint,
|
|
| 27 | + JoinPointType(..), JoinPointHood(..), joinPointHoodArity, isJoinPoint,
|
|
| 28 | 28 | |
| 29 | 29 | Alignment, mkAlignment, alignmentOf, alignmentBytes,
|
| 30 | 30 | |
| ... | ... | @@ -70,7 +70,7 @@ module GHC.Types.Basic ( |
| 70 | 70 | BranchCount, oneBranch,
|
| 71 | 71 | InterestingCxt(..),
|
| 72 | 72 | TailCallInfo(..), tailCallInfo, zapOccTailCallInfo,
|
| 73 | - isAlwaysTailCalled, occInfoIsTrueJoinPoint,
|
|
| 73 | + isAlwaysTailCalled, occInfoJoinPointType_maybe,
|
|
| 74 | 74 | |
| 75 | 75 | EP(..),
|
| 76 | 76 | |
| ... | ... | @@ -1150,11 +1150,16 @@ instance Monoid InsideLam where |
| 1150 | 1150 | |
| 1151 | 1151 | -----------------
|
| 1152 | 1152 | |
| 1153 | +joinPointHoodArity :: JoinPointHood -> Maybe JoinArity
|
|
| 1154 | +joinPointHoodArity = \case
|
|
| 1155 | + NotJoinPoint -> Nothing
|
|
| 1156 | + JoinPoint { joinPointArity = ja } -> Just ja
|
|
| 1157 | + |
|
| 1153 | 1158 | -- | See Note [TailCallInfo]
|
| 1154 | 1159 | data TailCallInfo
|
| 1155 | 1160 | = AlwaysTailCalled
|
| 1156 | - { tailCallArity :: {-# UNPACK #-} !JoinArity
|
|
| 1157 | - , trueTailCall :: !Bool -- ^ is this a true join point? see Note [Quasi join points]
|
|
| 1161 | + { tailCallArity :: {-# UNPACK #-} !JoinArity
|
|
| 1162 | + , tailCallJoinPointType :: !JoinPointType -- ^ See Note [Quasi join points]
|
|
| 1158 | 1163 | }
|
| 1159 | 1164 | | NoTailCallInfo
|
| 1160 | 1165 | deriving (Eq)
|
| ... | ... | @@ -1176,14 +1181,14 @@ isAlwaysTailCalled occ |
| 1176 | 1181 | -- If so, is it a true join point or a quasi join point?
|
| 1177 | 1182 | --
|
| 1178 | 1183 | -- See Note [Quasi join points] in GHC.Core.Opt.Simplify.Iteration.
|
| 1179 | -occInfoIsTrueJoinPoint :: OccInfo -> Maybe Bool
|
|
| 1180 | -occInfoIsTrueJoinPoint occ =
|
|
| 1184 | +occInfoJoinPointType_maybe :: OccInfo -> Maybe JoinPointType
|
|
| 1185 | +occInfoJoinPointType_maybe occ =
|
|
| 1181 | 1186 | case tailCallInfo occ of
|
| 1182 | - AlwaysTailCalled { trueTailCall = true } -> Just true
|
|
| 1187 | + AlwaysTailCalled { tailCallJoinPointType = join_ty } -> Just join_ty
|
|
| 1183 | 1188 | NoTailCallInfo -> Nothing
|
| 1184 | 1189 | instance Outputable TailCallInfo where
|
| 1185 | - ppr (AlwaysTailCalled ar t) =
|
|
| 1186 | - sep [ text "Tail", (if t then empty else text "Quasi"), int ar ]
|
|
| 1190 | + ppr (AlwaysTailCalled { tailCallJoinPointType = join_ty, tailCallArity = ar }) =
|
|
| 1191 | + sep [ ppr join_ty <> text "Tail", int ar ]
|
|
| 1187 | 1192 | ppr NoTailCallInfo = text "NoTailCallInfo"
|
| 1188 | 1193 | |
| 1189 | 1194 | -----------------
|
| ... | ... | @@ -1232,8 +1237,11 @@ instance Outputable OccInfo where |
| 1232 | 1237 | pp_tail = pprShortTailCallInfo tail_info
|
| 1233 | 1238 | |
| 1234 | 1239 | pprShortTailCallInfo :: TailCallInfo -> SDoc
|
| 1235 | -pprShortTailCallInfo (AlwaysTailCalled ar t)
|
|
| 1236 | - = char 'T' <> (if t then empty else text "[Q]")
|
|
| 1240 | +pprShortTailCallInfo
|
|
| 1241 | + (AlwaysTailCalled
|
|
| 1242 | + { tailCallJoinPointType = join_type
|
|
| 1243 | + , tailCallArity = ar })
|
|
| 1244 | + = char 'T' <> (case join_type of { TrueJoinPoint -> empty; QuasiJoinPoint -> char 'Q' })
|
|
| 1237 | 1245 | <> brackets (int ar)
|
| 1238 | 1246 | pprShortTailCallInfo NoTailCallInfo = empty
|
| 1239 | 1247 |
| ... | ... | @@ -574,7 +574,7 @@ isWorkerLikeId id = |
| 574 | 574 | isJoinId :: Var -> Bool
|
| 575 | 575 | isJoinId = isJust . joinId_maybe
|
| 576 | 576 | |
| 577 | -joinId_maybe :: Var -> Maybe JoinType
|
|
| 577 | +joinId_maybe :: Var -> Maybe JoinPointType
|
|
| 578 | 578 | -- It is convenient in GHC.Core.Opt.SetLevels.lvlMFE to apply isJoinId
|
| 579 | 579 | -- to the free vars of an expression, so it's convenient
|
| 580 | 580 | -- if it returns False for type variables
|
| ... | ... | @@ -589,10 +589,11 @@ idJoinPointHood :: Var -> JoinPointHood |
| 589 | 589 | idJoinPointHood id
|
| 590 | 590 | | isId id
|
| 591 | 591 | = case Var.idDetails id of
|
| 592 | - JoinId ty arity _marks ->
|
|
| 593 | - let isTrue = case ty of { TrueJoinPoint -> True; QuasiJoinPoint -> False}
|
|
| 594 | - in JoinPoint isTrue arity
|
|
| 595 | - _ -> NotJoinPoint
|
|
| 592 | + JoinId
|
|
| 593 | + { joinIdType = join_type
|
|
| 594 | + , joinIdArity = arity }
|
|
| 595 | + -> JoinPoint join_type arity
|
|
| 596 | + _ -> NotJoinPoint
|
|
| 596 | 597 | | otherwise = NotJoinPoint
|
| 597 | 598 | |
| 598 | 599 | idDataCon :: Id -> DataCon
|
| ... | ... | @@ -675,7 +676,7 @@ idJoinArity id = |
| 675 | 676 | JoinPoint { joinPointArity = ar } -> ar
|
| 676 | 677 | NotJoinPoint -> pprPanic "idJoinArity" (ppr id)
|
| 677 | 678 | |
| 678 | -asJoinId :: Id -> JoinType -> JoinArity -> JoinId
|
|
| 679 | +asJoinId :: Id -> JoinPointType -> JoinArity -> JoinId
|
|
| 679 | 680 | asJoinId id ty arity
|
| 680 | 681 | = warnPprTrace (not (isLocalId id))
|
| 681 | 682 | "global id being marked as join var" (ppr id) $
|
| ... | ... | @@ -710,9 +711,8 @@ zapJoinId jid |
| 710 | 711 | asJoinId_maybe :: Id -> JoinPointHood -> Id
|
| 711 | 712 | asJoinId_maybe id = \case
|
| 712 | 713 | NotJoinPoint -> zapJoinId id
|
| 713 | - JoinPoint { isTrueJoinPoint = true_join, joinPointArity = arity } ->
|
|
| 714 | - let ty = if true_join then TrueJoinPoint else QuasiJoinPoint
|
|
| 715 | - in asJoinId id ty arity
|
|
| 714 | + JoinPoint { joinPointType = join_type, joinPointArity = arity } ->
|
|
| 715 | + asJoinId id join_type arity
|
|
| 716 | 716 | |
| 717 | 717 | {-
|
| 718 | 718 | ************************************************************************
|
| ... | ... | @@ -65,7 +65,7 @@ module GHC.Types.Id.Info ( |
| 65 | 65 | TailCallInfo(..),
|
| 66 | 66 | tailCallInfo, isAlwaysTailCalled,
|
| 67 | 67 | |
| 68 | - JoinType(..),
|
|
| 68 | + JoinPointType(..),
|
|
| 69 | 69 | |
| 70 | 70 | -- ** The RuleInfo type
|
| 71 | 71 | RuleInfo(..),
|
| ... | ... | @@ -207,7 +207,7 @@ data IdDetails |
| 207 | 207 | -- This only covers /un-lifted/ coercions, of type
|
| 208 | 208 | -- (t1 ~# t2) or (t1 ~R# t2), not their lifted variants
|
| 209 | 209 | | JoinId
|
| 210 | - { joinIdType :: JoinType
|
|
| 210 | + { joinIdType :: JoinPointType
|
|
| 211 | 211 | , joinIdArity :: JoinArity
|
| 212 | 212 | , joinIdCbvMarks :: Maybe [CbvMark]
|
| 213 | 213 | }
|
| ... | ... | @@ -226,14 +226,6 @@ data IdDetails |
| 226 | 226 | -- The [CbvMark] is always empty (and ignored) until after Tidy for ids from the current
|
| 227 | 227 | -- module.
|
| 228 | 228 | |
| 229 | -data JoinType
|
|
| 230 | - = TrueJoinPoint
|
|
| 231 | - | QuasiJoinPoint
|
|
| 232 | - deriving stock ( Eq, Show )
|
|
| 233 | -instance Outputable JoinType where
|
|
| 234 | - ppr TrueJoinPoint = text "TrueJoinPoint"
|
|
| 235 | - ppr QuasiJoinPoint = text "QuasiJoinPoint"
|
|
| 236 | - |
|
| 237 | 229 | data RecSelInfo
|
| 238 | 230 | = RSI { rsi_def :: [ConLike] -- Record selector defined for these
|
| 239 | 231 | , rsi_undef :: [ConLike] -- Record selector not defined for these
|
| ... | ... | @@ -422,7 +414,7 @@ isCoVarDetails :: IdDetails -> Bool |
| 422 | 414 | isCoVarDetails CoVarId = True
|
| 423 | 415 | isCoVarDetails _ = False
|
| 424 | 416 | |
| 425 | -isJoinIdDetails_maybe :: IdDetails -> Maybe (JoinType, JoinArity, Maybe [CbvMark])
|
|
| 417 | +isJoinIdDetails_maybe :: IdDetails -> Maybe (JoinPointType, JoinArity, Maybe [CbvMark])
|
|
| 426 | 418 | isJoinIdDetails_maybe (JoinId ty join_arity marks) = Just (ty, join_arity, marks)
|
| 427 | 419 | isJoinIdDetails_maybe _ = Nothing
|
| 428 | 420 |
| ... | ... | @@ -330,7 +330,8 @@ tickishCanSplit _ = False |
| 330 | 330 | -- | Is @join f x in <tick> jump f x@ valid?
|
| 331 | 331 | tickishCanScopeJoin :: GenTickish pass -> Bool
|
| 332 | 332 | tickishCanScopeJoin tick = case tick of
|
| 333 | - ProfNote{} -> True
|
|
| 333 | + ProfNote{} -> False -- Turns the join point into a quasi join point.
|
|
| 334 | + -- See Note [Quasi join points]
|
|
| 334 | 335 | HpcTick{} -> False
|
| 335 | 336 | Breakpoint{} -> False
|
| 336 | 337 | SourceNote{} -> True
|
| ... | ... | @@ -132,7 +132,7 @@ import GHC.Utils.Fingerprint |
| 132 | 132 | import GHC.Types.SrcLoc
|
| 133 | 133 | import GHC.Types.Unique
|
| 134 | 134 | import qualified GHC.Data.Strict as Strict
|
| 135 | -import GHC.Utils.Outputable( JoinPointHood(..) )
|
|
| 135 | +import GHC.Utils.Outputable( JoinPointHood(..), JoinPointType (..) )
|
|
| 136 | 136 | import GHCi.FFI
|
| 137 | 137 | import GHCi.Message
|
| 138 | 138 | |
| ... | ... | @@ -1053,6 +1053,10 @@ instance Binary DiffTime where |
| 1053 | 1053 | get bh = do r <- get bh
|
| 1054 | 1054 | return $ fromRational r
|
| 1055 | 1055 | |
| 1056 | +instance Binary JoinPointType where
|
|
| 1057 | + put_ bh ty = put_ bh (ty == TrueJoinPoint)
|
|
| 1058 | + get bh = do { true <- get bh; return $ if true then TrueJoinPoint else QuasiJoinPoint }
|
|
| 1059 | + |
|
| 1056 | 1060 | instance Binary JoinPointHood where
|
| 1057 | 1061 | put_ bh NotJoinPoint = putByte bh 0
|
| 1058 | 1062 | put_ bh (JoinPoint t ar) = do
|
| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | module GHC.Utils.Outputable (
|
| 16 | 16 | -- * Type classes
|
| 17 | 17 | Outputable(..), OutputableBndr(..), OutputableP(..),
|
| 18 | - BindingSite(..), JoinPointHood(..), isJoinPoint,
|
|
| 18 | + BindingSite(..), JoinPointType(..), JoinPointHood(..), isJoinPoint,
|
|
| 19 | 19 | |
| 20 | 20 | IsOutput(..), IsLine(..), IsDoc(..),
|
| 21 | 21 | HLine, HDoc,
|
| ... | ... | @@ -150,6 +150,7 @@ import Data.Graph (SCC(..)) |
| 150 | 150 | import Data.List (intersperse)
|
| 151 | 151 | import Data.List.NonEmpty (NonEmpty (..))
|
| 152 | 152 | import Data.Semigroup (Arg(..))
|
| 153 | +import qualified Data.Semigroup as Semi
|
|
| 153 | 154 | import qualified Data.List.NonEmpty as NEL
|
| 154 | 155 | import Data.Time ( UTCTime )
|
| 155 | 156 | import Data.Time.Format.ISO8601
|
| ... | ... | @@ -1284,10 +1285,21 @@ data BindingSite |
| 1284 | 1285 | | LetBind -- ^ The x in (let x = rhs in e)
|
| 1285 | 1286 | deriving Eq
|
| 1286 | 1287 | |
| 1288 | +data JoinPointType
|
|
| 1289 | + = TrueJoinPoint
|
|
| 1290 | + | QuasiJoinPoint
|
|
| 1291 | + deriving Eq
|
|
| 1292 | +instance Outputable JoinPointType where
|
|
| 1293 | + ppr TrueJoinPoint = empty
|
|
| 1294 | + ppr QuasiJoinPoint = text "Quasi"
|
|
| 1295 | +instance Semigroup JoinPointType where
|
|
| 1296 | + TrueJoinPoint <> TrueJoinPoint = TrueJoinPoint
|
|
| 1297 | + _ <> _ = QuasiJoinPoint
|
|
| 1298 | + |
|
| 1287 | 1299 | data JoinPointHood
|
| 1288 | 1300 | = JoinPoint
|
| 1289 | - { isTrueJoinPoint :: {-# UNPACK #-} !Bool
|
|
| 1290 | - , joinPointArity :: {-# UNPACK #-} !Int
|
|
| 1301 | + { joinPointType :: {-# UNPACK #-} !JoinPointType
|
|
| 1302 | + , joinPointArity :: {-# UNPACK #-} !Int
|
|
| 1291 | 1303 | -- ^ The JoinArity (but an Int here because synonym JoinArity is defined in Types.Basic)
|
| 1292 | 1304 | }
|
| 1293 | 1305 | | NotJoinPoint
|
| ... | ... | @@ -1298,10 +1310,9 @@ isJoinPoint (JoinPoint {}) = True |
| 1298 | 1310 | isJoinPoint NotJoinPoint = False
|
| 1299 | 1311 | |
| 1300 | 1312 | instance Outputable JoinPointHood where
|
| 1301 | - ppr NotJoinPoint = text "NotJoinPoint"
|
|
| 1302 | - ppr (JoinPoint true arity) =
|
|
| 1303 | - (if true then empty else text "Quasi")
|
|
| 1304 | - <> text "JoinPoint" <> parens (ppr arity)
|
|
| 1313 | + ppr NotJoinPoint = text "NotJoinPoint"
|
|
| 1314 | + ppr (JoinPoint join_type arity) =
|
|
| 1315 | + ppr join_type <> text "JoinPoint" <> parens (ppr arity)
|
|
| 1305 | 1316 | |
| 1306 | 1317 | instance NFData JoinPointHood where
|
| 1307 | 1318 | rnf x = x `seq` ()
|