Simon Peyton Jones pushed to branch wip/T23109a at Glasgow Haskell Compiler / GHC
Commits:
-
acc7c29d
by Simon Peyton Jones at 2025-05-26T10:21:37+01:00
-
2da3fb2c
by Simon Peyton Jones at 2025-05-26T10:21:55+01:00
-
4d2a8804
by Simon Peyton Jones at 2025-05-26T11:23:49+01:00
5 changed files:
- compiler/GHC/Core/Opt/Simplify.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
Changes:
... | ... | @@ -156,7 +156,7 @@ simplifyPgm logger unit_env name_ppr_ctx opts |
156 | 156 | && logHasDumpFlag logger Opt_D_dump_simpl_stats) $
|
157 | 157 | logDumpMsg logger
|
158 | 158 | "Simplifier statistics for following pass"
|
159 | - (vcat [text termination_msg <+> text "after" <+> ppr (it_count-1)
|
|
159 | + (vcat [text termination_msg <+> text "after" <+> ppr it_count
|
|
160 | 160 | <+> text "iterations",
|
161 | 161 | blankLine,
|
162 | 162 | pprSimplCount counts_out])
|
... | ... | @@ -240,8 +240,7 @@ simplifyPgm logger unit_env name_ppr_ctx opts |
240 | 240 | ; read_rule_env = updExternalPackageRules base_rule_env <$> read_eps_rules
|
241 | 241 | |
242 | 242 | ; fam_envs = (eps_fam_inst_env eps, fam_inst_env)
|
243 | - ; iter_mode = mode { sm_first_iter = iteration_no ==1 }
|
|
244 | - ; simpl_env = mkSimplEnv iter_mode fam_envs } ;
|
|
243 | + ; simpl_env = mkSimplEnv mode fam_envs } ;
|
|
245 | 244 | |
246 | 245 | -- Simplify the program
|
247 | 246 | ((binds1, rules1), counts1) <-
|
... | ... | @@ -272,35 +272,32 @@ seUnfoldingOpts env = sm_uf_opts (seMode env) |
272 | 272 | |
273 | 273 | -- See Note [The environments of the Simplify pass]
|
274 | 274 | data SimplMode = SimplMode -- See comments in GHC.Core.Opt.Simplify.Monad
|
275 | - { sm_phase :: !CompilerPhase
|
|
276 | - , sm_names :: ![String] -- ^ Name(s) of the phase
|
|
277 | - , sm_first_iter :: !Bool -- ^ True <=> first iteration
|
|
278 | - -- False <=> second or subsequent iteration
|
|
279 | - , sm_rules :: !Bool -- ^ Whether RULES are enabled
|
|
280 | - , sm_inline :: !Bool -- ^ Whether inlining is enabled
|
|
281 | - , sm_eta_expand :: !Bool -- ^ Whether eta-expansion is enabled
|
|
282 | - , sm_cast_swizzle :: !Bool -- ^ Do we swizzle casts past lambdas?
|
|
283 | - , sm_uf_opts :: !UnfoldingOpts -- ^ Unfolding options
|
|
284 | - , sm_case_case :: !Bool -- ^ Whether case-of-case is enabled
|
|
285 | - , sm_pre_inline :: !Bool -- ^ Whether pre-inlining is enabled
|
|
286 | - , sm_float_enable :: !FloatEnable -- ^ Whether to enable floating out
|
|
275 | + { sm_phase :: !CompilerPhase
|
|
276 | + , sm_names :: ![String] -- ^ Name(s) of the phase
|
|
277 | + , sm_rules :: !Bool -- ^ Whether RULES are enabled
|
|
278 | + , sm_inline :: !Bool -- ^ Whether inlining is enabled
|
|
279 | + , sm_eta_expand :: !Bool -- ^ Whether eta-expansion is enabled
|
|
280 | + , sm_cast_swizzle :: !Bool -- ^ Do we swizzle casts past lambdas?
|
|
281 | + , sm_uf_opts :: !UnfoldingOpts -- ^ Unfolding options
|
|
282 | + , sm_case_case :: !Bool -- ^ Whether case-of-case is enabled
|
|
283 | + , sm_pre_inline :: !Bool -- ^ Whether pre-inlining is enabled
|
|
284 | + , sm_float_enable :: !FloatEnable -- ^ Whether to enable floating out
|
|
287 | 285 | , sm_do_eta_reduction :: !Bool
|
288 | - , sm_arity_opts :: !ArityOpts
|
|
289 | - , sm_rule_opts :: !RuleOpts
|
|
290 | - , sm_case_folding :: !Bool
|
|
291 | - , sm_case_merge :: !Bool
|
|
292 | - , sm_co_opt_opts :: !OptCoercionOpts -- ^ Coercion optimiser options
|
|
286 | + , sm_arity_opts :: !ArityOpts
|
|
287 | + , sm_rule_opts :: !RuleOpts
|
|
288 | + , sm_case_folding :: !Bool
|
|
289 | + , sm_case_merge :: !Bool
|
|
290 | + , sm_co_opt_opts :: !OptCoercionOpts -- ^ Coercion optimiser options
|
|
293 | 291 | }
|
294 | 292 | |
295 | 293 | instance Outputable SimplMode where
|
296 | 294 | ppr (SimplMode { sm_phase = p , sm_names = ss
|
297 | - , sm_first_iter = fi, sm_rules = r, sm_inline = i
|
|
295 | + , sm_rules = r, sm_inline = i
|
|
298 | 296 | , sm_cast_swizzle = cs
|
299 | 297 | , sm_eta_expand = eta, sm_case_case = cc })
|
300 | 298 | = text "SimplMode" <+> braces (
|
301 | 299 | sep [ text "Phase =" <+> ppr p <+>
|
302 | 300 | brackets (text (concat $ intersperse "," ss)) <> comma
|
303 | - , pp_flag fi (text "first-iter") <> comma
|
|
304 | 301 | , pp_flag i (text "inline") <> comma
|
305 | 302 | , pp_flag r (text "rules") <> comma
|
306 | 303 | , pp_flag eta (text "eta-expand") <> comma
|
... | ... | @@ -2342,21 +2342,10 @@ simplOutId env fun cont |
2342 | 2342 | |
2343 | 2343 | -- Normal case for (f e1 .. en)
|
2344 | 2344 | simplOutId env fun cont
|
2345 | - = do { rule_base <- getSimplRules
|
|
2345 | + = -- Try rewrite rules: Plan (BEFORE) in Note [When to apply rewrite rules]
|
|
2346 | + do { rule_base <- getSimplRules
|
|
2346 | 2347 | ; let rules_for_me = getRules rule_base fun
|
2347 | - arg_info = mkArgInfo env fun rules_for_me cont
|
|
2348 | 2348 | out_args = contOutArgs env cont :: [OutExpr]
|
2349 | - |
|
2350 | - -- If we are not in the first iteration, we have already tried rules and inlining
|
|
2351 | - -- at the end of the previous iteration; no need to repeat that
|
|
2352 | --- ; if not (sm_first_iter (seMode env))
|
|
2353 | --- then rebuildCall env arg_info cont
|
|
2354 | --- else
|
|
2355 | --- Do this BEFORE so that we can take advantage of single-occ inlines
|
|
2356 | --- Example: T21839c which takes an extra Simplifier iteration after w/w
|
|
2357 | --- if you don't do this
|
|
2358 | - |
|
2359 | - -- Try rewrite rules: Plan (BEFORE) in Note [When to apply rewrite rules]
|
|
2360 | 2349 | ; mb_match <- if not (null rules_for_me) &&
|
2361 | 2350 | (isClassOpId fun || activeUnfolding (seMode env) fun)
|
2362 | 2351 | then tryRules env rules_for_me fun out_args
|
... | ... | @@ -2368,14 +2357,16 @@ simplOutId env fun cont |
2368 | 2357 | |
2369 | 2358 | -- Try inlining
|
2370 | 2359 | do { logger <- getLogger
|
2371 | - ; mb_inline <- tryInlining env logger fun (contArgs cont)
|
|
2360 | + ; mb_inline <- tryInlining env logger fun cont
|
|
2372 | 2361 | ; case mb_inline of{
|
2373 | - Just expr -> simplExprF env expr cont ;
|
|
2362 | + Just expr -> do { checkedTick (UnfoldingDone fun)
|
|
2363 | + ; simplExprF env expr cont } ;
|
|
2374 | 2364 | Nothing ->
|
2375 | 2365 | |
2376 | 2366 | -- Neither worked, so just rebuild
|
2377 | - rebuildCall env arg_info cont
|
|
2378 | - } } } }
|
|
2367 | + do { let arg_info = mkArgInfo env fun rules_for_me cont
|
|
2368 | + ; rebuildCall env arg_info cont
|
|
2369 | + } } } } }
|
|
2379 | 2370 | |
2380 | 2371 | ---------------------------------------------------------
|
2381 | 2372 | -- Dealing with a call site
|
... | ... | @@ -2447,39 +2438,28 @@ rebuildCall env fun_info |
2447 | 2438 | |
2448 | 2439 | ---------- No further useful info, revert to generic rebuild ------------
|
2449 | 2440 | rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_rules = rules }) cont
|
2441 | + | null rules
|
|
2442 | + = rebuild env (argInfoExpr fun rev_args) cont
|
|
2443 | + | otherwise -- Try rules again: Plan (AFTER) in Note [When to apply rewrite rules]
|
|
2450 | 2444 | = do { let args = reverse rev_args
|
2451 | - |
|
2452 | - -- Try rules again: Plan (AFTER) in Note [When to apply rewrite rules]
|
|
2453 | - ; mb_match <- if null rules
|
|
2454 | - then return Nothing
|
|
2455 | - else tryRules env rules fun (map argSpecArg args)
|
|
2456 | - ; case mb_match of {
|
|
2445 | + ; mb_match <- tryRules env rules fun (map argSpecArg args)
|
|
2446 | + ; case mb_match of
|
|
2457 | 2447 | Just (rule_arity, rhs) -> simplExprF env rhs $
|
2458 | - pushSimplifiedArgs env (drop rule_arity args) cont ;
|
|
2459 | - Nothing ->
|
|
2460 | - |
|
2461 | - do { logger <- getLogger
|
|
2462 | - ; mb_inline <- tryInlining env logger fun (null args, argSummaries env args, cont)
|
|
2463 | - ; case mb_inline of
|
|
2464 | - Just body -> simplExprF env body $
|
|
2465 | - pushSimplifiedArgs env args cont
|
|
2466 | - Nothing -> rebuild env (argInfoExpr fun rev_args) cont
|
|
2467 | - } } }
|
|
2448 | + pushSimplifiedArgs env (drop rule_arity args) cont
|
|
2449 | + Nothing -> rebuild env (argInfoExpr fun rev_args) cont }
|
|
2468 | 2450 | |
2469 | 2451 | -----------------------------------
|
2470 | -tryInlining :: SimplEnv -> Logger -> OutId
|
|
2471 | - -> (Bool, [ArgSummary], SimplCont)
|
|
2472 | - -> SimplM (Maybe OutExpr)
|
|
2473 | -tryInlining env logger fun (lone_variable, arg_infos, call_cont)
|
|
2474 | - | Just expr <- callSiteInline env logger fun lone_variable arg_infos interesting_cont
|
|
2475 | - = do { dump_inline expr call_cont
|
|
2476 | - ; checkedTick (UnfoldingDone fun)
|
|
2452 | +tryInlining :: SimplEnv -> Logger -> OutId -> SimplCont -> SimplM (Maybe OutExpr)
|
|
2453 | +tryInlining env logger var cont
|
|
2454 | + | Just expr <- callSiteInline env logger var lone_variable arg_infos interesting_cont
|
|
2455 | + = do { dump_inline expr cont
|
|
2477 | 2456 | ; return (Just expr) }
|
2478 | 2457 | |
2479 | 2458 | | otherwise
|
2480 | 2459 | = return Nothing
|
2481 | 2460 | |
2482 | 2461 | where
|
2462 | + (lone_variable, arg_infos, call_cont) = contArgs cont
|
|
2483 | 2463 | interesting_cont = interestingCallContext env call_cont
|
2484 | 2464 | |
2485 | 2465 | log_inlining doc
|
... | ... | @@ -2490,12 +2470,12 @@ tryInlining env logger fun (lone_variable, arg_infos, call_cont) |
2490 | 2470 | dump_inline unfolding cont
|
2491 | 2471 | | not (logHasDumpFlag logger Opt_D_dump_inlinings) = return ()
|
2492 | 2472 | | not (logHasDumpFlag logger Opt_D_verbose_core2core)
|
2493 | - = when (isExternalName (idName fun)) $
|
|
2473 | + = when (isExternalName (idName var)) $
|
|
2494 | 2474 | log_inlining $
|
2495 | - sep [text "Inlining done:", nest 4 (ppr fun)]
|
|
2475 | + sep [text "Inlining done:", nest 4 (ppr var)]
|
|
2496 | 2476 | | otherwise
|
2497 | 2477 | = log_inlining $
|
2498 | - sep [text "Inlining done: " <> ppr fun,
|
|
2478 | + sep [text "Inlining done: " <> ppr var,
|
|
2499 | 2479 | nest 4 (vcat [text "Inlined fn: " <+> nest 2 (ppr unfolding),
|
2500 | 2480 | text "Cont: " <+> ppr cont])]
|
2501 | 2481 |
... | ... | @@ -24,7 +24,7 @@ module GHC.Core.Opt.Simplify.Utils ( |
24 | 24 | SimplCont(..), DupFlag(..), FromWhat(..), StaticEnv,
|
25 | 25 | isSimplified, contIsStop,
|
26 | 26 | contIsDupable, contResultType, contHoleType, contHoleScaling,
|
27 | - contIsTrivial, contArgs, contIsRhs, argSummaries,
|
|
27 | + contIsTrivial, contArgs, contIsRhs,
|
|
28 | 28 | countArgs, contOutArgs, dropContArgs,
|
29 | 29 | mkBoringStop, mkRhsStop, mkLazyArgStop,
|
30 | 30 | interestingCallContext,
|
... | ... | @@ -537,11 +537,15 @@ contArgs cont |
537 | 537 | lone _ = True
|
538 | 538 | |
539 | 539 | go args (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = k })
|
540 | - = go (argSummary se arg : args) k
|
|
540 | + = go (is_interesting arg se : args) k
|
|
541 | 541 | go args (ApplyToTy { sc_cont = k }) = go args k
|
542 | 542 | go args (CastIt { sc_cont = k }) = go args k
|
543 | 543 | go args k = (False, reverse args, k)
|
544 | 544 | |
545 | + is_interesting arg se = interestingArg se arg
|
|
546 | + -- Do *not* use short-cutting substitution here
|
|
547 | + -- because we want to get as much IdInfo as possible
|
|
548 | + |
|
545 | 549 | contOutArgs :: SimplEnv -> SimplCont -> [OutExpr]
|
546 | 550 | -- Get the leading arguments from the `SimplCont`, as /OutExprs/
|
547 | 551 | contOutArgs env cont
|
... | ... | @@ -883,15 +887,6 @@ strictArgContext (ArgInfo { ai_encl = encl_rules, ai_discs = discs }) |
883 | 887 | -- Why NonRecursive? Becuase it's a bit like
|
884 | 888 | -- let a = g x in f a
|
885 | 889 | |
886 | -argSummaries :: SimplEnv -> [ArgSpec] -> [ArgSummary]
|
|
887 | -argSummaries env args
|
|
888 | - = go args
|
|
889 | - where
|
|
890 | - env' = zapSubstEnv env -- The args are simplified already
|
|
891 | - go [] = []
|
|
892 | - go (TyArg {} : args) = go args
|
|
893 | - go (ValArg { as_arg = arg } : args) = argSummary env' arg : go args
|
|
894 | - |
|
895 | 890 | interestingCallContext :: SimplEnv -> SimplCont -> CallCtxt
|
896 | 891 | -- See Note [Interesting call context]
|
897 | 892 | interestingCallContext env cont
|
... | ... | @@ -995,9 +990,9 @@ rule for (*) (df d) can fire. To do this |
995 | 990 | b) we say that a con-like argument (eg (df d)) is interesting
|
996 | 991 | -}
|
997 | 992 | |
998 | -argSummary :: SimplEnv -> CoreExpr -> ArgSummary
|
|
993 | +interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
|
|
999 | 994 | -- See Note [Interesting arguments]
|
1000 | -argSummary env e = go env 0 e
|
|
995 | +interestingArg env e = go env 0 e
|
|
1001 | 996 | where
|
1002 | 997 | -- n is # value args to which the expression is applied
|
1003 | 998 | go env n (Var v)
|
... | ... | @@ -1005,8 +1000,6 @@ argSummary env e = go env 0 e |
1005 | 1000 | DoneId v' -> go_var n v'
|
1006 | 1001 | DoneEx e _ -> go (zapSubstEnv env) n e
|
1007 | 1002 | ContEx tvs cvs ids e -> go (setSubstEnv env tvs cvs ids) n e
|
1008 | - -- NB: substId looks up in the InScopeSet:
|
|
1009 | - -- we want to get as much IdInfo as possible
|
|
1010 | 1003 | |
1011 | 1004 | go _ _ (Lit l)
|
1012 | 1005 | | isLitRubbish l = TrivArg -- Leads to unproductive inlining in WWRec, #20035
|
... | ... | @@ -1469,11 +1462,18 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env |
1469 | 1462 | |
1470 | 1463 | one_occ IAmDead = True -- Happens in ((\x.1) v)
|
1471 | 1464 | one_occ OneOcc{ occ_n_br = 1
|
1472 | - , occ_in_lam = NotInsideLam
|
|
1473 | - , occ_int_cxt = int_cxt }
|
|
1474 | - = isNotTopLevel top_lvl -- Get rid of allocation
|
|
1475 | - || (int_cxt==IsInteresting && idArity bndr > 0) -- Function is applied
|
|
1476 | - -- || (early_phase && not (isConLikeUnfolding unf)) -- See early_phase
|
|
1465 | + , occ_in_lam = NotInsideLam }
|
|
1466 | + = isNotTopLevel top_lvl || sePhase env /= FinalPhase
|
|
1467 | + -- Inline even top level things if not inside lambda
|
|
1468 | + -- Can reduce simplifier iterations, when something is later
|
|
1469 | + -- inlining and becomes dead
|
|
1470 | + --
|
|
1471 | + -- But not in FinalPhase because that's just after we have
|
|
1472 | + -- carefully floated out constants to top level
|
|
1473 | + |
|
1474 | + -- = isNotTopLevel top_lvl -- Get rid of allocation
|
|
1475 | + -- || (int_cxt==IsInteresting && idArity bndr > 0) -- Function is applied
|
|
1476 | + -- OLD || (early_phase && not (isConLikeUnfolding unf)) -- See early_phase
|
|
1477 | 1477 | one_occ OneOcc{ occ_n_br = 1
|
1478 | 1478 | , occ_in_lam = IsInsideLam
|
1479 | 1479 | , occ_int_cxt = IsInteresting }
|
... | ... | @@ -60,7 +60,6 @@ initSimplMode :: DynFlags -> CompilerPhase -> String -> SimplMode |
60 | 60 | initSimplMode dflags phase name = SimplMode
|
61 | 61 | { sm_names = [name]
|
62 | 62 | , sm_phase = phase
|
63 | - , sm_first_iter = True
|
|
64 | 63 | , sm_rules = gopt Opt_EnableRewriteRules dflags
|
65 | 64 | , sm_eta_expand = gopt Opt_DoLambdaEtaExpansion dflags
|
66 | 65 | , sm_cast_swizzle = True
|