Simon Peyton Jones pushed to branch wip/case-bndr-unf at Glasgow Haskell Compiler / GHC
Commits:
-
04ba5bff
by Simon Peyton Jones at 2026-10-26T17:38:26+00:00
-
9e5f6245
by Simon Peyton Jones at 2026-10-26T17:38:26+00:00
-
7eda54bc
by Simon Peyton Jones at 2026-10-26T17:38:26+00:00
18 changed files:
- + changelog.d/T27962
- + changelog.d/T27963
- compiler/GHC/Core.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/HsToCore/Utils.hs
- compiler/GHC/Types/Id.hs
- + testsuite/tests/simplCore/should_compile/T27962.hs
- + testsuite/tests/simplCore/should_compile/T27963.hs
- + testsuite/tests/simplCore/should_compile/T27963.stderr
- + testsuite/tests/simplCore/should_compile/T27965.hs
- testsuite/tests/simplCore/should_compile/all.T
Changes:
| 1 | +section: compiler
|
|
| 2 | +issues: #27962
|
|
| 3 | +mrs: !16829
|
|
| 4 | +synopsis:
|
|
| 5 | + Fix a Lint error when using `runRW#` and `coerce` together
|
|
| 6 | +description:
|
|
| 7 | + Just an internal compiler bug, of long standing. |
| 1 | +section: compiler
|
|
| 2 | +issues: #27963
|
|
| 3 | +mrs: !16829
|
|
| 4 | +synopsis:
|
|
| 5 | + Fix a rather obscure interaction of `coerce` and RULES
|
|
| 6 | +description:
|
|
| 7 | + A `coerce` could prevent a RULE firing. |
| ... | ... | @@ -1393,6 +1393,151 @@ same way as above, otherwise the analysis would not be conservative wrt. the |
| 1393 | 1393 | lenient semantics (which includes the strict one). It is also much harder to
|
| 1394 | 1394 | explain and maintain, as it turned out.
|
| 1395 | 1395 | |
| 1396 | +Note [Core binder IdInfo invariants]
|
|
| 1397 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1398 | +We allow the following IdInfo on different sorts of Core binders.
|
|
| 1399 | +See the fields in GHC.Types.Id.Info.IdInfo:
|
|
| 1400 | + |
|
| 1401 | +We classify binders into
|
|
| 1402 | + * let-binders let x=rhs in body
|
|
| 1403 | + * lambda binders (\x. e)
|
|
| 1404 | + * case binders case e of x { ... }
|
|
| 1405 | + * case-alternative binders case e of _ { K x y -> ... }
|
|
| 1406 | + |
|
| 1407 | + Let Lambda Case/case-alt
|
|
| 1408 | + ---------------------------------------------
|
|
| 1409 | + Occurrence Yes Yes Yes
|
|
| 1410 | + |
|
| 1411 | + InlinePrag Yes No No
|
|
| 1412 | + Strictness (DmdSig) Yes No No
|
|
| 1413 | + CPR info (CprSig) Yes No No
|
|
| 1414 | + CAF Yes No No
|
|
| 1415 | + Arity Yes No No
|
|
| 1416 | + Call-arity Yes No No
|
|
| 1417 | + Rules (RuleInfo) Yes No No
|
|
| 1418 | + Unfolding Yes No(CBI1) evaldUnfolding only (CBI2)
|
|
| 1419 | + Demand info Yes Yes Yes
|
|
| 1420 | + One-shot No Yes No
|
|
| 1421 | + ------------------------------------------------
|
|
| 1422 | + |
|
| 1423 | +The predicate `GHC.Types.Id.lamBndrInfoOK` checks the Lambda and Case columns
|
|
| 1424 | +of this table (except one-shot info), and Core Lint applies it to every
|
|
| 1425 | +non-let binder (`lintIdBndr`).
|
|
| 1426 | + |
|
| 1427 | +Generally, lambda binders have only IdInfo that describes their /use/
|
|
| 1428 | +(e.g. occ-info, demand info) not their /definition/. See esp (CBI1).
|
|
| 1429 | + |
|
| 1430 | +Case and case-alternative binders are similar because again they lack a definition,
|
|
| 1431 | +and because they can /become/ a lambda binder when `mkDupableAlt` abstracts over them.
|
|
| 1432 | + |
|
| 1433 | +Places that must take care to maintain these invariants (#27965):
|
|
| 1434 | + |
|
| 1435 | +* The desugarer, when desugaring a strict binding let !x = rhs in body,
|
|
| 1436 | + generates case x of x { DEFAULT -> body }; the case binder must not inherit
|
|
| 1437 | + x's IdInfo. See `GHC.HsToCore.Utils.seqVar`.
|
|
| 1438 | + |
|
| 1439 | +* `GHC.Core.Utils.bindNonRec` (used by `mkCoreLet`, and hence by the
|
|
| 1440 | + Simplifier's `wrapFloats`), which turns let x = rhs in body into
|
|
| 1441 | + case rhs of x { DEFAULT -> body } when `rhs` is unlifted and not
|
|
| 1442 | + ok-for-speculation. Here `x` may well have a let-unfolding, e.g. one made
|
|
| 1443 | + by `makeTrivial`.
|
|
| 1444 | + |
|
| 1445 | +* `GHC.Core.Opt.SpecConstr.mkSeqs`, which builds case arg of arg' { DEFAULT -> rhs }
|
|
| 1446 | + where `arg` may be an imported Id with an unfolding.
|
|
| 1447 | + |
|
| 1448 | +All three use `GHC.Types.Id.mkCaseBndrFromLetBndr`.
|
|
| 1449 | + |
|
| 1450 | +* The Simplifier's `simplNonRecE` does not use a StrictBind continuation for a
|
|
| 1451 | + strict let-binding let x = rhs in body if `x` has RULES, a stable unfolding,
|
|
| 1452 | + or a non-default inline pragma; for if it did, `mkDupableContWithDmds` might
|
|
| 1453 | + turn `x` into the lambda binder of a join point. See `use_strict_bind`.
|
|
| 1454 | + |
|
| 1455 | +(CBI1) Based on #17530 and #21496 we never attach unfoldings of any kind to lambda
|
|
| 1456 | + binders, not even `evaldUnfolding`.
|
|
| 1457 | + |
|
| 1458 | + It's just too easy for the call site to change and invalidate the unfolding.
|
|
| 1459 | + E.g. the caller of the lambda drops a seq (e.g. because the lambda is strict
|
|
| 1460 | + in its binder) which in turn makes the OtherCon[] unfolding a lie. So
|
|
| 1461 | + unfoldings on lambda binders can never really be trusted when on lambda
|
|
| 1462 | + binders if there is the chance of the call site to change. So it's easiest to
|
|
| 1463 | + just never attach any to lambda binders to begin with, as well as stripping
|
|
| 1464 | + them off if we e.g. float out an expression while abstracting over some
|
|
| 1465 | + arguments.
|
|
| 1466 | + |
|
| 1467 | +(CBI2) See Note [Evaluated-ness on case binders]
|
|
| 1468 | + |
|
| 1469 | +(CBI3) Note that /occurrences/ may have IdInfo that is not present on the binder.
|
|
| 1470 | + Notably, consider case e of r { Just x -> ..r...; Nothing -> ...r... }
|
|
| 1471 | + The occurrence of `r` in the (Just x) branch will have an unfolding `Just x`,
|
|
| 1472 | + and similarly in the `Nothing` branch. But the /binder/ of `r` has only
|
|
| 1473 | + `evaldUnfolding` See Note [Evaluated-ness on case binders]
|
|
| 1474 | + |
|
| 1475 | +Note [Evaluated-ness on case binders]
|
|
| 1476 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1477 | +The binding site of an Id in case expression (case-binder or case alternative) may
|
|
| 1478 | +carry an `OtherCon []` (aka `evaldUnfolding`). meaning "this variable is certainly
|
|
| 1479 | +evaluated". Specifically:
|
|
| 1480 | + |
|
| 1481 | +* Case binders are always evaluated. `GHC.Core.Opt.Simplify.Iteration.simplAlts` and
|
|
| 1482 | + CorePrep add `evaldUnfolding` to every case binder.
|
|
| 1483 | + |
|
| 1484 | +* Case-alternative binders for strict constructor fields
|
|
| 1485 | + binders)
|
|
| 1486 | + data T = MkT !Int Int
|
|
| 1487 | + case x of MkT y z -> ...
|
|
| 1488 | + `y` gets an evaldUnfolding.
|
|
| 1489 | + |
|
| 1490 | + This is done by `GHC.Core.Utils.dataConRepFSInstPat` (used by the interface-file loader,
|
|
| 1491 | + among others), `GHC.Core.SimpleOpt`, the Simplifier (`adjustFieldsIdInfo`), and
|
|
| 1492 | + worker/wrapper (for the argument and CPR result binders it makes;
|
|
| 1493 | + see Note [Record evaluated-ness in worker/wrapper] in GHC.Core.Opt.WorkWrap.Utils).
|
|
| 1494 | + |
|
| 1495 | +Why is this information on the /binder/? Within the Simplifier it is not
|
|
| 1496 | +needed there: in each case alternative the Simplifier adds a more precise
|
|
| 1497 | +unfolding for the case binder (and evaluated-ness for strict-field binders) to
|
|
| 1498 | +its in-scope set, and refreshes every occurrence from that. But many other
|
|
| 1499 | +passes rebuild variable occurrences /from the binder/: substitution-based
|
|
| 1500 | +passes (SimpleOpt, Specialise, SpecConstr, CSE), SetLevels/FloatOut, the binder
|
|
| 1501 | +swap in the occurrence analyser, CoreTidy, and CorePrep. After such a pass,
|
|
| 1502 | +an occurrence knows that the variable is evaluated only if the binder does.
|
|
| 1503 | + |
|
| 1504 | +That knowledge is used, mainly via `exprIsHNF`/`varIsHNF` (not by
|
|
| 1505 | +`exprOkForSpeculation`; see Note [exprOkForSpeculation and evaluated variables]
|
|
| 1506 | +in GHC.Core.Utils), by:
|
|
| 1507 | + |
|
| 1508 | +* CorePrep: deciding whether a let-binding is a value (allocate directly) or
|
|
| 1509 | + a thunk, e.g. `let x = Box y` where `y` is a strict field.
|
|
| 1510 | + See Note [Pin evaluatedness on floats] in GHC.CoreToStg.Prep. CorePrep runs
|
|
| 1511 | + just after CoreTidy, which propagates binder IdInfo to occurrences.
|
|
| 1512 | + |
|
| 1513 | +* SetLevels/FloatOut: floating single-alternative cases out of loops, when the
|
|
| 1514 | + scrutinee is evaluated; see Note [Floating single-alternative cases] in
|
|
| 1515 | + GHC.Core.Opt.SetLevels. Also the call-by-value marks given to abstracted
|
|
| 1516 | + variables (`GHC.Types.Id.transferPolyIdInfo`).
|
|
| 1517 | + |
|
| 1518 | +* Worker/wrapper: `move_transit_vars` avoids an unboxed 1-tuple for a single
|
|
| 1519 | + evaluated transit variable (test T18109); and the CPR result binders of the
|
|
| 1520 | + wrapper remain evaluated (tests T13077a, #13027). The latter matters because
|
|
| 1521 | + unboxed-tuple alternatives take a fast path in the Simplifier's
|
|
| 1522 | + `adjustFieldsIdInfo`, and so get evaluated-ness only from the binder.
|
|
| 1523 | + |
|
| 1524 | +* SimpleOpt: eliminating a case on an evaluated variable, and `mkFieldSeqFloats`.
|
|
| 1525 | + |
|
| 1526 | +* Minor heuristic uses: FloatIn (the late FloatIn runs after FloatOut and CSE
|
|
| 1527 | + with no Simplifier in between) and occurrences created by CSE or the binder
|
|
| 1528 | + swap, until the next Simplifier run.
|
|
| 1529 | + |
|
| 1530 | +Core Lint does /not/ depend on this information. Nor does anything in STG or
|
|
| 1531 | +tag inference.
|
|
| 1532 | + |
|
| 1533 | +Removing the information from the binders would require these passes to track
|
|
| 1534 | +evaluated-ness in an environment instead (as SpecConstr already does with its
|
|
| 1535 | +ValueEnv), which they currently don't. So we allow an OtherCon unfolding (and
|
|
| 1536 | +only that) on case binders and case-alternative binders:
|
|
| 1537 | +see the table in Note [Core binder IdInfo invariants]
|
|
| 1538 | + |
|
| 1539 | + |
|
| 1540 | + |
|
| 1396 | 1541 | ************************************************************************
|
| 1397 | 1542 | * *
|
| 1398 | 1543 | In/Out type synonyms
|
| ... | ... | @@ -1742,16 +1887,6 @@ floatBinders (FloatTick {}) = [] |
| 1742 | 1887 | |
| 1743 | 1888 | The @Unfolding@ type is declared here to avoid numerous loops
|
| 1744 | 1889 | |
| 1745 | -Note [Never put `OtherCon` unfoldings on lambda binders]
|
|
| 1746 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1747 | -Based on #21496 we never attach unfoldings of any kind to lambda binders.
|
|
| 1748 | -It's just too easy for the call site to change and invalidate the unfolding.
|
|
| 1749 | -E.g. the caller of the lambda drops a seq (e.g. because the lambda is strict in it's binder)
|
|
| 1750 | -which in turn makes the OtherCon[] unfolding a lie.
|
|
| 1751 | -So unfoldings on lambda binders can never really be trusted when on lambda binders if there
|
|
| 1752 | -is the chance of the call site to change. So it's easiest to just never attach any
|
|
| 1753 | -to lambda binders to begin with, as well as stripping them off if we e.g. float out
|
|
| 1754 | -and expression while abstracting over some arguments.
|
|
| 1755 | 1890 | -}
|
| 1756 | 1891 | |
| 1757 | 1892 | -- | Records the /unfolding/ of an identifier, which is approximately the form the
|
| ... | ... | @@ -1858,6 +1858,15 @@ lintIdBndr top_lvl bind_site id thing_inside |
| 1858 | 1858 | hang (text "Lambda binder" <+> quotes (ppr id) <+> text "has an unfolding")
|
| 1859 | 1859 | 2 (ppr unf)
|
| 1860 | 1860 | |
| 1861 | + -- Check that lambda, case, and case-alternative binders have
|
|
| 1862 | + -- only the IdInfo permitted by the table in
|
|
| 1863 | + -- Note [Core binder IdInfo invariants] in GHC.Core
|
|
| 1864 | + ; checkL (is_let_bind || lamBndrInfoOK id) $
|
|
| 1865 | + hang (text "Non-let binder" <+> quotes (ppr id)
|
|
| 1866 | + <+> text "has IdInfo that only a let-binder may have")
|
|
| 1867 | + 2 (vcat [ text "Binding site:" <+> text (show_site bind_site)
|
|
| 1868 | + , text "IdInfo:" <+> ppr (idInfo id) ])
|
|
| 1869 | + |
|
| 1861 | 1870 | ; addLoc (IdTy id) (lintValueType id_ty)
|
| 1862 | 1871 | |
| 1863 | 1872 | ; addInScopeId id thing_inside }
|
| ... | ... | @@ -1869,6 +1878,12 @@ lintIdBndr top_lvl bind_site id thing_inside |
| 1869 | 1878 | LetBind -> True
|
| 1870 | 1879 | _ -> False
|
| 1871 | 1880 | |
| 1881 | + show_site :: BindingSite -> String
|
|
| 1882 | + show_site LambdaBind = "lambda"
|
|
| 1883 | + show_site CaseBind = "case binder"
|
|
| 1884 | + show_site CasePatBind = "case alternative"
|
|
| 1885 | + show_site LetBind = "let"
|
|
| 1886 | + |
|
| 1872 | 1887 | {-
|
| 1873 | 1888 | %************************************************************************
|
| 1874 | 1889 | %* *
|
| ... | ... | @@ -28,7 +28,7 @@ module GHC.Core.Opt.Simplify.Env ( |
| 28 | 28 | SimplEnvIS, checkSimplEnvIS, pprBadSimplEnvIS,
|
| 29 | 29 | |
| 30 | 30 | -- * Substitution results
|
| 31 | - SimplSR(..), substId, lookupRecBndr,
|
|
| 31 | + SimplClo(..), simplCloExpr, substId, lookupRecBndr,
|
|
| 32 | 32 | |
| 33 | 33 | -- * Simplifying 'Id' binders
|
| 34 | 34 | simplNonRecBndr, simplNonRecJoinBndr, simplRecBndrs, simplRecJoinBndrs,
|
| ... | ... | @@ -61,7 +61,7 @@ import GHC.Core.Opt.Simplify.Monad |
| 61 | 61 | import GHC.Core.Rules.Config ( RuleOpts(..) )
|
| 62 | 62 | import GHC.Core
|
| 63 | 63 | import GHC.Core.Utils
|
| 64 | -import GHC.Core.Subst( substExprSC )
|
|
| 64 | +import GHC.Core.Subst( substExpr )
|
|
| 65 | 65 | import GHC.Core.Unfold
|
| 66 | 66 | import GHC.Core.TyCo.Subst (emptyIdSubstEnv, mkSubst)
|
| 67 | 67 | import GHC.Core.Multiplicity( Scaled(..), mkMultMul )
|
| ... | ... | @@ -470,18 +470,26 @@ pprSimplEnv env |
| 470 | 470 | ppr_one v | isId v = ppr v <+> ppr (idUnfolding v)
|
| 471 | 471 | | otherwise = ppr v
|
| 472 | 472 | |
| 473 | -type SimplIdSubst = IdEnv SimplSR -- IdId |--> OutExpr
|
|
| 473 | +type SimplIdSubst = IdEnv SimplClo -- IdId |--> OutExpr
|
|
| 474 | 474 | -- See Note [Extending the IdSubstEnv] in GHC.Core.Subst
|
| 475 | 475 | |
| 476 | --- | A substitution result.
|
|
| 477 | -data SimplSR
|
|
| 476 | +-- | A "closure" used in the Simplifier. It is used
|
|
| 477 | +-- * as the range of the substitution, 'SimplIdSubst'
|
|
| 478 | +-- * as the argument in an 'ApplyToVal' continuation
|
|
| 479 | +-- Roughly: either an (InExpr, StaticEnv) pair for an
|
|
| 480 | +-- as-yet-unsimplified expression
|
|
| 481 | +-- or an OutExpr, for an already-simplified one
|
|
| 482 | +-- It's a bit like thunk: we may "evaluate" the SimplClo in a ApplyToVal
|
|
| 483 | +-- and thereby transform it from `ContEx` to `DoneEx`
|
|
| 484 | +-- This happens in the `ApplyToVal` case of `mkDupableContWithDmds`
|
|
| 485 | +-- See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils
|
|
| 486 | +data SimplClo
|
|
| 478 | 487 | = DoneEx OutExpr JoinPointHood
|
| 479 | 488 | -- If x :-> DoneEx e ja is in the SimplIdSubst
|
| 480 | 489 | -- then replace occurrences of x by e
|
| 481 | 490 | -- and ja = Just a <=> x is a join-point of arity a
|
| 482 | 491 | -- See Note [Join arity in SimplIdSubst]
|
| 483 | 492 | |
| 484 | - |
|
| 485 | 493 | | DoneId OutId
|
| 486 | 494 | -- If x :-> DoneId v is in the SimplIdSubst
|
| 487 | 495 | -- then replace occurrences of x by v
|
| ... | ... | @@ -490,11 +498,11 @@ data SimplSR |
| 490 | 498 | |
| 491 | 499 | | ContEx SimplEnv
|
| 492 | 500 | InExpr
|
| 493 | - MOutCoercion -- See Note [The sc_cast field of ApplyToVal]
|
|
| 501 | + MOutCoercion -- See Note [The MOutCoercion field of ContEx]
|
|
| 494 | 502 | -- If x :-> ContEx static_env e mco is in the SimplISubst
|
| 495 | 503 | -- then replace occurrences of x by (subst static_env e) |> mco
|
| 496 | 504 | |
| 497 | -instance Outputable SimplSR where
|
|
| 505 | +instance Outputable SimplClo where
|
|
| 498 | 506 | ppr (DoneId v) = text "DoneId" <+> ppr v
|
| 499 | 507 | ppr (DoneEx e mj) = text "DoneEx" <> pp_mj <+> ppr e
|
| 500 | 508 | where
|
| ... | ... | @@ -637,7 +645,7 @@ reSimplifying :: SimplEnv -> Bool |
| 637 | 645 | reSimplifying (SimplEnv { seInlineDepth = n }) = n>0
|
| 638 | 646 | |
| 639 | 647 | ---------------------
|
| 640 | -extendIdSubst :: SimplEnv -> Id -> SimplSR -> SimplEnv
|
|
| 648 | +extendIdSubst :: SimplEnv -> Id -> SimplClo -> SimplEnv
|
|
| 641 | 649 | extendIdSubst env@(SimplEnv {seIdSubst = subst}) var res
|
| 642 | 650 | = assertPpr (isId var && not (isCoVar var)) (ppr var) $
|
| 643 | 651 | env { seIdSubst = extendVarEnv subst var res }
|
| ... | ... | @@ -1032,7 +1040,7 @@ So we want to look up the inner X.g_34 in the substitution, where we'll |
| 1032 | 1040 | find that it has been substituted by b. (Or conceivably cloned.)
|
| 1033 | 1041 | -}
|
| 1034 | 1042 | |
| 1035 | -substId :: SimplEnv -> InId -> SimplSR
|
|
| 1043 | +substId :: SimplEnv -> InId -> SimplClo
|
|
| 1036 | 1044 | -- Returns DoneEx only on a non-Var expression
|
| 1037 | 1045 | substId (SimplEnv { seInScope = in_scope, seIdSubst = ids }) v
|
| 1038 | 1046 | = case lookupVarEnv ids v of -- Note [Global Ids in the substitution]
|
| ... | ... | @@ -1364,15 +1372,18 @@ getTCvSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seCvSubst = cv |
| 1364 | 1372 | |
| 1365 | 1373 | getFullSubst :: InScopeSet -> SimplEnv -> Subst
|
| 1366 | 1374 | getFullSubst in_scope (SimplEnv { seIdSubst = id_env, seTvSubst = tv_env, seCvSubst = cv_env })
|
| 1367 | - = mkSubst in_scope (mapVarEnv to_expr id_env) tv_env cv_env
|
|
| 1375 | + = mkSubst in_scope (mapVarEnv (simplCloExpr in_scope) id_env) tv_env cv_env
|
|
| 1376 | + |
|
| 1377 | +simplCloExpr :: InScopeSet -> SimplClo -> OutExpr
|
|
| 1378 | +-- Turn a SimplClo into an OutExpr, by applying the substitution
|
|
| 1379 | +-- (if any) and the pending cast (if any)
|
|
| 1380 | +simplCloExpr _ (DoneEx e _) = e
|
|
| 1381 | +simplCloExpr _ (DoneId v) = Var v
|
|
| 1382 | +simplCloExpr in_scope (ContEx env e mco) = mkCastMCo e' mco
|
|
| 1368 | 1383 | where
|
| 1369 | - to_expr :: SimplSR -> CoreExpr
|
|
| 1370 | - -- A tiresome impedence-matcher
|
|
| 1371 | - to_expr (DoneEx e _) = e
|
|
| 1372 | - to_expr (DoneId v) = Var v
|
|
| 1373 | - to_expr (ContEx env e mco) = mkCastMCo e' mco
|
|
| 1374 | - where
|
|
| 1375 | - e' = GHC.Core.Subst.substExprSC (getFullSubst in_scope env) e
|
|
| 1384 | + e' = GHC.Core.Subst.substExpr (getFullSubst in_scope env) e
|
|
| 1385 | + -- NB: we use substExpr, not substExprSC: we want to get the benefit of
|
|
| 1386 | + -- knowing what is evaluated etc, via the in-scope set
|
|
| 1376 | 1387 | |
| 1377 | 1388 | substTy :: HasDebugCallStack => SimplEnv -> Type -> Type
|
| 1378 | 1389 | substTy env ty = Type.substTy (getTCvSubst env) ty
|
| ... | ... | @@ -285,8 +285,8 @@ simplRecOrTopPair :: SimplEnv |
| 285 | 285 | -> SimplM (SimplFloats, SimplEnv)
|
| 286 | 286 | |
| 287 | 287 | simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
|
| 288 | - | Just env' <- preInlineUnconditionally env (bindContextLevel bind_cxt)
|
|
| 289 | - old_bndr (UnSimplified env) rhs MRefl
|
|
| 288 | + | Just env' <- preInlineLetUnconditionally env (bindContextLevel bind_cxt)
|
|
| 289 | + old_bndr rhs env
|
|
| 290 | 290 | = {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
|
| 291 | 291 | simplTrace "SimplBindr:inline-uncond1" (ppr old_bndr) $
|
| 292 | 292 | do { tick (PreInlineUnconditionally old_bndr)
|
| ... | ... | @@ -1226,17 +1226,8 @@ simplExprF1 env (Tick t expr) cont = {-#SCC "simplTick" #-} simplTick env t exp |
| 1226 | 1226 | simplExprF1 env (Coercion co) cont = {-#SCC "simplCoercionF" #-} simplCoercionF env co cont
|
| 1227 | 1227 | |
| 1228 | 1228 | simplExprF1 env (Cast body co) cont
|
| 1229 | - = do { co1 <- {-#SCC "simplCast-simplCoercion" #-}
|
|
| 1230 | - simplCoercion env co
|
|
| 1231 | - |
|
| 1232 | - ; let cont1 = {-#SCC "simplCast-addCoerce" #-}
|
|
| 1233 | - if isReflCo co1
|
|
| 1234 | - then cont -- See Note [Optimising reflexivity]
|
|
| 1235 | - else pushCast env co1 cont
|
|
| 1236 | - -- True <=> co1 is optimised
|
|
| 1237 | - |
|
| 1238 | - ; {-#SCC "simplCast-simplExprF" #-}
|
|
| 1239 | - simplExprF env body cont1 }
|
|
| 1229 | + = do { co1 <- simplCoercion env co
|
|
| 1230 | + ; simplExprF env body (pushCast env co1 cont) }
|
|
| 1240 | 1231 | |
| 1241 | 1232 | simplExprF1 env (App fun arg) cont
|
| 1242 | 1233 | = {-#SCC "simplExprF1-App" #-} case arg of
|
| ... | ... | @@ -1264,9 +1255,9 @@ simplExprF1 env (App fun arg) cont |
| 1264 | 1255 | -- observed the quadratic behavior, so this extra entanglement
|
| 1265 | 1256 | -- seems not worthwhile.
|
| 1266 | 1257 | simplExprF env fun $
|
| 1267 | - ApplyToVal { sc_arg = arg, sc_env = UnSimplified env
|
|
| 1258 | + ApplyToVal { sc_arg = ContEx env arg MRefl, sc_dup = NoDup
|
|
| 1268 | 1259 | , sc_hole_ty = substTy env (exprType fun)
|
| 1269 | - , sc_cast = MRefl, sc_cont = cont }
|
|
| 1260 | + , sc_cont = cont }
|
|
| 1270 | 1261 | |
| 1271 | 1262 | simplExprF1 env expr@(Lam {}) cont
|
| 1272 | 1263 | = {-#SCC "simplExprF1-Lam" #-}
|
| ... | ... | @@ -1301,7 +1292,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont |
| 1301 | 1292 | do { ty' <- simplType env ty
|
| 1302 | 1293 | ; simplExprF (extendTvSubst env bndr ty') body cont }
|
| 1303 | 1294 | |
| 1304 | - | Just env' <- preInlineUnconditionally env NotTopLevel bndr (UnSimplified env) rhs MRefl
|
|
| 1295 | + | Just env' <- preInlineLetUnconditionally env NotTopLevel bndr rhs env
|
|
| 1305 | 1296 | -- Because of the let-can-float invariant, it's ok to
|
| 1306 | 1297 | -- inline freely, or to drop the binding if it is dead.
|
| 1307 | 1298 | = do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr) $
|
| ... | ... | @@ -1637,9 +1628,8 @@ rebuild_go env expr cont |
| 1637 | 1628 | ApplyToTy { sc_arg_ty = ty, sc_cont = cont}
|
| 1638 | 1629 | -> rebuild_go env (App expr (Type ty)) cont
|
| 1639 | 1630 | |
| 1640 | - ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
|
|
| 1641 | - , sc_cont = cont, sc_hole_ty = fun_ty }
|
|
| 1642 | - -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
|
|
| 1631 | + ApplyToVal { sc_arg = arg, sc_cont = cont, sc_hole_ty = fun_ty }
|
|
| 1632 | + -> do { arg' <- simplArg env Nothing fun_ty arg
|
|
| 1643 | 1633 | ; rebuild_go env (App expr arg') cont }
|
| 1644 | 1634 | |
| 1645 | 1635 | completeBindX :: SimplEnv
|
| ... | ... | @@ -1653,6 +1643,7 @@ completeBindX env from_what bndr rhs body cont |
| 1653 | 1643 | | FromBeta arg_levity <- from_what
|
| 1654 | 1644 | , needsCaseBindingL arg_levity rhs -- Enforcing the let-can-float-invariant
|
| 1655 | 1645 | = do { (env1, bndr1) <- simplNonRecBndr env bndr -- Lambda binders don't have rules
|
| 1646 | + -- See Note [Core binder IdInfo invariants] in GHC.Core
|
|
| 1656 | 1647 | ; (floats, expr') <- simplNonRecBody env1 from_what body cont
|
| 1657 | 1648 | -- Do not float floats past the Case binder below
|
| 1658 | 1649 | ; let expr'' = wrapFloats floats expr'
|
| ... | ... | @@ -1686,69 +1677,12 @@ completeBindX env from_what bndr rhs body cont |
| 1686 | 1677 | ; let all_floats = rhs_floats `addFloats` bind_float `addFloats` body_floats
|
| 1687 | 1678 | ; return ( all_floats, body' ) }
|
| 1688 | 1679 | |
| 1689 | -{-
|
|
| 1690 | -************************************************************************
|
|
| 1680 | + |
|
| 1681 | +{- *********************************************************************
|
|
| 1691 | 1682 | * *
|
| 1692 | -\subsection{Lambdas}
|
|
| 1683 | + Arguments
|
|
| 1693 | 1684 | * *
|
| 1694 | -************************************************************************
|
|
| 1695 | --}
|
|
| 1696 | - |
|
| 1697 | -{- Note [Optimising reflexivity]
|
|
| 1698 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1699 | -It's important (for compiler performance) to get rid of reflexivity as soon
|
|
| 1700 | -as it appears. See #11735, #14737, and #15019.
|
|
| 1701 | - |
|
| 1702 | -In particular, we want to behave well on
|
|
| 1703 | - |
|
| 1704 | - * e |> co1 |> co2
|
|
| 1705 | - where the two happen to cancel out entirely. That is quite common;
|
|
| 1706 | - e.g. a newtype wrapping and unwrapping cancel.
|
|
| 1707 | - |
|
| 1708 | - |
|
| 1709 | - * (f |> co) @t1 @t2 ... @tn x1 .. xm
|
|
| 1710 | - Here we will use pushCoTyArg and pushCoValArg successively, which
|
|
| 1711 | - build up SelCo stacks. Silly to do that if co is reflexive.
|
|
| 1712 | - |
|
| 1713 | -However, we don't want to call isReflexiveCo too much, because it uses
|
|
| 1714 | -type equality which is expensive on big types (#14737 comment:7).
|
|
| 1715 | - |
|
| 1716 | -A good compromise (determined experimentally) seems to be to call
|
|
| 1717 | -isReflexiveCo
|
|
| 1718 | - * when composing casts, and
|
|
| 1719 | - * at the end
|
|
| 1720 | - |
|
| 1721 | -In investigating this I saw missed opportunities for on-the-fly
|
|
| 1722 | -coercion shrinkage. See #15090.
|
|
| 1723 | - |
|
| 1724 | -Note [Avoid re-simplifying coercions]
|
|
| 1725 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1726 | -In some benchmarks (with deeply nested cases) we successively push
|
|
| 1727 | -casts onto the SimplCont. We don't want to call the coercion optimiser
|
|
| 1728 | -on each successive composition -- that's at least quadratic. So:
|
|
| 1729 | - |
|
| 1730 | -* The CastIt constructor in SimplCont has a `sc_opt :: Bool` flag to
|
|
| 1731 | - record whether the coercion optimiser has been applied to the coercion.
|
|
| 1732 | - |
|
| 1733 | -* In `simplCast`, when we see (Cast e co), we simplify `co` to get
|
|
| 1734 | - an OutCoercion, and built a CastIt with sc_opt=True.
|
|
| 1735 | - |
|
| 1736 | - Actually not quite: if we are simplifying the result of inlining an
|
|
| 1737 | - unfolding (seInlineDepth > 0), then instead of /optimising/ it again,
|
|
| 1738 | - just /substitute/ which is cheaper. See `simplCoercion`.
|
|
| 1739 | - |
|
| 1740 | -* In `pushCast` if we combine this new coercion with an existing one,
|
|
| 1741 | - we build a CastIt for (co1 ; co2) with sc_opt=False.
|
|
| 1742 | - |
|
| 1743 | -* When unpacking a CastIt, in `rebuild`, we optimise the (presumably
|
|
| 1744 | - composed) coercion if sc_opt=False; this is done by `optOutCoercion`.
|
|
| 1745 | - |
|
| 1746 | -* When duplicating a continuation in `mkDupableContWithDmds`, before
|
|
| 1747 | - duplicating a CastIt, optimise the coercion. Otherwise we'll end up
|
|
| 1748 | - optimising it separately in the duplicate copies.
|
|
| 1749 | - |
|
| 1750 | -* See also Note [The sc_cast field of ApplyToVal] in GHC.Core.Opt.Simplify.Utils.
|
|
| 1751 | --}
|
|
| 1685 | +********************************************************************* -}
|
|
| 1752 | 1686 | |
| 1753 | 1687 | simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet
|
| 1754 | 1688 | -> Maybe ArgInfo -- ^ Just <=> This arg `ai` occurs in an app
|
| ... | ... | @@ -1756,15 +1690,12 @@ simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet |
| 1756 | 1690 | -- how `f` uses `ai`, affecting the Stop
|
| 1757 | 1691 | -- continuation passed to 'simplExprC'
|
| 1758 | 1692 | -> OutType -- ^ Type of the function applied to this arg
|
| 1759 | - -> StaticEnv -> CoreExpr -- ^ Expression with its static envt
|
|
| 1760 | - -> MOutCoercion -- Wrap this around the result
|
|
| 1693 | + -> SimplClo -- ^ The argument
|
|
| 1761 | 1694 | -> SimplM OutExpr
|
| 1762 | -simplArg _ _ _ (Simplified {}) arg mco
|
|
| 1763 | - = -- See Note [Avoid repeated simplification]
|
|
| 1764 | - case mco of
|
|
| 1765 | - MRefl -> return arg -- Vastly common case
|
|
| 1766 | - MCo co -> return (mkCast arg co)
|
|
| 1767 | -simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco
|
|
| 1695 | +-- See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils
|
|
| 1696 | +simplArg _ _ _ (DoneEx arg _) = return arg -- See Note [Avoid repeated simplification]
|
|
| 1697 | +simplArg _ _ _ (DoneId v) = return (Var v)
|
|
| 1698 | +simplArg env mb_arg_info fun_ty (ContEx arg_se arg mco)
|
|
| 1768 | 1699 | = do { let arg_env' = arg_se `setInScopeFromE` env
|
| 1769 | 1700 | arg_ty = funArgTy fun_ty
|
| 1770 | 1701 | stop = case mb_arg_info of
|
| ... | ... | @@ -1773,13 +1704,12 @@ simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco |
| 1773 | 1704 | cont = addCastMCo mco stop
|
| 1774 | 1705 | ; simplExprC arg_env' arg cont }
|
| 1775 | 1706 | |
| 1776 | -{-
|
|
| 1777 | -************************************************************************
|
|
| 1707 | + |
|
| 1708 | +{- *********************************************************************
|
|
| 1778 | 1709 | * *
|
| 1779 | -\subsection{Lambdas}
|
|
| 1710 | + Lambdas
|
|
| 1780 | 1711 | * *
|
| 1781 | -************************************************************************
|
|
| 1782 | --}
|
|
| 1712 | +********************************************************************* -}
|
|
| 1783 | 1713 | |
| 1784 | 1714 | simplNonRecBody :: SimplEnv -> FromWhat
|
| 1785 | 1715 | -> InExpr -> SimplCont
|
| ... | ... | @@ -1806,13 +1736,9 @@ simpl_lam env bndr body (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = cont }) |
| 1806 | 1736 | |
| 1807 | 1737 | -- Value beta-reduction
|
| 1808 | 1738 | -- This works for /coercion/ lambdas too
|
| 1809 | -simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
|
|
| 1810 | - , sc_cast = arg_mco, sc_cont = cont
|
|
| 1739 | +simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_cont = cont
|
|
| 1811 | 1740 | , sc_hole_ty = fun_ty})
|
| 1812 | - | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg_se arg arg_mco
|
|
| 1813 | - , not (needsCaseBindingL arg_levity arg)
|
|
| 1814 | - -- Ok to test arg::InExpr in needsCaseBinding because
|
|
| 1815 | - -- exprOkForSpeculation is stable under simplification
|
|
| 1741 | + | Just env' <- preInlineBetaUnconditionally env arg_levity bndr arg
|
|
| 1816 | 1742 | = simplTrace "SimplBindr:inline-uncond3"
|
| 1817 | 1743 | (ppr bndr <+> text ":=" <+> ppr arg) $
|
| 1818 | 1744 | do { tick (BetaReduction bndr)
|
| ... | ... | @@ -1823,14 +1749,14 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se |
| 1823 | 1749 | = do { tick (BetaReduction bndr)
|
| 1824 | 1750 | ; let from_what = FromBeta arg_levity
|
| 1825 | 1751 | |
| 1826 | - ; case (arg_se, arg_mco) of
|
|
| 1827 | - (UnSimplified arg_env, MRefl)
|
|
| 1752 | + ; case arg of
|
|
| 1753 | + ContEx arg_env arg_expr MRefl
|
|
| 1828 | 1754 | -- Optimisation: when there is no wrapping coercion use simplNonRecE
|
| 1829 | 1755 | -- so that the clever floating out of let-bindings can take place
|
| 1830 | 1756 | -- in this round of the Simplifier
|
| 1831 | - -> simplNonRecE env from_what bndr (arg, arg_env) body cont
|
|
| 1757 | + -> simplNonRecE env from_what bndr (arg_expr, arg_env) body cont
|
|
| 1832 | 1758 | |
| 1833 | - _ -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
|
|
| 1759 | + _ -> do { arg' <- simplArg env Nothing fun_ty arg
|
|
| 1834 | 1760 | ; completeBindX env from_what bndr arg' body cont }
|
| 1835 | 1761 | }
|
| 1836 | 1762 | where
|
| ... | ... | @@ -1869,7 +1795,7 @@ simplLamBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr) |
| 1869 | 1795 | -- could have a stable unfolding;
|
| 1870 | 1796 | -- see Historical Note [Case binders and join points]
|
| 1871 | 1797 | -- But now it is much simpler! We now only remove unfoldings.
|
| 1872 | --- See Note [Never put `OtherCon` unfoldings on lambda binders]
|
|
| 1798 | +-- See (CBI1) in Note [Core binder IdInfo invariants]
|
|
| 1873 | 1799 | simplLamBndr env bndr = simplBinder env (zapIdUnfolding bndr)
|
| 1874 | 1800 | |
| 1875 | 1801 | simplLamBndrs :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [OutBndr])
|
| ... | ... | @@ -1903,7 +1829,7 @@ simplNonRecE :: HasDebugCallStack |
| 1903 | 1829 | |
| 1904 | 1830 | simplNonRecE env from_what bndr (rhs, rhs_se) body cont
|
| 1905 | 1831 | | assert (isId bndr && not (isJoinId bndr) ) $
|
| 1906 | - is_strict_bind
|
|
| 1832 | + use_strict_bind
|
|
| 1907 | 1833 | = -- Evaluate RHS strictly
|
| 1908 | 1834 | simplExprF (rhs_se `setInScopeFromE` env) rhs
|
| 1909 | 1835 | (StrictBind { sc_bndr = bndr, sc_body = body, sc_from = from_what
|
| ... | ... | @@ -1918,14 +1844,31 @@ simplNonRecE env from_what bndr (rhs, rhs_se) body cont |
| 1918 | 1844 | ; return (floats1 `addFloats` floats2, expr') }
|
| 1919 | 1845 | |
| 1920 | 1846 | where
|
| 1921 | - is_strict_bind = case from_what of
|
|
| 1922 | - FromBeta Unlifted -> True
|
|
| 1847 | + info = idInfo bndr
|
|
| 1848 | + |
|
| 1849 | + use_strict_bind
|
|
| 1923 | 1850 | -- If we are coming from a beta-reduction (FromBeta) we must
|
| 1924 | - -- establish the let-can-float invariant, so go via StrictBind
|
|
| 1851 | + -- establish the let-can-float invariant, so we must go via StrictBind
|
|
| 1925 | 1852 | -- If not, the invariant holds already, and it's optional.
|
| 1853 | + | FromBeta Unlifted <- from_what
|
|
| 1854 | + = True
|
|
| 1855 | + |
|
| 1856 | + -- Not if the demand is non-strict
|
|
| 1857 | + | not (isStrUsedDmd (demandInfo info))
|
|
| 1858 | + = False
|
|
| 1859 | + |
|
| 1860 | + -- Not if case-of-case is off
|
|
| 1861 | + -- See (SB1) in Note [StrictBind]
|
|
| 1862 | + | not (seCaseCase env)
|
|
| 1863 | + = False
|
|
| 1864 | + |
|
| 1865 | + -- Not for things with RULES or INLINE or NOINLINE
|
|
| 1866 | + -- See (SB3) in Note [StrictBind]
|
|
| 1867 | + | FromLet <- from_what
|
|
| 1868 | + , not (lamBndrInfoOK bndr)
|
|
| 1869 | + = False
|
|
| 1926 | 1870 | |
| 1927 | - -- (FromBeta Lifted) or FromLet: look at the demand info
|
|
| 1928 | - _ -> seCaseCase env && isStrUsedDmd (idDemandInfo bndr)
|
|
| 1871 | + | otherwise = True
|
|
| 1929 | 1872 | |
| 1930 | 1873 | |
| 1931 | 1874 | ------------------
|
| ... | ... | @@ -2262,11 +2205,14 @@ simplOutId env fun cont |
| 2262 | 2205 | | fun `hasKey` runRWKey
|
| 2263 | 2206 | , ApplyToTy { sc_cont = cont1 } <- cont
|
| 2264 | 2207 | , ApplyToTy { sc_cont = cont2, sc_arg_ty = hole_ty } <- cont1
|
| 2265 | - , ApplyToVal { sc_cont = cont3, sc_arg = arg, sc_cast = arg_mco
|
|
| 2266 | - , sc_env = arg_se, sc_hole_ty = fun_ty } <- cont2
|
|
| 2208 | + , ApplyToVal { sc_cont = cont3, sc_arg = arg_clo, sc_hole_ty = fun_ty } <- cont2
|
|
| 2267 | 2209 | -- Do this even if (contIsStop cont), or if seCaseCase is off.
|
| 2268 | 2210 | -- See Note [No eta-expansion in runRW#]
|
| 2269 | - = do { let (_saf,arg_env) = mkAltEnv env arg_se
|
|
| 2211 | + = do { let (arg_env, arg, arg_mco)
|
|
| 2212 | + = case arg_clo of
|
|
| 2213 | + ContEx se e mco -> (se `setInScopeFromE` env, e, mco)
|
|
| 2214 | + DoneEx e _ -> (env, e, MRefl)
|
|
| 2215 | + DoneId v -> (env, Var v, MRefl)
|
|
| 2270 | 2216 | |
| 2271 | 2217 | overall_res_ty = contResultType cont3
|
| 2272 | 2218 | -- hole_ty is the type of the current runRW# application
|
| ... | ... | @@ -2281,23 +2227,32 @@ simplOutId env fun cont |
| 2281 | 2227 | -- * If we don't do this we get a beta-redex every time, so the
|
| 2282 | 2228 | -- simplifier keeps doing more iterations.
|
| 2283 | 2229 | -- * Even more important: see Note [No eta-expansion in runRW#]
|
| 2230 | + --
|
|
| 2231 | + -- But only if there is no pending cast on the argument (#27962);
|
|
| 2232 | + -- if there is, the general case below deals with it properly
|
|
| 2284 | 2233 | ; arg' <- case arg of
|
| 2285 | - Lam s body -> do { (env', s') <- simplBinder arg_env s
|
|
| 2286 | - ; body' <- simplExprC env' body inner_cont
|
|
| 2287 | - ; return (Lam s' body') }
|
|
| 2288 | - -- Important: do not try to eta-expand this lambda
|
|
| 2289 | - -- See Note [No eta-expansion in runRW#]
|
|
| 2234 | + Lam s body
|
|
| 2235 | + | MRefl <- arg_mco
|
|
| 2236 | + -> do { (env', s') <- simplBinder arg_env s
|
|
| 2237 | + ; body' <- simplExprC env' body inner_cont
|
|
| 2238 | + ; return (Lam s' body') }
|
|
| 2239 | + -- Important: do not try to eta-expand this lambda
|
|
| 2240 | + -- See Note [No eta-expansion in runRW#]
|
|
| 2290 | 2241 | |
| 2291 | 2242 | _ -> do { s' <- newId (fsLit "s") ManyTy realWorldStatePrimTy
|
| 2292 | 2243 | ; let (m,_,_) = splitFunTy fun_ty
|
| 2293 | 2244 | env' = arg_env `addNewInScopeIds` [s']
|
| 2294 | 2245 | hole_ty = mkVisFunTy m realWorldStatePrimTy new_runrw_res_ty
|
| 2295 | 2246 | cont' = pushCastMCo env' arg_mco $
|
| 2296 | - ApplyToVal { sc_arg = Var s', sc_cast = MRefl
|
|
| 2297 | - , sc_env = Simplified OkDup
|
|
| 2247 | + ApplyToVal { sc_arg = DoneId s'
|
|
| 2248 | + , sc_dup = dup
|
|
| 2298 | 2249 | , sc_cont = inner_cont
|
| 2299 | 2250 | , sc_hole_ty = hole_ty }
|
| 2300 | 2251 | -- cont' applies to s', then K
|
| 2252 | + -- The argument (Var s') is small, but inner_cont may not be
|
|
| 2253 | + -- dupable; see (AV2) in Note [The argument of ApplyToVal]
|
|
| 2254 | + dup | contIsDupable inner_cont = OkDup
|
|
| 2255 | + | otherwise = NoDup
|
|
| 2301 | 2256 | ; body' <- simplExprC env' arg cont'
|
| 2302 | 2257 | ; return (Lam s' body') }
|
| 2303 | 2258 | |
| ... | ... | @@ -2364,13 +2319,12 @@ rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_c |
| 2364 | 2319 | |
| 2365 | 2320 | ---------- Simplify value arguments --------------------
|
| 2366 | 2321 | rebuildCall env fun_info
|
| 2367 | - (ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
|
|
| 2368 | - , sc_hole_ty = fun_ty, sc_cont = cont })
|
|
| 2369 | - | UnSimplified arg_env <- arg_se
|
|
| 2322 | + (ApplyToVal { sc_arg = arg, sc_hole_ty = fun_ty, sc_cont = cont })
|
|
| 2323 | + | ContEx arg_env arg_expr arg_mco <- arg
|
|
| 2370 | 2324 | , isStrictArgInfo fun_info -- Strict arguments
|
| 2371 | 2325 | , seCaseCase env -- But only when case-of-case is on.
|
| 2372 | 2326 | -- See Note [Case-of-case and full laziness]
|
| 2373 | - = simplExprF (arg_env `setInScopeFromE` env) arg $
|
|
| 2327 | + = simplExprF (arg_env `setInScopeFromE` env) arg_expr $
|
|
| 2374 | 2328 | addCastMCo arg_mco $
|
| 2375 | 2329 | StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
|
| 2376 | 2330 | , sc_dup = NoDup
|
| ... | ... | @@ -2382,7 +2336,7 @@ rebuildCall env fun_info |
| 2382 | 2336 | -- There is no benefit (unlike in a let-binding), and we'd
|
| 2383 | 2337 | -- have to be very careful about bogus strictness through
|
| 2384 | 2338 | -- floating a demanded let.
|
| 2385 | - = do { arg' <- simplArg env (Just fun_info) fun_ty arg_se arg arg_mco
|
|
| 2339 | + = do { arg' <- simplArg env (Just fun_info) fun_ty arg
|
|
| 2386 | 2340 | ; rebuildCall env (addValArgTo fun_info arg' fun_ty) cont }
|
| 2387 | 2341 | |
| 2388 | 2342 | ---------- No further useful info, revert to generic rebuild ------------
|
| ... | ... | @@ -2530,11 +2484,11 @@ Then |
| 2530 | 2484 | * We simplify BIG before trying the rule; but the rule does not fire
|
| 2531 | 2485 | (forcing this simplification is why we have the RULE in this example)
|
| 2532 | 2486 | * We inline f = \x. g x, in `simpl_lam`
|
| 2533 | - * So if `simpl_lam` did preInlineUnconditionally we get (g BIG)
|
|
| 2487 | + * So if `simpl_lam` did preInlineBetaUnconditionally we get (g BIG)
|
|
| 2534 | 2488 | * Now if g has a RULE we'll simplify BIG again, and this whole thing can
|
| 2535 | 2489 | iterate.
|
| 2536 | 2490 | * However, if `f` did not have a RULE, so that BIG has /not/ already been
|
| 2537 | - simplified, we /want/ to do preInlineUnconditionally in simpl_lam.
|
|
| 2491 | + simplified, we /want/ to do preInlineBetaUnconditionally in simpl_lam.
|
|
| 2538 | 2492 | |
| 2539 | 2493 | So we go to some effort to avoid repeatedly simplifying the same thing.
|
| 2540 | 2494 | Suppose we are in the Plan (AFTER) case of rule application, for a rule
|
| ... | ... | @@ -2543,8 +2497,9 @@ and a call |
| 2543 | 2497 | f (e1,e2)
|
| 2544 | 2498 | Then:
|
| 2545 | 2499 | |
| 2546 | -* The (sc_env :: StaticEnv) field of ApplyToVal records if the argument
|
|
| 2547 | - has been evaluated. See Note [StaticEnv] in GHC.Core.Opt.Simplify.Utils.
|
|
| 2500 | +* The (sc_arg :: SimplClo) field of ApplyToVal records if the argument
|
|
| 2501 | + has been simplified: it is a DoneEx if so, and a ContEx if not.
|
|
| 2502 | + See Note [The argument of ApplyToVal] in GHC.Core.Opt.Simplify.Utils.
|
|
| 2548 | 2503 | |
| 2549 | 2504 | * The rule fires returning
|
| 2550 | 2505 | RuleMatch { rm_rhs = (\x y. ...x..), rm_args = [ e1, e2 ] }
|
| ... | ... | @@ -2557,17 +2512,17 @@ Then: |
| 2557 | 2512 | is the reason that `RuleMatch` separates the two.
|
| 2558 | 2513 | |
| 2559 | 2514 | * `fireRuleAFTER` uses `pushOutArgs` to push [ e1, e2 ] back onto the
|
| 2560 | - continuation with sc_env=Simplified NoDup.
|
|
| 2515 | + continuation as (DoneEx e1) and (DoneEx e2).
|
|
| 2561 | 2516 | |
| 2562 | 2517 | * Beta-reduction fires (in `simpl_lam`) for the \x.
|
| 2563 | 2518 | |
| 2564 | 2519 | * Suppose `x` occurs many times. Then we want to behave like `let x=e1 in ..`,
|
| 2565 | - but we use `simplArg`, which in turn uses that `sc_env` flag to avoid
|
|
| 2520 | + but we use `simplArg`, which in turn uses the DoneEx to avoid
|
|
| 2566 | 2521 | re-simplifying `e1`.
|
| 2567 | 2522 | |
| 2568 | 2523 | * Suppose `x` occurs just once or not at all; then the call to
|
| 2569 | - `preInlineUnconditionally` in `simpl_lam` will fire, and extend the
|
|
| 2570 | - substitution with
|
|
| 2524 | + `preInlineBetaUnconditionally` in `simpl_lam` will fire, and extend the
|
|
| 2525 | + substitution with the very same SimplClo
|
|
| 2571 | 2526 | x :-> DoneEx e1
|
| 2572 | 2527 | |
| 2573 | 2528 | * At the /occurrence/ of `x`, the function `simplInId` calls `simplOutExpr`
|
| ... | ... | @@ -2774,8 +2729,7 @@ trySeqRules in_env scrut rhs cont |
| 2774 | 2729 | , ValArg { as_arg = no_cast_scrut
|
| 2775 | 2730 | , as_dmd = seqDmd
|
| 2776 | 2731 | , as_hole_ty = res3_ty } ]
|
| 2777 | - rule_cont = ApplyToVal { sc_env = UnSimplified in_env, sc_arg = rhs
|
|
| 2778 | - , sc_cast = MRefl
|
|
| 2732 | + rule_cont = ApplyToVal { sc_arg = ContEx in_env rhs MRefl, sc_dup = NoDup
|
|
| 2779 | 2733 | , sc_cont = cont, sc_hole_ty = res4_ty }
|
| 2780 | 2734 | |
| 2781 | 2735 | out_args = [Type rhs_rep, Type scrut_ty, Type rhs_ty, no_cast_scrut]
|
| ... | ... | @@ -3420,6 +3374,7 @@ simplAlts (saf,env0) scrut case_bndr alts cont' |
| 3420 | 3374 | ; let case_bndr2 = case_bndr1 `setIdUnfolding` evaldUnfolding
|
| 3421 | 3375 | env2 = modifyInScope env1 case_bndr2
|
| 3422 | 3376 | -- See Note [Case binder evaluated-ness]
|
| 3377 | + -- and Note [Evaluated-ness on case binders] in GHC.Core
|
|
| 3423 | 3378 | fam_envs = seFamEnvs env0
|
| 3424 | 3379 | |
| 3425 | 3380 | ; (alt_env', scrut', case_bndr') <- improveSeq fam_envs (saf,env2) scrut
|
| ... | ... | @@ -3879,8 +3834,8 @@ knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont |
| 3879 | 3834 | return ( emptyFloats env
|
| 3880 | 3835 | , extendIdSubst env case_bndr (DoneEx scrut NotJoinPoint))
|
| 3881 | 3836 | |
| 3882 | - | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr
|
|
| 3883 | - (UnSimplified env) con_app MRefl
|
|
| 3837 | + | Just env' <- preInlineLetUnconditionally env NotTopLevel case_bndr
|
|
| 3838 | + con_app env
|
|
| 3884 | 3839 | = return (emptyFloats env', env')
|
| 3885 | 3840 | |
| 3886 | 3841 | | otherwise
|
| ... | ... | @@ -4043,7 +3998,7 @@ mkDupableContWithDmds env dmds (TickIt t cont) |
| 4043 | 3998 | mkDupableContWithDmds env _
|
| 4044 | 3999 | cont1@(StrictBind { sc_bndr = bndr, sc_body = body, sc_from = from_what
|
| 4045 | 4000 | , sc_env = se, sc_cont = cont})
|
| 4046 | --- See Note [Duplicating StrictBind]
|
|
| 4001 | +-- See (SB2) in Note [StrictBind]
|
|
| 4047 | 4002 | -- K[ let x = <> in b ] --> join j x = K[ b ]
|
| 4048 | 4003 | -- j <>
|
| 4049 | 4004 | = do { let sb_env = case se of
|
| ... | ... | @@ -4060,7 +4015,10 @@ mkDupableContWithDmds env _ |
| 4060 | 4015 | ; let join_body = wrapFloats floats1 join_inner
|
| 4061 | 4016 | res_ty = contResultType cont
|
| 4062 | 4017 | |
| 4063 | - ; mkDupableStrictBind env bndr' join_body res_ty }
|
|
| 4018 | + -- bndr' is about to become a lambda binder, so it must have suitable
|
|
| 4019 | + -- IdInfo; simplNonRecE ensures this. See Note [Core binder IdInfo invariants]
|
|
| 4020 | + ; assertPpr (lamBndrInfoOK bndr') (ppr bndr' $$ ppr (idInfo bndr')) $
|
|
| 4021 | + mkDupableStrictBind env bndr' join_body res_ty }
|
|
| 4064 | 4022 | |
| 4065 | 4023 | mkDupableContWithDmds env _
|
| 4066 | 4024 | (StrictArg { sc_fun = fun, sc_cont = cont
|
| ... | ... | @@ -4111,8 +4069,7 @@ mkDupableContWithDmds env dmds |
| 4111 | 4069 | , sc_arg_ty = arg_ty, sc_hole_ty = hole_ty }) }
|
| 4112 | 4070 | |
| 4113 | 4071 | mkDupableContWithDmds env dmds
|
| 4114 | - (ApplyToVal { sc_arg = arg, sc_env = se, sc_cast = arg_mco
|
|
| 4115 | - , sc_cont = cont, sc_hole_ty = hole_ty })
|
|
| 4072 | + (ApplyToVal { sc_arg = arg, sc_cont = cont, sc_hole_ty = hole_ty })
|
|
| 4116 | 4073 | = -- e.g. [...hole...] (...arg...)
|
| 4117 | 4074 | -- ==>
|
| 4118 | 4075 | -- let a = ...arg...
|
| ... | ... | @@ -4124,12 +4081,12 @@ mkDupableContWithDmds env dmds |
| 4124 | 4081 | expectNonEmpty dmds
|
| 4125 | 4082 | ; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
|
| 4126 | 4083 | ; let env' = env `setInScopeFromF` floats1
|
| 4127 | - ; arg' <- simplArg env' Nothing hole_ty se arg arg_mco
|
|
| 4084 | + ; arg' <- simplArg env' Nothing hole_ty arg
|
|
| 4128 | 4085 | ; (let_floats2, triv_arg) <- makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
|
| 4129 | 4086 | ; let all_floats = floats1 `addLetFloats` let_floats2
|
| 4130 | 4087 | ; return ( all_floats
|
| 4131 | - , ApplyToVal { sc_arg = triv_arg, sc_env = Simplified OkDup
|
|
| 4132 | - , sc_cast = MRefl, sc_cont = cont', sc_hole_ty = hole_ty }) }
|
|
| 4088 | + , ApplyToVal { sc_arg = DoneEx triv_arg NotJoinPoint, sc_dup = OkDup
|
|
| 4089 | + , sc_cont = cont', sc_hole_ty = hole_ty }) }
|
|
| 4133 | 4090 | |
| 4134 | 4091 | mkDupableContWithDmds env _
|
| 4135 | 4092 | (Select { sc_bndr = case_bndr, sc_alts = alts, sc_env = se, sc_cont = cont })
|
| ... | ... | @@ -4253,7 +4210,9 @@ mkDupableAlt _env case_bndr jfloats (Alt con alt_bndrs alt_rhs_in) |
| 4253 | 4210 | | otherwise = v
|
| 4254 | 4211 | |
| 4255 | 4212 | -- No lambda binder has an unfolding, but (currently) case binders can,
|
| 4256 | - -- so we must zap them here.
|
|
| 4213 | + -- so we must zap them here. But case binders never have a pragma,
|
|
| 4214 | + -- stable unfolding or RULES, so there is no need to zap those.
|
|
| 4215 | + -- See Note [Core binder IdInfo invariants] in GHC.Core
|
|
| 4257 | 4216 | join_rhs = mkLams (map zapIdUnfolding final_bndrs) rhs_with_seqs
|
| 4258 | 4217 | |
| 4259 | 4218 | ; join_bndr <- newJoinId filtered_binders rhs_ty'
|
| ... | ... | @@ -4569,7 +4528,7 @@ There are two ways to make it duplicable. |
| 4569 | 4528 | ; False -> jump $j r2 }
|
| 4570 | 4529 | |
| 4571 | 4530 | Notice that Plan B is very like the way we handle strict bindings;
|
| 4572 | - see Note [Duplicating StrictBind]. And Plan B is exactly what we'd
|
|
| 4531 | + see Note [StrictBind]. And Plan B is exactly what we'd
|
|
| 4573 | 4532 | get if we turned use a case expression to evaluate the strict arg:
|
| 4574 | 4533 | |
| 4575 | 4534 | case (case x of { True -> r1; False -> r2 }) of
|
| ... | ... | @@ -4642,23 +4601,54 @@ Note [Inline small things to avoid creating a thunk] in |
| 4642 | 4601 | Simplify.Utils. But if we do inline them, the entire process will
|
| 4643 | 4602 | repeat -- back to exponential behaviour.
|
| 4644 | 4603 | |
| 4645 | -So we are careful to keep the demand-info on a2 and a3. Then they'll
|
|
| 4646 | -be /strict/ let-bindings, which will be dealt with by StrictBind.
|
|
| 4647 | -That's why contIsDupableWithDmds is careful to propagage demand
|
|
| 4648 | -info to the auxiliary bindings it creates. See the Demand argument
|
|
| 4649 | -to makeTrivial.
|
|
| 4650 | - |
|
| 4651 | -Note [Duplicating StrictBind]
|
|
| 4652 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 4653 | -We make a StrictBind duplicable in a very similar way to
|
|
| 4654 | -that for case expressions. After all,
|
|
| 4655 | - let x* = e in b is similar to case e of x -> b
|
|
| 4656 | - |
|
| 4657 | -So we potentially make a join-point for the body, thus:
|
|
| 4658 | - let x = <> in b ==> join j x = b
|
|
| 4659 | - in j <>
|
|
| 4660 | - |
|
| 4661 | -Just like StrictArg in fact -- and indeed they share code.
|
|
| 4604 | +So we are careful to keep the demand-info on a2 and a3. Then they'll be
|
|
| 4605 | +/strict/ let-bindings, which will be dealt with by `StrictBind` (see
|
|
| 4606 | +Note [StrictBind]). That's why `contIsDupableWithDmds` is careful to
|
|
| 4607 | +propagate demand info to the auxiliary bindings it creates. See the
|
|
| 4608 | +`Demand` argument to `makeTrivial`.
|
|
| 4609 | + |
|
| 4610 | +Note [StrictBind]
|
|
| 4611 | +~~~~~~~~~~~~~~~~~
|
|
| 4612 | +We use StrictBind when we fine
|
|
| 4613 | + let x! = rhs in body
|
|
| 4614 | +where the `x` is definitely demanded in body. When this happens we can
|
|
| 4615 | +float out case-expressions etc from inside `e`; e.g.
|
|
| 4616 | + let { x! = case a of (p,q) -> rhs } in b
|
|
| 4617 | +-->
|
|
| 4618 | + case a of (p,q) -> let x! = rhs in b
|
|
| 4619 | + |
|
| 4620 | +We simplify `rhs` with a StrictBind continuation that continues with
|
|
| 4621 | +`body`
|
|
| 4622 | + |
|
| 4623 | +(SB1) We only use StrictBind when case-of-case is on:
|
|
| 4624 | + see Note [Case-of-case and full laziness]
|
|
| 4625 | + |
|
| 4626 | +(SB2) We make a StrictBind /duplicable/ in a very similar way to
|
|
| 4627 | + that for case expressions. After all,
|
|
| 4628 | + let x! = e in b is similar to case e of x -> b
|
|
| 4629 | + |
|
| 4630 | + So we potentially make a join-point for the body, thus:
|
|
| 4631 | + let x = <> in b ==> join j x = b
|
|
| 4632 | + in j <>
|
|
| 4633 | + |
|
| 4634 | + Just like StrictArg in fact -- and indeed they share code.
|
|
| 4635 | + |
|
| 4636 | +(SB3) We do not do use StrictBind if the binder `x` has:
|
|
| 4637 | + * A stable unfolding
|
|
| 4638 | + * RULES
|
|
| 4639 | + * An inlining activation that is not always active.
|
|
| 4640 | + Why not? Because these things won't survive if we duplicate the join point.
|
|
| 4641 | + For example:
|
|
| 4642 | + let {-# NOINLINE x #-}
|
|
| 4643 | + x! = case y of { ... }
|
|
| 4644 | + in blah
|
|
| 4645 | + If we make a join point j x = blah, we have nowhere convenient
|
|
| 4646 | + to put that NOINLINE. Ditto INLINE or RULES. It's very unusual,
|
|
| 4647 | + so no harm in simply not using StrictBind. But it does happen;
|
|
| 4648 | + one example is this, in the Applicative (ST s) instance in
|
|
| 4649 | + GHC.Internal.Control.Monad.St.Lazy.Imp
|
|
| 4650 | + {-# NOINLINE res1 #-}
|
|
| 4651 | + !res1 = unST fm s
|
|
| 4662 | 4652 | |
| 4663 | 4653 | Note [Join point abstraction] Historical note
|
| 4664 | 4654 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -12,7 +12,8 @@ module GHC.Core.Opt.Simplify.Utils ( |
| 12 | 12 | tryEtaExpandRhs, wantEtaExpansion,
|
| 13 | 13 | |
| 14 | 14 | -- Inlining,
|
| 15 | - preInlineUnconditionally, postInlineUnconditionally,
|
|
| 15 | + preInlineLetUnconditionally, preInlineBetaUnconditionally,
|
|
| 16 | + postInlineUnconditionally,
|
|
| 16 | 17 | activeRule,
|
| 17 | 18 | getUnfoldingInRuleMatch,
|
| 18 | 19 | updModeForStableUnfoldings, updModeForRuleLHS, updModeForRuleRHS,
|
| ... | ... | @@ -174,16 +175,14 @@ data SimplCont |
| 174 | 175 | -- Invariant: never an identity coercion
|
| 175 | 176 | , sc_opt :: Bool -- True <=> sc_co has had optCoercion applied to it
|
| 176 | 177 | -- See Note [Avoid re-simplifying coercions]
|
| 177 | - -- in GHC.Core.Opt.Simplify.Iteration
|
|
| 178 | 178 | , sc_cont :: SimplCont }
|
| 179 | 179 | |
| 180 | 180 | | ApplyToVal -- (ApplyToVal arg K)[e] = K[ e arg ]
|
| 181 | 181 | { sc_hole_ty :: OutType -- Type of the function, presumably (forall a. blah)
|
| 182 | 182 | -- See Note [The hole type in ApplyToTy]
|
| 183 | - , sc_env :: StaticEnv -- See Note [StaticEnv]
|
|
| 184 | - , sc_arg :: CoreExpr -- The argument
|
|
| 185 | - , sc_cast :: MOutCoercion -- Wrap this OutCoercion around the (simplified) argument
|
|
| 186 | - -- See Note [The sc_cast field of ApplyToVal]
|
|
| 183 | + , sc_dup :: DupFlag -- See Note [The argument of ApplyToVal]
|
|
| 184 | + , sc_arg :: SimplClo -- The argument
|
|
| 185 | + -- Invariant: if sc_arg is a ContEx, then sc_dup = NoDup
|
|
| 187 | 186 | , sc_cont :: SimplCont }
|
| 188 | 187 | |
| 189 | 188 | | ApplyToTy -- (ApplyToTy ty K)[e] = K[ e ty ]
|
| ... | ... | @@ -201,6 +200,7 @@ data SimplCont |
| 201 | 200 | -- The two strict forms have no DupFlag, because we never duplicate them
|
| 202 | 201 | | StrictBind -- (StrictBind x b K)[e] = let x = e in K[b]
|
| 203 | 202 | -- or, equivalently, = K[ (\x.b) e ]
|
| 203 | + -- See Note [StrictBind] in GHC.Core.Opt.Simplify.Iteration
|
|
| 204 | 204 | { sc_from :: FromWhat
|
| 205 | 205 | , sc_env :: StaticEnv -- See Note [StaticEnv]
|
| 206 | 206 | -- The sc_env in StrictBind is never (Simplified NoDup)
|
| ... | ... | @@ -252,49 +252,85 @@ perhapsSubstTy (UnSimplified env) ty = substTy env ty |
| 252 | 252 | |
| 253 | 253 | {- Note [StaticEnv]
|
| 254 | 254 | ~~~~~~~~~~~~~~~~~~~
|
| 255 | -Consider ApplyToVal, which has
|
|
| 256 | - sc_env :: StaticEnv
|
|
| 257 | - sc_arg :: CoreExpr
|
|
| 258 | -Initially, `sc_arg` is an un-simplified InExpr, and `sc_env` is (UnSimplified env),
|
|
| 259 | -where `env` gives meaning to the free variables of `sc_arg`; in particular, `env`
|
|
| 260 | -may have substitutions that must apply to the argument.
|
|
| 261 | - |
|
| 262 | -But sometimes we simplify the argument, and in that case, `sc_arg` is an OutExpr,
|
|
| 263 | -the simplified argument, and `sc_env` is (Simplified NoDup) or (Simplified OkDup).
|
|
| 264 | -The former is the safe, conservative option, but in `mkDupableCont` we want to make
|
|
| 265 | -the continuation duplicable, so we make the argument small and tag it with
|
|
| 266 | -(Simplified OkDup).
|
|
| 267 | - |
|
| 268 | -We later simplify the argument, e.g. in `simplArg`. Then
|
|
| 269 | - * If sc_env is Simplified, it's a no-op
|
|
| 270 | - * If sc_env is (UnSimplified arg_env) we simplify `sc_arg` with
|
|
| 271 | - - Its captured envt `arg_env`
|
|
| 255 | +Consider Select, which has
|
|
| 256 | + sc_env :: StaticEnv
|
|
| 257 | + sc_bndr :: Id
|
|
| 258 | + sc_alts :: [CoreAlt]
|
|
| 259 | +Initially, `sc_bndr` and `sc_alts` are un-simplified InThings, and `sc_env` is
|
|
| 260 | +(UnSimplified env), where `env` gives meaning to their free variables; in
|
|
| 261 | +particular, `env` may have substitutions that must apply to them.
|
|
| 262 | + |
|
| 263 | +But sometimes (notably in `mkDupableCont`) we simplify them, and in that case
|
|
| 264 | +`sc_bndr` and `sc_alts` are OutThings, and `sc_env` is (Simplified dup).
|
|
| 265 | + |
|
| 266 | +When we finally simplify the alternatives (see `mkAltEnv`)
|
|
| 267 | + * If sc_env is Simplified, there is nothing to do
|
|
| 268 | + * If sc_env is (UnSimplified alt_env) we simplify them with
|
|
| 269 | + - Their captured envt `alt_env`
|
|
| 272 | 270 | - but overriding its InScopeSet with the larger one at the
|
| 273 | 271 | simplification point.
|
| 274 | 272 | Why override the InScopeSet? Example:
|
| 275 | - (let y = ey in f) ex
|
|
| 276 | - By the time we simplify ex, 'y' will be in scope.
|
|
| 277 | - All this is done in `simplArg`.
|
|
| 273 | + case (let y = ey in f) of alts
|
|
| 274 | + By the time we simplify alts, 'y' will be in scope.
|
|
| 278 | 275 | |
| 279 | 276 | Note that:
|
| 280 | 277 | |
| 281 | 278 | * In the Simplified case there is no environment, because the substitution has
|
| 282 | 279 | already been applied.
|
| 283 | 280 | |
| 284 | -* We say sc_arg :: CoreExpr, rather than sc_arg :: InExpr or sc_arg :: OutExpr,
|
|
| 285 | - because whether it is InExpr or OutExpr depends on `sc_env`
|
|
| 281 | +* We say sc_alts :: [CoreAlt], rather than [InAlt] or [OutAlt],
|
|
| 282 | + because whether they are InAlts or OutAlts depends on `sc_env`
|
|
| 283 | + |
|
| 284 | +* Same deal for StrictBind, where the StaticEnv scopes over sc_bndr and sc_body.
|
|
| 286 | 285 | |
| 287 | -* Same deal for Select, and StrictBind, but the StaticEnv scopes over
|
|
| 288 | - * sc_bndr and sc_alts (for Select)
|
|
| 289 | - * sc_bndr and sc_body (for StrictBind)
|
|
| 286 | +* ApplyToVal is similar, but simpler: it uses a SimplClo instead.
|
|
| 287 | + See Note [The argument of ApplyToVal].
|
|
| 290 | 288 | |
| 291 | -* Even though the InScopeSet of an (UnSimplified se) is overridden in `simplArg`,
|
|
| 292 | - that InScopeSet is not irrelevant: it should include all the free vars of
|
|
| 293 | - applying the substitution to the InExpr. Reason: contHoleType uses perhapsSubstTy
|
|
| 294 | - to apply the substitution to the expression, and that (rightly) gives ASSERT
|
|
| 295 | - failures if the InScopeSet isn't big enough.
|
|
| 289 | +* Even though the InScopeSet of an (UnSimplified se) is overridden, that
|
|
| 290 | + InScopeSet is not irrelevant: it should include all the free vars of
|
|
| 291 | + applying the substitution to the InThing. Reason: contHoleType uses
|
|
| 292 | + perhapsSubstTy to apply the substitution to the binder, and that
|
|
| 293 | + (rightly) gives ASSERT failures if the InScopeSet isn't big enough.
|
|
| 296 | 294 | |
| 297 | 295 | (SE1) If dup = OkToDup, then continuation k is also ok-to-dup
|
| 296 | + |
|
| 297 | +Note [The argument of ApplyToVal]
|
|
| 298 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 299 | +ApplyToVal has
|
|
| 300 | + sc_dup :: DupFlag
|
|
| 301 | + sc_arg :: SimplClo
|
|
| 302 | + |
|
| 303 | +Initially, `sc_arg` is (ContEx env arg MRefl), where `arg` is the un-simplified
|
|
| 304 | +InExpr, and `env` gives meaning to the free variables of `arg`; in particular,
|
|
| 305 | +`env` may have substitutions that must apply to the argument.
|
|
| 306 | + |
|
| 307 | +But sometimes we simplify the argument, and in that case, `sc_arg` is
|
|
| 308 | +(DoneEx arg' NotJoinPoint), where `arg'` is the simplified argument.
|
|
| 309 | + |
|
| 310 | +The `sc_dup` flag says whether the continuation can be duplicated. NoDup is
|
|
| 311 | +the safe, conservative option, but in `mkDupableCont` we want to make the
|
|
| 312 | +continuation duplicable, so we make the argument small (and hence a DoneEx)
|
|
| 313 | +and set `sc_dup` to OkDup. Invariants:
|
|
| 314 | + |
|
| 315 | + (AV1) If `sc_arg` is a ContEx, then `sc_dup` is NoDup.
|
|
| 316 | + |
|
| 317 | + (AV2) If `sc_dup` is OkDup then `sc_cont` is also ok-to-dup; see (SE1)
|
|
| 318 | + in Note [StaticEnv].
|
|
| 319 | + |
|
| 320 | +We later simplify the argument, in `simplArg`. Then
|
|
| 321 | + * If `sc_arg` is a DoneEx (or DoneId), it's a no-op
|
|
| 322 | + * If `sc_arg` is (ContEx arg_env arg mco) we simplify `arg` with
|
|
| 323 | + - Its captured envt `arg_env`
|
|
| 324 | + - but overriding its InScopeSet with the larger one at the
|
|
| 325 | + simplification point.
|
|
| 326 | + Why override the InScopeSet? Example:
|
|
| 327 | + (let y = ey in f) ex
|
|
| 328 | + By the time we simplify ex, 'y' will be in scope.
|
|
| 329 | + Then we wrap the cast `mco` around the result.
|
|
| 330 | + See Note [The MOutCoercion field of ContEx].
|
|
| 331 | + |
|
| 332 | +Using a SimplClo for the argument means that it can be substituted for a lambda
|
|
| 333 | +binder, in `preInlineBetaUnconditionally`, without further ado.
|
|
| 298 | 334 | -}
|
| 299 | 335 | |
| 300 | 336 | instance Outputable DupFlag where
|
| ... | ... | @@ -312,9 +348,9 @@ instance Outputable SimplCont where |
| 312 | 348 | = (text "TickIt" <+> ppr t) $$ ppr cont
|
| 313 | 349 | ppr (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
|
| 314 | 350 | = (text "ApplyToTy" <+> pprParendType ty) $$ ppr cont
|
| 315 | - ppr (ApplyToVal { sc_arg = arg, sc_env = env, sc_cont = cont, sc_hole_ty = hole_ty })
|
|
| 316 | - = (hang (text "ApplyToVal" <> braces (ppr env) <+> text "hole-ty:" <+> pprParendType hole_ty)
|
|
| 317 | - 2 (pprParendExpr arg))
|
|
| 351 | + ppr (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_cont = cont, sc_hole_ty = hole_ty })
|
|
| 352 | + = (hang (text "ApplyToVal" <> braces (ppr dup) <+> text "hole-ty:" <+> pprParendType hole_ty)
|
|
| 353 | + 2 (ppr arg))
|
|
| 318 | 354 | $$ ppr cont
|
| 319 | 355 | ppr (StrictBind { sc_bndr = b, sc_cont = cont })
|
| 320 | 356 | = (text "StrictBind" <+> ppr b) $$ ppr cont
|
| ... | ... | @@ -433,8 +469,8 @@ pushOutArgs fun_ty (arg:args) cont |
| 433 | 469 | = ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
|
| 434 | 470 | , sc_cont = pushOutArgs (piResultTy fun_ty ty) args cont }
|
| 435 | 471 | | otherwise
|
| 436 | - = ApplyToVal { sc_hole_ty = fun_ty, sc_cast = MRefl
|
|
| 437 | - , sc_arg = arg, sc_env = Simplified NoDup
|
|
| 472 | + = ApplyToVal { sc_hole_ty = fun_ty
|
|
| 473 | + , sc_arg = DoneEx arg NotJoinPoint, sc_dup = NoDup
|
|
| 438 | 474 | , sc_cont = pushOutArgs (funResultTy fun_ty) args cont}
|
| 439 | 475 | |
| 440 | 476 | pushArgSpecs :: [ArgSpec] -- In normal, forward order
|
| ... | ... | @@ -445,7 +481,7 @@ pushArgSpec :: ArgSpec -> SimplCont -> SimplCont |
| 445 | 481 | pushArgSpec (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
|
| 446 | 482 | = ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont }
|
| 447 | 483 | pushArgSpec (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
|
| 448 | - = ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup, sc_cast = MRefl
|
|
| 484 | + = ApplyToVal { sc_arg = DoneEx arg NotJoinPoint, sc_dup = NoDup
|
|
| 449 | 485 | , sc_hole_ty = hole_ty, sc_cont = cont }
|
| 450 | 486 | |
| 451 | 487 | argSpecArg :: ArgSpec -> OutExpr
|
| ... | ... | @@ -496,7 +532,12 @@ contIsStop _ = False |
| 496 | 532 | contIsDupable :: SimplCont -> Bool
|
| 497 | 533 | contIsDupable (Stop {}) = True
|
| 498 | 534 | contIsDupable (ApplyToTy { sc_cont = k }) = contIsDupable k
|
| 499 | -contIsDupable (ApplyToVal { sc_env = se }) = okToDupSE se -- See (SE1) in Note [StaticEnv]
|
|
| 535 | +contIsDupable (ApplyToVal { sc_dup = dup, sc_arg = arg })
|
|
| 536 | + = assertPpr (not (okToDup dup && is_cont_ex arg)) (ppr arg) $
|
|
| 537 | + okToDup dup -- See (AV1,AV2) in Note [The argument of ApplyToVal]
|
|
| 538 | + where
|
|
| 539 | + is_cont_ex (ContEx {}) = True
|
|
| 540 | + is_cont_ex _ = False
|
|
| 500 | 541 | contIsDupable (Select { sc_env = se }) = okToDupSE se -- ...ditto...
|
| 501 | 542 | contIsDupable (StrictBind { sc_env = se }) = okToDupSE se -- ...ditto...
|
| 502 | 543 | contIsDupable (StrictArg { sc_dup = dup }) = okToDup dup -- ...ditto...
|
| ... | ... | @@ -605,8 +646,8 @@ contArgs env cont |
| 605 | 646 | lone (CastIt {}) = False -- stops it being "lone"
|
| 606 | 647 | lone _ = True
|
| 607 | 648 | |
| 608 | - go args (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = k })
|
|
| 609 | - = go (interestingArg env se arg : args) k
|
|
| 649 | + go args (ApplyToVal { sc_arg = arg, sc_cont = k })
|
|
| 650 | + = go (interestingArg env arg : args) k
|
|
| 610 | 651 | go args (ApplyToTy { sc_cont = k }) = go args k
|
| 611 | 652 | go args (CastIt { sc_cont = k }) = go args k
|
| 612 | 653 | go args k = (False, reverse args, k)
|
| ... | ... | @@ -621,15 +662,13 @@ contOutArgs env cont |
| 621 | 662 | go (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
|
| 622 | 663 | = Type ty : go cont
|
| 623 | 664 | |
| 624 | - go (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = cont })
|
|
| 625 | - = case se of
|
|
| 626 | - Simplified {} -> arg : go cont
|
|
| 627 | - UnSimplified env -> GHC.Core.Subst.substExpr (getFullSubst in_scope env) arg : go cont
|
|
| 628 | - -- Make sure we apply the static environment `sc_env` as a substitution
|
|
| 665 | + go (ApplyToVal { sc_arg = arg, sc_cont = cont })
|
|
| 666 | + = simplCloExpr in_scope arg : go cont
|
|
| 667 | + -- Make sure we apply the static environment of a ContEx as a substitution
|
|
| 629 | 668 | -- to get an OutExpr. See (BF1) in Note [tryRules: plan (BEFORE)]
|
| 630 | 669 | -- in GHC.Core.Opt.Simplify.Iteration
|
| 631 | - -- NB: we use substExpr, not substExprSC: we want to get the benefit of
|
|
| 632 | - -- knowing what is evaluated etc, via the in-scope set
|
|
| 670 | + -- simplCloExpr also wraps the pending cast (if any) around the argument;
|
|
| 671 | + -- omitting it can make a rule fail to match (#27963)
|
|
| 633 | 672 | |
| 634 | 673 | -- No more arguments
|
| 635 | 674 | go _ = []
|
| ... | ... | @@ -826,23 +865,86 @@ make use of the strictness info for the function. |
| 826 | 865 | * *
|
| 827 | 866 | ********************************************************************* -}
|
| 828 | 867 | |
| 829 | -{- Note [The sc_cast field of ApplyToVal]
|
|
| 830 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 868 | +{- Note [The MOutCoercion field of ContEx]
|
|
| 869 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 831 | 870 | In the `ApplyToVal` case of `pushCast` we want to push an `OutCoercion` into the
|
| 832 | -argument. But the argument may or may not have been simplified (see Note [StaticEnv])
|
|
| 833 | -so we definitely can't just wrap the cast around the argument. Instead we store it
|
|
| 834 | -in the `sc_cast` field -- this is the whole reason for the `sc_cast` field.
|
|
| 871 | +argument. But the argument may or may not have been simplified (see Note [The
|
|
| 872 | +argument of ApplyToVal]):
|
|
| 873 | + |
|
| 874 | +* If it has been simplified, it is (DoneEx arg' _), and we can simply wrap the
|
|
| 875 | + cast around `arg'`.
|
|
| 876 | + |
|
| 877 | +* If it has not, it is (ContEx env arg mco), and we definitely can't just wrap
|
|
| 878 | + the (Out)cast around the InExpr `arg`. Instead we compose it with `mco` --
|
|
| 879 | + this is the whole reason for the MOutCoercion field of `ContEx`.
|
|
| 880 | + |
|
| 881 | +All this is done by `mkCloCastMCo`.
|
|
| 835 | 882 | |
| 836 | 883 | We deal with that pending cast mainly in `simplArg`.
|
| 837 | 884 | |
| 838 | 885 | But we /also/ sometimes want to substitute that argument for a lambda-binder, in
|
| 839 | -`preInlineUnconditionally`. So we also have to put that pending cast into
|
|
| 840 | -`ContEx`; hence the MOutCoercion field of `ContEx`. Then we deal with it
|
|
| 841 | -appropriately when /applying/ the substitution in `simplInId`.
|
|
| 886 | +`preInlineBetaUnconditionally`; and since the substitution maps an Id to a SimplClo,
|
|
| 887 | +the pending cast comes along for free. Then we deal with it appropriately when
|
|
| 888 | +/applying/ the substitution in `simplInId`.
|
|
| 889 | + |
|
| 890 | +Note [Optimising reflexivity]
|
|
| 891 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 892 | +It's important (for compiler performance) to get rid of reflexivity as soon
|
|
| 893 | +as it appears. See #11735, #14737, and #15019.
|
|
| 894 | + |
|
| 895 | +In particular, we want to behave well on
|
|
| 896 | + |
|
| 897 | + * e |> co1 |> co2
|
|
| 898 | + where the two happen to cancel out entirely. That is quite common;
|
|
| 899 | + e.g. a newtype wrapping and unwrapping cancel.
|
|
| 900 | + |
|
| 901 | + |
|
| 902 | + * (f |> co) @t1 @t2 ... @tn x1 .. xm
|
|
| 903 | + Here we will use pushCoTyArg and pushCoValArg successively, which
|
|
| 904 | + build up SelCo stacks. Silly to do that if co is reflexive.
|
|
| 905 | + |
|
| 906 | +However, we don't want to call isReflexiveCo too much, because it uses
|
|
| 907 | +type equality which is expensive on big types (#14737 comment:7).
|
|
| 908 | + |
|
| 909 | +A good compromise (determined experimentally) seems to be to call
|
|
| 910 | +isReflexiveCo
|
|
| 911 | + * when composing casts, and
|
|
| 912 | + * at the end
|
|
| 913 | + |
|
| 914 | +In investigating this I saw missed opportunities for on-the-fly
|
|
| 915 | +coercion shrinkage. See #15090.
|
|
| 916 | + |
|
| 917 | +Note [Avoid re-simplifying coercions]
|
|
| 918 | +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 919 | +In some benchmarks (with deeply nested cases) we successively push
|
|
| 920 | +casts onto the SimplCont. We don't want to call the coercion optimiser
|
|
| 921 | +on each successive composition -- that's at least quadratic. So:
|
|
| 922 | + |
|
| 923 | +* The CastIt constructor in SimplCont has a `sc_opt :: Bool` flag to
|
|
| 924 | + record whether the coercion optimiser has been applied to the coercion.
|
|
| 925 | + |
|
| 926 | +* In `simplCast`, when we see (Cast e co), we simplify `co` to get
|
|
| 927 | + an OutCoercion, and built a CastIt with sc_opt=True.
|
|
| 928 | + |
|
| 929 | + Actually not quite: if we are simplifying the result of inlining an
|
|
| 930 | + unfolding (seInlineDepth > 0), then instead of /optimising/ it again,
|
|
| 931 | + just /substitute/ which is cheaper. See `simplCoercion`.
|
|
| 932 | + |
|
| 933 | +* In `pushCast` if we combine this new coercion with an existing one,
|
|
| 934 | + we build a CastIt for (co1 ; co2) with sc_opt=False.
|
|
| 935 | + |
|
| 936 | +* When unpacking a CastIt, in `rebuild`, we optimise the (presumably
|
|
| 937 | + composed) coercion if sc_opt=False; this is done by `optOutCoercion`.
|
|
| 938 | + |
|
| 939 | +* When duplicating a continuation in `mkDupableContWithDmds`, before
|
|
| 940 | + duplicating a CastIt, optimise the coercion. Otherwise we'll end up
|
|
| 941 | + optimising it separately in the duplicate copies.
|
|
| 942 | + |
|
| 943 | +* See also Note [The MOutCoercion field of ContEx]
|
|
| 842 | 944 | -}
|
| 843 | 945 | |
| 844 | 946 | optOutCoercion :: SimplEnvIS -> OutCoercion -> Bool -> OutCoercion
|
| 845 | --- See Note [Avoid re-simplifying coercions] in GHC.Core.Opt.Simplify.Iteration
|
|
| 947 | +-- See Note [Avoid re-simplifying coercions]
|
|
| 846 | 948 | optOutCoercion env co already_optimised
|
| 847 | 949 | | already_optimised = co -- Ditto
|
| 848 | 950 | | otherwise = optCoercion opts empty_subst co
|
| ... | ... | @@ -862,7 +964,8 @@ pushCastMCo env (MCo co) cont = pushCast env co cont |
| 862 | 964 | |
| 863 | 965 | pushCast :: SimplEnv -> OutCoercion -> SimplCont -> SimplCont
|
| 864 | 966 | pushCast env co cont
|
| 865 | - = go co True cont
|
|
| 967 | + | isReflCo co = cont -- See Note [Optimising reflexivity]
|
|
| 968 | + | otherwise = go co True cont
|
|
| 866 | 969 | where
|
| 867 | 970 | |
| 868 | 971 | -- ToDo: pushCast Refl (ApplylToVal arg1 (ApplyToVal arg2 ...))
|
| ... | ... | @@ -871,7 +974,7 @@ pushCast env co cont |
| 871 | 974 | go co1 _ (CastIt { sc_co = co2, sc_cont = cont }) -- See Note [Optimising reflexivity] in GHC.Core.Opt.Simplify.Iteration
|
| 872 | 975 | = go (mkTransCo co1 co2) False cont
|
| 873 | 976 | -- False: (mkTransCo co1 co2) is not fully optimised
|
| 874 | - -- See Note [Avoid re-simplifying coercions] in GHC.Core.Opt.Simplify.Iteration
|
|
| 977 | + -- See Note [Avoid re-simplifying coercions]
|
|
| 875 | 978 | |
| 876 | 979 | go co co_is_opt (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = tail })
|
| 877 | 980 | | Just (tyL, arg_ty', m_co') <- pushCoTyArg co arg_ty
|
| ... | ... | @@ -886,21 +989,17 @@ pushCast env co cont |
| 886 | 989 | -- where co :: (s1->s2) ~ (t1->t2)
|
| 887 | 990 | -- co1 :: t1 ~ s1
|
| 888 | 991 | -- co2 :: s2 ~ t2
|
| 889 | - go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
|
|
| 890 | - , sc_cast = arg_mco, sc_cont = tail })
|
|
| 992 | + go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_cont = tail })
|
|
| 891 | 993 | | not co_is_opt
|
| 892 | 994 | = -- pushCoValArg duplicates the coercion, so optimise first
|
| 893 | 995 | go (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
|
| 894 | 996 | |
| 895 | 997 | | Just (tyL, m_co1, m_co2) <- pushCoValArg co
|
| 896 | 998 | = {-#SCC "addCoerce-pushCoValArg" #-}
|
| 897 | - -- Dealing with m_co1 is the entire reason for the sc_cast field
|
|
| 898 | - -- of ApplyToVal; see Note [The sc_cast field of ApplyToVal]
|
|
| 899 | - ApplyToVal { sc_arg = arg
|
|
| 900 | - , sc_env = arg_se
|
|
| 901 | - , sc_cast = arg_mco `mkTransMCo` m_co1
|
|
| 902 | - , sc_cont = go_mco m_co2 True tail
|
|
| 903 | - , sc_hole_ty = tyL }
|
|
| 999 | + -- See Note [The MOutCoercion field of ContEx]
|
|
| 1000 | + cont { sc_arg = mkCloCastMCo arg m_co1
|
|
| 1001 | + , sc_cont = go_mco m_co2 True tail
|
|
| 1002 | + , sc_hole_ty = tyL }
|
|
| 904 | 1003 | |
| 905 | 1004 | go co co_is_opt cont
|
| 906 | 1005 | | isReflCo co = cont -- Having this at the end makes a huge
|
| ... | ... | @@ -914,6 +1013,13 @@ pushCast env co cont |
| 914 | 1013 | go_mco MRefl _ cont = cont
|
| 915 | 1014 | go_mco (MCo co) opt cont = go co opt cont
|
| 916 | 1015 | |
| 1016 | +mkCloCastMCo :: SimplClo -> MOutCoercion -> SimplClo
|
|
| 1017 | +-- See Note [The MOutCoercion field of ContEx]
|
|
| 1018 | +mkCloCastMCo clo MRefl = clo
|
|
| 1019 | +mkCloCastMCo (DoneId v) (MCo co) = DoneEx (mkCast (Var v) co) NotJoinPoint
|
|
| 1020 | +mkCloCastMCo (DoneEx e _) (MCo co) = DoneEx (mkCast e co) NotJoinPoint
|
|
| 1021 | +mkCloCastMCo (ContEx se e mco) (MCo co) = ContEx se e (mco `mkTransMCo` MCo co)
|
|
| 1022 | + |
|
| 917 | 1023 | |
| 918 | 1024 | {-
|
| 919 | 1025 | ************************************************************************
|
| ... | ... | @@ -1227,19 +1333,17 @@ Wrinkles: |
| 1227 | 1333 | |
| 1228 | 1334 | -}
|
| 1229 | 1335 | |
| 1230 | -interestingArg :: SimplEnv -> StaticEnv -> CoreExpr -> ArgSummary
|
|
| 1336 | +interestingArg :: SimplEnv -> SimplClo -> ArgSummary
|
|
| 1231 | 1337 | -- See Note [Interesting arguments]
|
| 1232 | -interestingArg env se e
|
|
| 1233 | - = case se of
|
|
| 1234 | - Simplified {} -> go env 0 e
|
|
| 1235 | - UnSimplified static_env -> go (static_env `setInScopeFromE` env) 0 e
|
|
| 1338 | +interestingArg env clo
|
|
| 1339 | + = go_clo env 0 clo
|
|
| 1236 | 1340 | where
|
| 1341 | + go_clo _ n (DoneId v) = go_var n v
|
|
| 1342 | + go_clo env n (DoneEx e _) = go (zapSubstEnv env) n e
|
|
| 1343 | + go_clo env n (ContEx se e _) = go (se `setInScopeFromE` env) n e
|
|
| 1344 | + |
|
| 1237 | 1345 | -- n is # value args to which the expression is applied
|
| 1238 | - go env n (Var v)
|
|
| 1239 | - = case substId env v of
|
|
| 1240 | - DoneId v' -> go_var n v'
|
|
| 1241 | - DoneEx e _ -> go (zapSubstEnv env) n e
|
|
| 1242 | - ContEx se e _mco -> go (se `setInScopeFromE` env) n e
|
|
| 1346 | + go env n (Var v) = go_clo env n (substId env v)
|
|
| 1243 | 1347 | |
| 1244 | 1348 | go _ _ (Lit l)
|
| 1245 | 1349 | | isLitRubbish l = NonTrivArg -- See (IA3) in Note [Interesting arguments]
|
| ... | ... | @@ -1738,15 +1842,15 @@ is a term (not a coercion) so we can't necessarily inline the latter in |
| 1738 | 1842 | the former.
|
| 1739 | 1843 | -}
|
| 1740 | 1844 | |
| 1741 | -preInlineUnconditionally
|
|
| 1845 | +preInlineLetUnconditionally
|
|
| 1742 | 1846 | :: SimplEnv -> TopLevelFlag -> InId
|
| 1743 | - -> StaticEnv -> CoreExpr -> MOutCoercion -- The argument
|
|
| 1847 | + -> InExpr -> SimplEnv -- These two go together
|
|
| 1744 | 1848 | -> Maybe SimplEnv -- Returned env has extended substitution
|
| 1745 | 1849 | -- Precondition: rhs satisfies the let-can-float invariant
|
| 1746 | 1850 | -- See Note [Core let-can-float invariant] in GHC.Core
|
| 1747 | 1851 | -- Reason: we don't want to inline single uses, or discard dead bindings,
|
| 1748 | 1852 | -- for unlifted, side-effect-ful bindings
|
| 1749 | -preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
|
|
| 1853 | +preInlineLetUnconditionally env top_lvl bndr rhs rhs_env
|
|
| 1750 | 1854 | | not pre_inline_unconditionally = Nothing
|
| 1751 | 1855 | | not active = Nothing
|
| 1752 | 1856 | | isTopLevel top_lvl && isDeadEndId bndr = Nothing -- Note [Top-level bottoming Ids]
|
| ... | ... | @@ -1758,26 +1862,15 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco |
| 1758 | 1862 | |
| 1759 | 1863 | -- See Note [Stable unfoldings and preInlineUnconditionally]
|
| 1760 | 1864 | | not (isInlinePragma inline_prag)
|
| 1761 | - , Just inl <- maybeUnfoldingTemplate unf = assertPpr (isReflMCo rhs_mco) (ppr bndr) $
|
|
| 1762 | - Just $! (extend_subst_with inl)
|
|
| 1865 | + , Just inl <- maybeUnfoldingTemplate unf = Just $! (extend_subst_with inl)
|
|
| 1763 | 1866 | |
| 1764 | 1867 | | otherwise = Nothing
|
| 1765 | 1868 | where
|
| 1766 | 1869 | unf = idUnfolding bndr
|
| 1767 | 1870 | |
| 1768 | - -- If the rhs is /not/ already simplified, extend the envt with ContEx, which captures
|
|
| 1769 | - -- the the lexical environment for us to restore in `simplInId`.
|
|
| 1770 | - -- If the rhs /is/ already simplified, then extend the envt with DoneEx;
|
|
| 1771 | - -- That makes `simplInId` call `simplOutExpr` which avoids re-simplifying
|
|
| 1772 | - -- the RHS.
|
|
| 1773 | - -- See Note [Avoid repeated simplification] in GHC.Core.Opt.Simplify.Iteration
|
|
| 1774 | - extend_subst_with inl_rhs
|
|
| 1775 | - = extendIdSubst env bndr $!
|
|
| 1776 | - case rhs_se of
|
|
| 1777 | - Simplified _ -> case rhs_mco of
|
|
| 1778 | - MRefl -> DoneEx inl_rhs NotJoinPoint -- Common case
|
|
| 1779 | - MCo co -> DoneEx (mkCast inl_rhs co) NotJoinPoint
|
|
| 1780 | - UnSimplified rhs_env -> ContEx rhs_env inl_rhs rhs_mco
|
|
| 1871 | + -- The rhs is not yet simplified, so extend the envt with ContEx, which
|
|
| 1872 | + -- captures the lexical environment for us to restore in `simplInId`.
|
|
| 1873 | + extend_subst_with inl_rhs = extendIdSubst env bndr $! ContEx rhs_env inl_rhs MRefl
|
|
| 1781 | 1874 | |
| 1782 | 1875 | one_occ IAmDead = True -- Happens in ((\x.1) v)
|
| 1783 | 1876 | one_occ OneOcc{ occ_n_br = 1
|
| ... | ... | @@ -1793,39 +1886,6 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco |
| 1793 | 1886 | -- See Note [pre/postInlineUnconditionally in gentle mode]
|
| 1794 | 1887 | inline_prag = idInlinePragma bndr
|
| 1795 | 1888 | |
| 1796 | --- Be very careful before inlining inside a lambda, because (a) we must not
|
|
| 1797 | --- invalidate occurrence information, and (b) we want to avoid pushing a
|
|
| 1798 | --- single allocation (here) into multiple allocations (inside lambda).
|
|
| 1799 | --- Inlining a *function* with a single *saturated* call would be ok, mind you.
|
|
| 1800 | --- || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
|
|
| 1801 | --- where
|
|
| 1802 | --- is_cheap = exprIsCheap rhs
|
|
| 1803 | --- ok = is_cheap && int_cxt
|
|
| 1804 | - |
|
| 1805 | - -- int_cxt The context isn't totally boring
|
|
| 1806 | - -- E.g. let f = \ab.BIG in \y. map f xs
|
|
| 1807 | - -- Don't want to substitute for f, because then we allocate
|
|
| 1808 | - -- its closure every time the \y is called
|
|
| 1809 | - -- But: let f = \ab.BIG in \y. map (f y) xs
|
|
| 1810 | - -- Now we do want to substitute for f, even though it's not
|
|
| 1811 | - -- saturated, because we're going to allocate a closure for
|
|
| 1812 | - -- (f y) every time round the loop anyhow.
|
|
| 1813 | - |
|
| 1814 | - -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
|
|
| 1815 | - -- so substituting rhs inside a lambda doesn't change the occ info.
|
|
| 1816 | - -- Sadly, not quite the same as exprIsHNF.
|
|
| 1817 | - canInlineInLam (Lit _) = True
|
|
| 1818 | - canInlineInLam (Cast e _) = canInlineInLam e
|
|
| 1819 | - canInlineInLam (Lam b e) = isRuntimeVar b || canInlineInLam e
|
|
| 1820 | - canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
|
|
| 1821 | - canInlineInLam (Var v) = case idOccInfo v of
|
|
| 1822 | - OneOcc { occ_in_lam = IsInsideLam } -> True
|
|
| 1823 | - ManyOccs {} -> True
|
|
| 1824 | - _ -> False
|
|
| 1825 | - canInlineInLam _ = False
|
|
| 1826 | - -- not ticks. Counting ticks cannot be duplicated, and non-counting
|
|
| 1827 | - -- ticks around a Lam will disappear anyway.
|
|
| 1828 | - |
|
| 1829 | 1889 | early_phase =
|
| 1830 | 1890 | case sePhase env of
|
| 1831 | 1891 | SimplPhase p -> p /= FinalPhase
|
| ... | ... | @@ -1856,6 +1916,97 @@ preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco |
| 1856 | 1916 | -- (Nor can we check for `exprIsExpandable rhs`, because that needs to look
|
| 1857 | 1917 | -- at the non-existent unfolding for the `I# 2#` which is also floated out.)
|
| 1858 | 1918 | |
| 1919 | +preInlineBetaUnconditionally
|
|
| 1920 | + :: SimplEnv -> Levity -> InId
|
|
| 1921 | + -> SimplClo -- The argument
|
|
| 1922 | + -> Maybe SimplEnv -- Returned env has extended substitution
|
|
| 1923 | +-- Like preInlineLetUnconditionally, but for a beta-redex (\bndr. body) arg
|
|
| 1924 | +-- The argument may or may not be already simplified (DoneEx or ContEx)
|
|
| 1925 | +--
|
|
| 1926 | +-- The binder is a lambda binder and so lacks most IdInfo;
|
|
| 1927 | +-- see Note [Core binder IdInfo invariants]
|
|
| 1928 | +--
|
|
| 1929 | +-- Compared to preInlineLetUnconditionally we omit some checks:
|
|
| 1930 | +-- * The binder is never top-level, so no need for the
|
|
| 1931 | +-- Note [Top-level bottoming Ids] check, nor for `early_phase`
|
|
| 1932 | +-- * A lambda binder is never a join point, so no need for the
|
|
| 1933 | +-- Note [Do not inline exit join points] check
|
|
| 1934 | +-- * A lambda binder never has an inline pragma, a stable unfolding, or RULES
|
|
| 1935 | +-- (see `lamBndrInfoOK`), so no need to check activation, nor for
|
|
| 1936 | +-- Note [Stable unfoldings and preInlineUnconditionally]
|
|
| 1937 | +--
|
|
| 1938 | +-- And we add one extra one
|
|
| 1939 | +-- * Check the let-can-float invariant, and don't inline if not
|
|
| 1940 | + |
|
| 1941 | +preInlineBetaUnconditionally env levity bndr arg
|
|
| 1942 | + | assertPpr (lamBndrInfoOK bndr) (ppr bndr) $
|
|
| 1943 | + not pre_inline_unconditionally = Nothing
|
|
| 1944 | + | isCoVar bndr = Nothing -- Note [Do not inline CoVars unconditionally]
|
|
| 1945 | + | not (one_occ (idOccInfo bndr)) = Nothing
|
|
| 1946 | + | needs_case_binding = Nothing -- Enforce the let-can-float invariant
|
|
| 1947 | + | otherwise = Just $! extendIdSubst env bndr arg
|
|
| 1948 | + -- If the arg is not yet simplified, it is a ContEx, which captures the
|
|
| 1949 | + -- lexical environment for us to restore in `simplInId`.
|
|
| 1950 | + -- If the arg is already simplified, then it is a DoneEx;
|
|
| 1951 | + -- That makes `simplInId` call `simplOutExpr` which avoids re-simplifying
|
|
| 1952 | + -- the arg.
|
|
| 1953 | + -- See Note [Avoid repeated simplification] in GHC.Core.Opt.Simplify.Iteration
|
|
| 1954 | + where
|
|
| 1955 | + pre_inline_unconditionally = sePreInline env
|
|
| 1956 | + |
|
| 1957 | + needs_case_binding = needsCaseBindingL levity rhs
|
|
| 1958 | + -- Ok to test an InExpr or OutExpr in needsCaseBindingL because
|
|
| 1959 | + -- exprOkForSpeculation is stable under simplification
|
|
| 1960 | + |
|
| 1961 | + rhs :: CoreExpr -- Can be InExpr or OutExpr, but here it does not matter
|
|
| 1962 | + rhs = case arg of
|
|
| 1963 | + ContEx _ e _ -> e -- InExpr
|
|
| 1964 | + DoneEx e _ -> e -- OutExpr
|
|
| 1965 | + DoneId v -> Var v -- OutExpr
|
|
| 1966 | + |
|
| 1967 | + one_occ IAmDead = True -- Happens in ((\x.1) v)
|
|
| 1968 | + one_occ OneOcc{ occ_n_br = 1
|
|
| 1969 | + , occ_in_lam = NotInsideLam } = True
|
|
| 1970 | + one_occ OneOcc{ occ_n_br = 1
|
|
| 1971 | + , occ_in_lam = IsInsideLam
|
|
| 1972 | + , occ_int_cxt = IsInteresting } = canInlineInLam rhs
|
|
| 1973 | + one_occ _ = False
|
|
| 1974 | + |
|
| 1975 | + |
|
| 1976 | +canInlineInLam :: CoreExpr -> Bool
|
|
| 1977 | +-- Be very careful before inlining inside a lambda, because (a) we must not
|
|
| 1978 | +-- invalidate occurrence information, and (b) we want to avoid pushing a
|
|
| 1979 | +-- single allocation (here) into multiple allocations (inside lambda).
|
|
| 1980 | +-- Inlining a *function* with a single *saturated* call would be ok, mind you.
|
|
| 1981 | +-- || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
|
|
| 1982 | +-- where
|
|
| 1983 | +-- is_cheap = exprIsCheap rhs
|
|
| 1984 | +-- ok = is_cheap && int_cxt
|
|
| 1985 | + |
|
| 1986 | + -- int_cxt The context isn't totally boring
|
|
| 1987 | + -- E.g. let f = \ab.BIG in \y. map f xs
|
|
| 1988 | + -- Don't want to substitute for f, because then we allocate
|
|
| 1989 | + -- its closure every time the \y is called
|
|
| 1990 | + -- But: let f = \ab.BIG in \y. map (f y) xs
|
|
| 1991 | + -- Now we do want to substitute for f, even though it's not
|
|
| 1992 | + -- saturated, because we're going to allocate a closure for
|
|
| 1993 | + -- (f y) every time round the loop anyhow.
|
|
| 1994 | + |
|
| 1995 | + -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
|
|
| 1996 | + -- so substituting rhs inside a lambda doesn't change the occ info.
|
|
| 1997 | + -- Sadly, not quite the same as exprIsHNF.
|
|
| 1998 | +canInlineInLam (Lit _) = True
|
|
| 1999 | +canInlineInLam (Cast e _) = canInlineInLam e
|
|
| 2000 | +canInlineInLam (Lam b e) = isRuntimeVar b || canInlineInLam e
|
|
| 2001 | +canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
|
|
| 2002 | +canInlineInLam (Var v) = case idOccInfo v of
|
|
| 2003 | + OneOcc { occ_in_lam = IsInsideLam } -> True
|
|
| 2004 | + ManyOccs {} -> True
|
|
| 2005 | + _ -> False
|
|
| 2006 | +canInlineInLam _ = False
|
|
| 2007 | + -- not ticks. Counting ticks cannot be duplicated, and non-counting
|
|
| 2008 | + -- ticks around a Lam will disappear anyway.
|
|
| 2009 | + |
|
| 1859 | 2010 | {-
|
| 1860 | 2011 | ************************************************************************
|
| 1861 | 2012 | * *
|
| ... | ... | @@ -2068,7 +2068,11 @@ mkSeqs seqees res_ty rhs = |
| 2068 | 2068 | -- Argument representing strict field and it's worth passing via cbv
|
| 2069 | 2069 | | wantCbvForId arg_id
|
| 2070 | 2070 | = Case (Var arg_id)
|
| 2071 | - (localiseId arg_id) -- See (SCF1) in Note [SpecConstr and strict fields]
|
|
| 2071 | + (mkCaseBndrFromLetBndr (localiseId arg_id))
|
|
| 2072 | + -- localiseId: see (SCF1) in Note [SpecConstr and strict fields]
|
|
| 2073 | + -- mkCaseBndrFromLetBndr: arg_id may have IdInfo (e.g. an unfolding,
|
|
| 2074 | + -- if it is a global) that a case binder must not have; see
|
|
| 2075 | + -- Note [Core binder IdInfo invariants] in GHC.Core
|
|
| 2072 | 2076 | res_ty
|
| 2073 | 2077 | ([Alt DEFAULT [] rhs])
|
| 2074 | 2078 |
| ... | ... | @@ -1041,7 +1041,7 @@ unbox_one_arg opts arg_var |
| 1041 | 1041 | |
| 1042 | 1042 | -- Apply str info to new args. Also remove OtherCon unfoldings so they
|
| 1043 | 1043 | -- don't end up in lambda binders of the worker.
|
| 1044 | - -- See Note [Never put `OtherCon` unfoldings on lambda binders]
|
|
| 1044 | + -- See (CBI1) in Note [Core binder IdInfo invariants]
|
|
| 1045 | 1045 | arg_ids' = map zapIdUnfolding $
|
| 1046 | 1046 | zipWithEqual setIdDemandInfo arg_ids ds
|
| 1047 | 1047 | |
| ... | ... | @@ -1711,8 +1711,7 @@ unbox_one_result opts res_bndr |
| 1711 | 1711 | move_transit_vars :: [Id] -> (CoreExpr -> CoreExpr -> CoreExpr, CoreExpr)
|
| 1712 | 1712 | move_transit_vars vars
|
| 1713 | 1713 | | [var] <- vars
|
| 1714 | - , let var_ty = idType var
|
|
| 1715 | - , isUnliftedType var_ty || exprIsHNF (Var var)
|
|
| 1714 | + , varIsHNF var -- NB: True of variables of unlifted type
|
|
| 1716 | 1715 | -- See Note [No unboxed tuple for single, unlifted transit var]
|
| 1717 | 1716 | -- * Wrapper: `unbox scrut alt = (case <scrut> of a -> <alt>)`
|
| 1718 | 1717 | -- * Worker: `tup = a`
|
| ... | ... | @@ -1816,7 +1815,7 @@ return unboxed instead of in an unboxed singleton tuple: |
| 1816 | 1815 | We want `$wh :: Int# -> [Int]`.
|
| 1817 | 1816 | We'd get `$wh :: Int# -> (# [Int] #)`.
|
| 1818 | 1817 | |
| 1819 | -By considering vars as unlifted that satisfy 'exprIsHNF', we catch (3).
|
|
| 1818 | +By considering vars as unlifted that satisfy 'varIsHNF', we catch (3).
|
|
| 1820 | 1819 | Why not check for 'exprOkForSpeculation'? Quite perplexingly, evaluated vars
|
| 1821 | 1820 | are not ok-for-spec, see Note [exprOkForSpeculation and evaluated variables].
|
| 1822 | 1821 | For (1) and (2) we would have to look at the term. WW only looks at the
|
| ... | ... | @@ -637,6 +637,7 @@ instance Outputable IdInfo where |
| 637 | 637 | [ (has_prag, text "InlPrag=" <> pprInlineDebug prag_info)
|
| 638 | 638 | , (has_occ, text "Occ=" <> ppr occ_info)
|
| 639 | 639 | , (has_dmd, text "Dmd=" <> ppr dmd_info)
|
| 640 | + , (has_cpr, text "Cpr=" <> ppr dmd_info)
|
|
| 640 | 641 | , (has_lbv , text "OS=" <> ppr lbv_info)
|
| 641 | 642 | , (has_arity, text "Arity=" <> int arity)
|
| 642 | 643 | , (has_called_arity, text "CallArity=" <> int called_arity)
|
| ... | ... | @@ -658,6 +659,9 @@ instance Outputable IdInfo where |
| 658 | 659 | lbv_info = oneShotInfo info
|
| 659 | 660 | has_lbv = not (hasNoOneShotInfo lbv_info)
|
| 660 | 661 | |
| 662 | + cpr = cprSigInfo info
|
|
| 663 | + has_cpr = not $ isTopCprSig cpr
|
|
| 664 | + |
|
| 661 | 665 | arity = arityInfo info
|
| 662 | 666 | has_arity = arity /= 0
|
| 663 | 667 |
| ... | ... | @@ -29,7 +29,7 @@ module GHC.Core.Utils ( |
| 29 | 29 | exprIsTrivial, getIdFromTrivialExpr, getIdFromTrivialExpr_maybe,
|
| 30 | 30 | trivial_expr_fold,
|
| 31 | 31 | exprIsDupable, exprIsCheap, exprIsExpandable, exprIsCheapX, CheapAppFun,
|
| 32 | - exprIsHNF, exprOkForSpeculation, exprOkToDiscard, exprOkForSpecEval,
|
|
| 32 | + exprIsHNF, varIsHNF, exprOkForSpeculation, exprOkToDiscard, exprOkForSpecEval,
|
|
| 33 | 33 | exprIsWorkFree, exprIsConLike,
|
| 34 | 34 | isCheapApp, isExpandableApp, isSaturatedConApp,
|
| 35 | 35 | exprIsTickedString, exprIsTickedString_maybe,
|
| ... | ... | @@ -756,7 +756,10 @@ bindNonRec bndr rhs body |
| 756 | 756 | | needsCaseBinding (idType bndr) rhs = case_bind
|
| 757 | 757 | | otherwise = let_bind
|
| 758 | 758 | where
|
| 759 | - case_bind = mkDefaultCase rhs bndr body
|
|
| 759 | + case_bind = mkDefaultCase rhs (mkCaseBndrFromLetBndr bndr) body
|
|
| 760 | + -- mkCaseBndrFromLetBndr: bndr may have IdInfo suitable for a
|
|
| 761 | + -- let-binder; see Note [Core binder IdInfo invariants]
|
|
| 762 | + -- in GHC.Core
|
|
| 760 | 763 | let_bind = Let (NonRec bndr rhs) body
|
| 761 | 764 | |
| 762 | 765 | -- | `needsCaseBinding` tests whether we have to use a @case@ rather than @let@
|
| ... | ... | @@ -2630,12 +2633,37 @@ it doesn't have the trickiness of the let-can-float invariant to worry about. |
| 2630 | 2633 | exprIsHNF :: CoreExpr -> Bool -- True => Value-lambda, constructor, PAP
|
| 2631 | 2634 | exprIsHNF = exprIsHNFlike isDataConWorkId isEvaldUnfolding True
|
| 2632 | 2635 | |
| 2636 | +-- | @varIsHNF v@ is the same as @exprIsHNF (Var v)@, but avoids building
|
|
| 2637 | +-- the @Var@ only to take it apart again
|
|
| 2638 | +varIsHNF :: Var -> Bool
|
|
| 2639 | +varIsHNF = varIsHNFlike isDataConWorkId isEvaldUnfolding
|
|
| 2640 | + |
|
| 2633 | 2641 | -- | Similar to 'exprIsHNF' but includes CONLIKE functions as well as
|
| 2634 | 2642 | -- data constructors. Conlike arguments are considered interesting by the
|
| 2635 | 2643 | -- inliner.
|
| 2636 | 2644 | exprIsConLike :: CoreExpr -> Bool -- True => lambda, conlike, PAP
|
| 2637 | 2645 | exprIsConLike = exprIsHNFlike isConLikeId isConLikeUnfolding False
|
| 2638 | 2646 | |
| 2647 | +varIsHNFlike :: (Var -> Bool) -> (Unfolding -> Bool) -> Var -> Bool
|
|
| 2648 | +-- The (Var v) case of exprIsHNFlike
|
|
| 2649 | +{-# INLINE varIsHNFlike #-}
|
|
| 2650 | +varIsHNFlike is_con is_con_unf v
|
|
| 2651 | + = idArity v > 0 || is_con v
|
|
| 2652 | + -- A PAP is a value, as is a nullary constructor, so that [] and ()
|
|
| 2653 | + -- are values, for example; and (e.g.) primops that don't have unfoldings.
|
|
| 2654 | + -- This is (id_app_is_value v []) in exprIsHNFlike
|
|
| 2655 | + |
|
| 2656 | + || is_con_unf (idUnfolding v)
|
|
| 2657 | + -- Check the thing's unfolding; it might be bound to a value
|
|
| 2658 | + -- or to a guaranteed-evaluated variable (isEvaldUnfolding)
|
|
| 2659 | + -- Contrast with Note [exprOkForSpeculation and evaluated variables]
|
|
| 2660 | + -- We don't look through loop breakers here, which is a bit conservative
|
|
| 2661 | + -- but otherwise I worry that if an Id's unfolding is just itself,
|
|
| 2662 | + -- we could get an infinite loop
|
|
| 2663 | + |
|
| 2664 | + || definitelyUnliftedType (idType v)
|
|
| 2665 | + -- Unlifted binders are always evaluated (#20140)
|
|
| 2666 | + |
|
| 2639 | 2667 | -- | Returns true for values or value-like expressions. These are lambdas,
|
| 2640 | 2668 | -- constructors / CONLIKE functions (as determined by the function argument)
|
| 2641 | 2669 | -- or PAPs.
|
| ... | ... | @@ -2649,20 +2677,8 @@ exprIsHNFlike is_con is_con_unf rubbish_lit_result e |
| 2649 | 2677 | = -- pprTraceWith "hnf" (\r -> ppr r <+> ppr e) $
|
| 2650 | 2678 | is_hnf_like e
|
| 2651 | 2679 | where
|
| 2652 | - is_hnf_like (Var v) -- NB: There are no value args at this point
|
|
| 2653 | - = id_app_is_value v [] -- Catches nullary constructors,
|
|
| 2654 | - -- so that [] and () are values, for example
|
|
| 2655 | - -- and (e.g.) primops that don't have unfoldings
|
|
| 2656 | - || is_con_unf (idUnfolding v)
|
|
| 2657 | - -- Check the thing's unfolding; it might be bound to a value
|
|
| 2658 | - -- or to a guaranteed-evaluated variable (isEvaldUnfolding)
|
|
| 2659 | - -- Contrast with Note [exprOkForSpeculation and evaluated variables]
|
|
| 2660 | - -- We don't look through loop breakers here, which is a bit conservative
|
|
| 2661 | - -- but otherwise I worry that if an Id's unfolding is just itself,
|
|
| 2662 | - -- we could get an infinite loop
|
|
| 2663 | - |
|
| 2664 | - || definitelyUnliftedType (idType v)
|
|
| 2665 | - -- Unlifted binders are always evaluated (#20140)
|
|
| 2680 | + is_hnf_like (Var v) = varIsHNFlike is_con is_con_unf v
|
|
| 2681 | + -- NB: There are no value args at this point
|
|
| 2666 | 2682 | |
| 2667 | 2683 | is_hnf_like (Lit lit)
|
| 2668 | 2684 | | isLitRubbish lit = rubbish_lit_result
|
| ... | ... | @@ -264,8 +264,14 @@ bindMatchId new mid body |
| 264 | 264 | -- Used to force variables when desugaring strict binders. It's crucial that the
|
| 265 | 265 | -- variable is shadowed by the case binder. See Wrinkle 1 in
|
| 266 | 266 | -- Note [Desugar Strict binds] in GHC.HsToCore.Binds.
|
| 267 | +--
|
|
| 268 | +-- The case binder has the same Name (and hence Unique), type and multiplicity
|
|
| 269 | +-- as `var`, but not its IdInfo: `var` may have, say, a NOINLINE pragma, but a
|
|
| 270 | +-- case binder must not; see Note [Core binder IdInfo invariants]
|
|
| 271 | +-- in GHC.Core, and #27965. E.g. `res1` in GHC.Internal.Control.Monad.ST.Lazy.Imp
|
|
| 272 | +-- has a NOINLINE pragma.
|
|
| 267 | 273 | seqVar :: Var -> CoreExpr -> CoreExpr
|
| 268 | -seqVar var body = mkDefaultCase (Var var) var body
|
|
| 274 | +seqVar var body = mkDefaultCase (Var var) (mkCaseBndrFromLetBndr var) body
|
|
| 269 | 275 | |
| 270 | 276 | mkCoLetMatchResult :: HasDebugCallStack => CoreBind -> MatchResult CoreExpr -> MatchResult CoreExpr
|
| 271 | 277 | mkCoLetMatchResult bind = fmap (mkCoreLet bind)
|
| ... | ... | @@ -94,6 +94,7 @@ module GHC.Types.Id ( |
| 94 | 94 | idArity,
|
| 95 | 95 | idCallArity, idFunRepArity,
|
| 96 | 96 | idSpecialisation, idCoreRules, idHasRules,
|
| 97 | + lamBndrInfoOK,
|
|
| 97 | 98 | idCafInfo, idLFInfo_maybe,
|
| 98 | 99 | idOneShotInfo,
|
| 99 | 100 | idOccInfo,
|
| ... | ... | @@ -102,7 +103,7 @@ module GHC.Types.Id ( |
| 102 | 103 | alwaysActiveUnfoldingFun, whenActiveUnfoldingFun, noUnfoldingFun,
|
| 103 | 104 | |
| 104 | 105 | -- ** Writing 'IdInfo' fields
|
| 105 | - setIdUnfolding, zapIdUnfolding, setCaseBndrEvald,
|
|
| 106 | + setIdUnfolding, zapIdUnfolding, setCaseBndrEvald, mkCaseBndrFromLetBndr,
|
|
| 106 | 107 | setIdArity,
|
| 107 | 108 | setIdCallArity,
|
| 108 | 109 | |
| ... | ... | @@ -881,10 +882,21 @@ setCaseBndrEvald :: StrictnessMark -> Id -> Id |
| 881 | 882 | -- itself, and any pattern-bound variables that are argument of a
|
| 882 | 883 | -- strict constructor. It just marks the variable as already-evaluated,
|
| 883 | 884 | -- so that (for example) a subsequent 'seq' can be dropped
|
| 885 | +-- See Note [Evaluated-ness on case binders] in GHC.Core
|
|
| 884 | 886 | setCaseBndrEvald str id
|
| 885 | 887 | | isMarkedStrict str = id `setIdUnfolding` evaldUnfolding
|
| 886 | 888 | | otherwise = id
|
| 887 | 889 | |
| 890 | +-- | Make a case binder from a binder that might have been let-bound, e.g.
|
|
| 891 | +-- let x = rhs in body ==> case rhs of x { DEFAULT -> body }
|
|
| 892 | +-- The let-binder may have IdInfo (an unfolding, an inline pragma, RULES)
|
|
| 893 | +-- that a case binder must not have, so we keep its Name, type, multiplicity
|
|
| 894 | +-- and IdDetails, but reset its IdInfo, except that we record that it is
|
|
| 895 | +-- evaluated.
|
|
| 896 | +-- See Note [Core binder IdInfo invariants] in GHC.Core
|
|
| 897 | +mkCaseBndrFromLetBndr :: Id -> Id
|
|
| 898 | +mkCaseBndrFromLetBndr id = id `setIdInfo` (vanillaIdInfo `setUnfoldingInfo` evaldUnfolding)
|
|
| 899 | + |
|
| 888 | 900 | -- | Similar to trimUnfolding, but also removes evaldness info.
|
| 889 | 901 | zapIdUnfolding :: Id -> Id
|
| 890 | 902 | zapIdUnfolding v
|
| ... | ... | @@ -905,6 +917,32 @@ idCoreRules id = ruleInfoRules (idSpecialisation id) |
| 905 | 917 | idHasRules :: Id -> Bool
|
| 906 | 918 | idHasRules id = not (isEmptyRuleInfo (idSpecialisation id))
|
| 907 | 919 | |
| 920 | +-- | True <=> the Id has only the IdInfo permitted on a lambda, case, or
|
|
| 921 | +-- case-alternative binder. See the table in Note [Core binder IdInfo invariants]
|
|
| 922 | +-- in GHC.Core; Core Lint checks this invariant.
|
|
| 923 | +--
|
|
| 924 | +-- We allow occurrence info, demand info, and one-shot info (which the table
|
|
| 925 | +-- permits only on lambda binders, but a case binder may be about to become one).
|
|
| 926 | +-- We also allow an `OtherCon []` unfolding; lambda binders must have no unfolding
|
|
| 927 | +-- at all, but Lint checks that separately.
|
|
| 928 | +lamBndrInfoOK :: Id -> Bool
|
|
| 929 | +lamBndrInfoOK id
|
|
| 930 | + = isDefaultInlinePragma (inlinePragInfo info)
|
|
| 931 | + && isNopSig (dmdSigInfo info)
|
|
| 932 | + && isTopCprSig (cprSigInfo info)
|
|
| 933 | + && mayHaveCafRefs (cafInfo info)
|
|
| 934 | + && arityInfo info == unknownArity
|
|
| 935 | + && callArityInfo info == unknownArity
|
|
| 936 | + && isEmptyRuleInfo (ruleInfo info)
|
|
| 937 | + && unf_ok (realUnfoldingInfo info)
|
|
| 938 | + where
|
|
| 939 | + info = idInfo id
|
|
| 940 | + |
|
| 941 | + -- See Note [Evaluated-ness on case binders] in GHC.Core
|
|
| 942 | + unf_ok NoUnfolding = True
|
|
| 943 | + unf_ok (OtherCon []) = True
|
|
| 944 | + unf_ok _ = False
|
|
| 945 | + |
|
| 908 | 946 | setIdSpecialisation :: Id -> RuleInfo -> Id
|
| 909 | 947 | setIdSpecialisation id spec_info = modifyIdInfo (`setRuleInfo` spec_info) id
|
| 910 | 948 |
| 1 | +{-# LANGUAGE MagicHash #-}
|
|
| 2 | + |
|
| 3 | +module T27962 where
|
|
| 4 | + |
|
| 5 | +import GHC.Exts
|
|
| 6 | + |
|
| 7 | +newtype N = MkN Int
|
|
| 8 | + |
|
| 9 | +-- After inlining myRun, we get (runRW# @LiftedRep @Int |> co) (\_ -> ...)
|
|
| 10 | +-- and the simplifier pushes co into the argument of runRW#.
|
|
| 11 | +-- #27962: the simplifier dropped that cast, yielding ill-typed Core
|
|
| 12 | +myRun :: (State# RealWorld -> N) -> N
|
|
| 13 | +myRun = coerce (runRW# :: (State# RealWorld -> Int) -> Int)
|
|
| 14 | +{-# INLINE myRun #-}
|
|
| 15 | + |
|
| 16 | +foo x = myRun (\_ -> MkN (x+1)) |
| 1 | +{-# OPTIONS_GHC -Wno-inline-rule-shadowing #-}
|
|
| 2 | + |
|
| 3 | +module T27963 where
|
|
| 4 | + |
|
| 5 | +-- This test is pretty delicate because it relies on a function
|
|
| 6 | +-- that has BOTH a rule AND an INLINE pragma
|
|
| 7 | +--
|
|
| 8 | +-- See #27963 for some discussion
|
|
| 9 | +--
|
|
| 10 | +-- Still, it should (just) work
|
|
| 11 | + |
|
| 12 | +import GHC.Exts
|
|
| 13 | + |
|
| 14 | +newtype N = MkN Int
|
|
| 15 | + |
|
| 16 | +f x = x
|
|
| 17 | +{-# INLINE f #-}
|
|
| 18 | +{-# RULES "f/42" forall x. f x = 42::Int #-}
|
|
| 19 | + |
|
| 20 | +-- The rule "f/42" should fire in both h1 and h2
|
|
| 21 | +h1,h2 :: N -> Int
|
|
| 22 | +h1 n = f (coerce n) + 0
|
|
| 23 | +h2 n = (coerce f) n + 0 -- #27963: the rule did not fire here |
| 1 | +Rule fired: f/42 (T27963)
|
|
| 2 | +Rule fired: f/42 (T27963) |
| 1 | +-- Lint checks that we don't produce a lambda-binder
|
|
| 2 | +-- with a NOINLINE pragma on it (#27965)
|
|
| 3 | + |
|
| 4 | +module T27965 where
|
|
| 5 | + |
|
| 6 | +h fm s = let {-# NOINLINE res1 #-}
|
|
| 7 | + !res1 = fm s
|
|
| 8 | + !(f, s') = res1
|
|
| 9 | + in (f+1::Int, s') |
| ... | ... | @@ -629,3 +629,7 @@ test('T27749', |
| 629 | 629 | test('T27629', only_ways(['optasm']), makefile_test, ['T27629'])
|
| 630 | 630 | test('T27936', normal, compile, [''])
|
| 631 | 631 | test('T27910', grep_errmsg(r'KnownBranch'), compile, ['-O -dno-typeable-binds -ddump-simpl-stats -dsuppress-uniques'])
|
| 632 | +test('T27962', normal, compile, [''])
|
|
| 633 | +test('T27962a', [extra_files(['T27962.hs'])], multimod_compile, ['T27962', '-v0 -O'])
|
|
| 634 | +test('T27963', [grep_errmsg(r'f/42')], compile, ['-O -ddump-rule-firings'])
|
|
| 635 | +test('T27965', normal, compile, ['']) |