Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC
Commits:
-
5bdcdf82
by Simon Peyton Jones at 2026-04-07T23:25:52+01:00
2 changed files:
Changes:
| ... | ... | @@ -40,7 +40,8 @@ import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe |
| 40 | 40 | , typeArity, arityTypeArity, etaExpandAT )
|
| 41 | 41 | import GHC.Core.SimpleOpt ( exprIsConApp_maybe, joinPointBinding_maybe, joinPointBindings_maybe )
|
| 42 | 42 | import GHC.Core.FVs ( mkRuleInfo {- exprsFreeIds -} )
|
| 43 | -import GHC.Core.Rules ( lookupRule, getRules )
|
|
| 43 | +import GHC.Core.Rules ( RuleMatch(..), applyBindWrapper, isEmptyBindWrapper
|
|
| 44 | + , lookupRule, getRules )
|
|
| 44 | 45 | import GHC.Core.Multiplicity
|
| 45 | 46 | |
| 46 | 47 | import GHC.Hs.Extension
|
| ... | ... | @@ -2298,7 +2299,7 @@ simplOutExpr env expr cont |
| 2298 | 2299 | _ -> rebuild_go env expr cont
|
| 2299 | 2300 | where
|
| 2300 | 2301 | (fun, args) = collectArgs expr
|
| 2301 | - cont' = pushArgs env Simplified (expType fun) args cont
|
|
| 2302 | + cont' = pushArgs env Simplified (exprType fun) args cont
|
|
| 2302 | 2303 | occ_fun = occurAnalyseExpr fun -- ToDo:explain; c.f. Note [Occurrence-analyse after rule firing]
|
| 2303 | 2304 | |
| 2304 | 2305 | ---------------------------------------------------------
|
| ... | ... | @@ -2364,10 +2365,14 @@ simplOutId env fun cont |
| 2364 | 2365 | then tryRules env rules_for_me fun out_args
|
| 2365 | 2366 | else return Nothing
|
| 2366 | 2367 | ; case mb_match of {
|
| 2367 | - Just (rule_arity, rhs, rhs_args ) -> simplExprF env rhs $
|
|
| 2368 | - pushArgs env NoDup rhs_args $
|
|
| 2369 | - dropContArgs rule_arity cont ;
|
|
| 2370 | - Nothing ->
|
|
| 2368 | + Just (RM { rm_rule = rule, rm_rhs = rhs
|
|
| 2369 | + , rm_args = rhs_args, rm_binds = wrap })
|
|
| 2370 | + -> simplExprF env rhs' $
|
|
| 2371 | + dropContArgs (ruleArity rule) cont
|
|
| 2372 | + where
|
|
| 2373 | + rhs' = applyBindWrapper wrap $
|
|
| 2374 | + mkApps rhs rhs_args
|
|
| 2375 | + ; Nothing ->
|
|
| 2371 | 2376 | |
| 2372 | 2377 | -- Try inlining
|
| 2373 | 2378 | do { logger <- getLogger
|
| ... | ... | @@ -2451,18 +2456,15 @@ rebuildCall env fun_info |
| 2451 | 2456 | ; rebuildCall env (addValArgTo fun_info arg' fun_ty) cont }
|
| 2452 | 2457 | |
| 2453 | 2458 | ---------- No further useful info, revert to generic rebuild ------------
|
| 2454 | -rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_rules = rules }) cont
|
|
| 2459 | +rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_arg_specs, ai_rules = rules }) cont
|
|
| 2455 | 2460 | | null rules
|
| 2456 | - = rebuild env (argInfoExpr fun rev_args) cont
|
|
| 2461 | + = rebuild env (argInfoExpr fun rev_arg_specs) cont
|
|
| 2457 | 2462 | | otherwise -- Try rules again: Plan (AFTER) in Note [When to apply rewrite rules]
|
| 2458 | - = do { let args = reverse rev_args
|
|
| 2459 | - ; mb_match <- tryRules env rules fun (map argSpecArg args)
|
|
| 2463 | + = do { let arg_specs = reverse rev_arg_specs
|
|
| 2464 | + ; mb_match <- tryRules env rules fun (map argSpecArg arg_specs)
|
|
| 2460 | 2465 | ; case mb_match of
|
| 2461 | - Just (rule_arity, rhs, rhs_args)
|
|
| 2462 | - -> simplExprF env rhs $
|
|
| 2463 | - pushArgs env Simplified rhs_args $
|
|
| 2464 | - pushArgSpecs env (drop rule_arity args) cont
|
|
| 2465 | - Nothing -> rebuild env (argInfoExpr fun rev_args) cont }
|
|
| 2466 | + Just rule_match -> fireRuleAFTER env rule_match arg_specs cont
|
|
| 2467 | + Nothing -> rebuild env (argInfoExpr fun rev_arg_specs) cont }
|
|
| 2466 | 2468 | |
| 2467 | 2469 | -----------------------------------
|
| 2468 | 2470 | tryInlining :: SimplEnv -> Logger -> OutId -> SimplCont -> SimplM (Maybe OutExpr)
|
| ... | ... | @@ -2644,20 +2646,36 @@ See Note [No free join points in arityType] in GHC.Core.Opt.Arity |
| 2644 | 2646 | ************************************************************************
|
| 2645 | 2647 | -}
|
| 2646 | 2648 | |
| 2649 | +fireRuleAFTER :: SimplEnv -> RuleMatch
|
|
| 2650 | + -> [ArgSpec] -> SimplCont
|
|
| 2651 | + -> SimplM (SimplFloats, CoreExpr)
|
|
| 2652 | +fireRuleAFTER env rule_match arg_specs cont
|
|
| 2653 | + | RM { rm_rule = rule, rm_rhs = rhs, rm_args = rhs_args
|
|
| 2654 | + , rm_binds = wrap, rm_bndrs = bndrs } <- rule_match
|
|
| 2655 | + = do { let env' = env `addNewInScopeIds` bndrs
|
|
| 2656 | + ; (floats, e') <- simplExprF env' rhs $
|
|
| 2657 | + pushArgs env' Simplified (exprType rhs) rhs_args $
|
|
| 2658 | + pushArgSpecs env' (drop (ruleArity rule) arg_specs) cont
|
|
| 2659 | + ; return $
|
|
| 2660 | + if isEmptyBindWrapper wrap
|
|
| 2661 | + then (floats, e')
|
|
| 2662 | + else (emptyFloats env', applyBindWrapper wrap $
|
|
| 2663 | + wrapFloats floats e') }
|
|
| 2664 | + |
|
| 2665 | + |
|
| 2647 | 2666 | tryRules :: SimplEnv -> [CoreRule]
|
| 2648 | 2667 | -> OutId -> [OutExpr]
|
| 2649 | - -> SimplM (Maybe (FullArgCount, CoreExpr, [CoreExpr]))
|
|
| 2668 | + -> SimplM (Maybe RuleMatch)
|
|
| 2650 | 2669 | |
| 2651 | 2670 | tryRules env rules fn args
|
| 2652 | - | Just (rule, rule_rhs, rule_args) <- lookupRule ropts in_scope_env
|
|
| 2653 | - act_fun fn args rules
|
|
| 2654 | - -- Fire a rule for the function
|
|
| 2655 | - = do { logger <- getLogger
|
|
| 2656 | - ; checkedTick (RuleFired (ruleName rule))
|
|
| 2657 | --- ; let occ_anald_rhs = occurAnalyseExpr rule_rhs
|
|
| 2658 | --- -- See Note [Occurrence-analyse after rule firing]
|
|
| 2659 | - ; dump logger rule rule_rhs
|
|
| 2660 | - ; return (Just (ruleArity rule, rhs_rhs, rule_args)) }
|
|
| 2671 | + | Just rule_match <- lookupRule ropts in_scope_env
|
|
| 2672 | + act_fun fn args rules
|
|
| 2673 | + -- Fire a rule for the function
|
|
| 2674 | + = do { let the_rule = rm_rule rule_match
|
|
| 2675 | + ; logger <- getLogger
|
|
| 2676 | + ; checkedTick (RuleFired (ruleName the_rule))
|
|
| 2677 | + ; dump logger the_rule (rm_rhs rule_match)
|
|
| 2678 | + ; return (Just rule_match) }
|
|
| 2661 | 2679 | |
| 2662 | 2680 | | otherwise -- No rule fires
|
| 2663 | 2681 | = do { logger <- getLogger
|
| ... | ... | @@ -2723,12 +2741,8 @@ trySeqRules in_env scrut rhs cont |
| 2723 | 2741 | ; let seq_rules = getRules rule_base seqId
|
| 2724 | 2742 | ; mb_match <- tryRules in_env seq_rules seqId out_args
|
| 2725 | 2743 | ; case mb_match of
|
| 2726 | - Nothing -> return Nothing
|
|
| 2727 | - Just (rule_arity, rhs, rhs_args) -> return (Just (rhs, cont'))
|
|
| 2728 | - where
|
|
| 2729 | - cont' = pushArgs in_env Simplified rhs_args $
|
|
| 2730 | - pushArgSpecs in_env (drop rule_arity out_arg_specs) rule_cont
|
|
| 2731 | - }
|
|
| 2744 | + Nothing -> return Nothing
|
|
| 2745 | + Just rule_match -> Just <$> fireRuleAFTER in_env rule_match out_arg_specs cont }
|
|
| 2732 | 2746 | where
|
| 2733 | 2747 | no_cast_scrut = drop_casts scrut
|
| 2734 | 2748 |
| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | module GHC.Core.Rules (
|
| 11 | 11 | -- ** Looking up rules
|
| 12 | 12 | RuleMatch(..), lookupRule, matchExprs, ruleLhsIsMoreSpecific,
|
| 13 | + BindWrapper, isEmptyBindWrapper, applyBindWrapper,
|
|
| 13 | 14 | |
| 14 | 15 | -- ** RuleBase, RuleEnv
|
| 15 | 16 | RuleBase, RuleEnv(..), mkRuleEnv, emptyRuleEnv,
|
| ... | ... | @@ -88,6 +89,7 @@ import GHC.Types.Basic |
| 88 | 89 | import GHC.Data.FastString
|
| 89 | 90 | import GHC.Data.Maybe
|
| 90 | 91 | import GHC.Data.Bag
|
| 92 | +import GHC.Data.OrdList
|
|
| 91 | 93 | import GHC.Data.List.SetOps( hasNoDups )
|
| 92 | 94 | |
| 93 | 95 | import GHC.Utils.FV( filterFV, fvVarSet )
|
| ... | ... | @@ -591,7 +593,7 @@ lookupRule opts rule_env@(ISE in_scope _) is_active fn args rules |
| 591 | 593 | go ms [] = ms
|
| 592 | 594 | go ms (r:rs)
|
| 593 | 595 | | Just rm <- matchRule opts rule_env is_active fn args' rough_args r
|
| 594 | - = go (rm { rm_binds = mkTicks ticks . rm_binds rm } : ms) rs
|
|
| 596 | + = go (rm { rm_binds = mkTicks ticks `consOL` rm_binds rm } : ms) rs
|
|
| 595 | 597 | | otherwise
|
| 596 | 598 | = -- pprTrace "match failed" (ppr r $$ ppr args $$
|
| 597 | 599 | -- ppr [ (arg_id, maybeUnfoldingTemplate unf)
|
| ... | ... | @@ -746,7 +748,7 @@ matchRule opts rule_env _is_active fn args _rough_args |
| 746 | 748 | ; return (RM { rm_rule = rule
|
| 747 | 749 | , rm_rhs = rhs
|
| 748 | 750 | , rm_args = []
|
| 749 | - , rm_binds = id
|
|
| 751 | + , rm_binds = emptyBindWrapper
|
|
| 750 | 752 | , rm_bndrs = [] }) }
|
| 751 | 753 | |
| 752 | 754 | matchRule _opts rule_env is_active _fn target_es rough_args
|
| ... | ... | @@ -968,13 +970,23 @@ data RuleSubst = RS { -- Substitution; applied only to the template, not the tar |
| 968 | 970 | , rs_bndrs :: [Var] -- Variables bound by floated lets
|
| 969 | 971 | }
|
| 970 | 972 | |
| 971 | -type BindWrapper = CoreExpr -> CoreExpr
|
|
| 973 | +type BindWrapper = OrdList (CoreExpr -> CoreExpr)
|
|
| 972 | 974 | -- See Notes [Matching lets] and [Matching cases]
|
| 973 | 975 | -- we represent the floated bindings as a core-to-core function
|
| 976 | + -- WE use an OrdList so that we can tell the common case of an empty wrapper
|
|
| 977 | + |
|
| 978 | +emptyBindWrapper :: BindWrapper
|
|
| 979 | +emptyBindWrapper = nilOL
|
|
| 980 | + |
|
| 981 | +isEmptyBindWrapper :: BindWrapper -> Bool
|
|
| 982 | +isEmptyBindWrapper = isNilOL
|
|
| 983 | + |
|
| 984 | +applyBindWrapper :: BindWrapper -> CoreExpr -> CoreExpr
|
|
| 985 | +applyBindWrapper bw e = foldrOL ($) e bw
|
|
| 974 | 986 | |
| 975 | 987 | emptyRuleSubst :: RuleSubst
|
| 976 | 988 | emptyRuleSubst = RS { rs_tv_subst = emptyVarEnv, rs_id_subst = emptyVarEnv
|
| 977 | - , rs_binds = \e -> e, rs_bndrs = [] }
|
|
| 989 | + , rs_binds = nilOL, rs_bndrs = [] }
|
|
| 978 | 990 | |
| 979 | 991 | |
| 980 | 992 | {- Note [Casts in the target]
|
| ... | ... | @@ -1110,7 +1122,7 @@ match renv subst e1 (Tick t e2) mco |
| 1110 | 1122 | | otherwise
|
| 1111 | 1123 | = Nothing
|
| 1112 | 1124 | where
|
| 1113 | - subst' = subst { rs_binds = rs_binds subst . mkTick t }
|
|
| 1125 | + subst' = subst { rs_binds = rs_binds subst `snocOL` mkTick t }
|
|
| 1114 | 1126 | |
| 1115 | 1127 | match renv subst e@(Tick t e1) e2 mco
|
| 1116 | 1128 | | tickishFloatable t -- Ignore floatable ticks in rule template.
|
| ... | ... | @@ -1344,7 +1356,7 @@ match renv subst e1 (Let bind e2) mco |
| 1344 | 1356 | -- We are floating the let-binding out, as if it had enclosed
|
| 1345 | 1357 | -- the entire target from Day 1. So we must add its binders to
|
| 1346 | 1358 | -- the in-scope set (#20200)
|
| 1347 | - (subst { rs_binds = rs_binds subst . Let bind'
|
|
| 1359 | + (subst { rs_binds = rs_binds subst `snocOL` Let bind'
|
|
| 1348 | 1360 | , rs_bndrs = new_bndrs ++ rs_bndrs subst })
|
| 1349 | 1361 | e1 e2 mco
|
| 1350 | 1362 | | otherwise
|
| ... | ... | @@ -1370,7 +1382,7 @@ match renv subst (Lam x1 e1) e2 mco |
| 1370 | 1382 | , Just (x2, e2', ts) <- exprIsLambda_maybe in_scope_env casted_e2
|
| 1371 | 1383 | -- See Note [Lambdas in the template]
|
| 1372 | 1384 | = let renv' = rnMatchBndr2 renv x1 x2
|
| 1373 | - subst' = subst { rs_binds = rs_binds subst . flip (foldr mkTick) ts }
|
|
| 1385 | + subst' = subst { rs_binds = rs_binds subst `snocOL` flip (foldr mkTick) ts }
|
|
| 1374 | 1386 | in match renv' subst' e1 e2' MRefl
|
| 1375 | 1387 | |
| 1376 | 1388 | match renv subst e1 e2@(Lam {}) mco
|
| ... | ... | @@ -1435,11 +1447,11 @@ match _ _ _e1 _e2 _mco = -- pprTrace "Failing at" ((text "e1:" <+> ppr _e1) $$ ( |
| 1435 | 1447 | eta_reduce :: RuleMatchEnv -> CoreExpr -> Maybe (RuleMatchEnv, CoreExpr)
|
| 1436 | 1448 | -- See Note [Eta reduction in the target]
|
| 1437 | 1449 | eta_reduce renv e@(Lam {})
|
| 1438 | - = go renv id [] e
|
|
| 1450 | + = go renv emptyBindWrapper [] e
|
|
| 1439 | 1451 | where
|
| 1440 | 1452 | go :: RuleMatchEnv -> BindWrapper -> [Var] -> CoreExpr
|
| 1441 | 1453 | -> Maybe (RuleMatchEnv, CoreExpr)
|
| 1442 | - go renv bw vs (Let b e) = go renv (bw . Let b) vs e
|
|
| 1454 | + go renv bw vs (Let b e) = go renv (bw `snocOL` Let b) vs e
|
|
| 1443 | 1455 | |
| 1444 | 1456 | go renv bw vs (Lam v e) = go renv' bw (v':vs) e
|
| 1445 | 1457 | where
|
| ... | ... | @@ -1454,7 +1466,7 @@ eta_reduce renv e@(Lam {}) |
| 1454 | 1466 | , v == rnOccR (rv_lcl renv) tv
|
| 1455 | 1467 | = go renv bw vs f
|
| 1456 | 1468 | |
| 1457 | - go renv bw [] e = Just (renv, bw e)
|
|
| 1469 | + go renv bw [] e = Just (renv, applyBindWrapper bw e)
|
|
| 1458 | 1470 | go _ _ (_:_) _ = Nothing
|
| 1459 | 1471 | |
| 1460 | 1472 | eta_reduce _ _ = Nothing
|