Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC
Commits:
-
74d3772d
by Simon Peyton Jones at 2026-05-02T00:55:09+01:00
11 changed files:
- compiler/GHC/Core.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/Types/Id/Make.hs
Changes:
| ... | ... | @@ -84,9 +84,13 @@ module GHC.Core ( |
| 84 | 84 | IsOrphan(..), isOrphan, notOrphan, chooseOrphanAnchor,
|
| 85 | 85 | |
| 86 | 86 | -- * Core rule data types
|
| 87 | - CoreRule(..),
|
|
| 87 | + CoreRule(..), RuleMatch(..),
|
|
| 88 | 88 | RuleName, RuleFun, IdUnfoldingFun, InScopeEnv(..), RuleOpts,
|
| 89 | 89 | |
| 90 | + -- * Floats
|
|
| 91 | + FloatBind(..), FloatBinds, emptyFloatBinds, isEmptyFloatBinds,
|
|
| 92 | + floatBinders, floatsBinders,
|
|
| 93 | + |
|
| 90 | 94 | -- ** Operations on 'CoreRule's
|
| 91 | 95 | ruleArity, ruleName, ruleIdName, ruleActivation,
|
| 92 | 96 | setRuleIdName, ruleModule,
|
| ... | ... | @@ -116,6 +120,8 @@ import GHC.Utils.Misc |
| 116 | 120 | import GHC.Utils.Outputable
|
| 117 | 121 | import GHC.Utils.Panic
|
| 118 | 122 | |
| 123 | +import GHC.Data.OrdList
|
|
| 124 | + |
|
| 119 | 125 | import Data.Data hiding (TyCon)
|
| 120 | 126 | import Data.Int
|
| 121 | 127 | import Data.List.NonEmpty (nonEmpty)
|
| ... | ... | @@ -1574,7 +1580,25 @@ data CoreRule |
| 1574 | 1580 | }
|
| 1575 | 1581 | -- See Note [Extra args in the target] in GHC.Core.Rules
|
| 1576 | 1582 | |
| 1577 | -type RuleFun = RuleOpts -> InScopeEnv -> Id -> [CoreExpr] -> Maybe CoreExpr
|
|
| 1583 | +type RuleFun = RuleOpts -> InScopeEnv
|
|
| 1584 | + -> Id -> [CoreExpr] -- Function applied to these arguments
|
|
| 1585 | + -> Maybe RuleMatch
|
|
| 1586 | + |
|
| 1587 | +data RuleMatch
|
|
| 1588 | + = RM { rm_rule :: CoreRule
|
|
| 1589 | + , rm_rhs :: CoreExpr -- Rhs of the rule
|
|
| 1590 | + , rm_args :: [CoreExpr] -- The args of the RHS
|
|
| 1591 | + , rm_floats :: FloatBinds -- Floated let-bindings
|
|
| 1592 | + -- See Note [Matching lets]
|
|
| 1593 | + }
|
|
| 1594 | + -- E.g. match r = RULE forall x,y. f (Just (y,x)) = g x y True
|
|
| 1595 | + -- target f (let v = ev in Just (ey, ex)) ez
|
|
| 1596 | + -- We get the RuleMatch
|
|
| 1597 | + -- RMM { rm_rule = r, rm_rhs = \xy. g x y True
|
|
| 1598 | + -- , rm_args = [ex, ey]
|
|
| 1599 | + -- , rm_floats = Let v=ev }
|
|
| 1600 | + -- The leftover `ez` is not returned; the caller is responsible for
|
|
| 1601 | + -- counting (ruleArity r) arguments
|
|
| 1578 | 1602 | |
| 1579 | 1603 | -- | The 'InScopeSet' in the 'InScopeEnv' is a /superset/ of variables that are
|
| 1580 | 1604 | -- currently in scope. See Note [The InScopeSet invariant].
|
| ... | ... | @@ -1622,6 +1646,37 @@ isLocalRule (Rule { ru_local = is_local }) = is_local |
| 1622 | 1646 | setRuleIdName :: Name -> CoreRule -> CoreRule
|
| 1623 | 1647 | setRuleIdName nm ru = ru { ru_fn = nm }
|
| 1624 | 1648 | |
| 1649 | +{-
|
|
| 1650 | +************************************************************************
|
|
| 1651 | +* *
|
|
| 1652 | + Floats
|
|
| 1653 | +* *
|
|
| 1654 | +************************************************************************
|
|
| 1655 | +-}
|
|
| 1656 | + |
|
| 1657 | +type FloatBinds = OrdList FloatBind
|
|
| 1658 | + |
|
| 1659 | +emptyFloatBinds :: FloatBinds
|
|
| 1660 | +emptyFloatBinds = nilOL
|
|
| 1661 | + |
|
| 1662 | +isEmptyFloatBinds :: FloatBinds -> Bool
|
|
| 1663 | +isEmptyFloatBinds = isNilOL
|
|
| 1664 | + |
|
| 1665 | +data FloatBind
|
|
| 1666 | + = FloatLet CoreBind
|
|
| 1667 | + | FloatCase CoreExpr CoreBndr AltCon [CoreBndr]
|
|
| 1668 | + -- case e of y { C ys -> ... }
|
|
| 1669 | + -- See Note [Floating single-alternative cases] in GHC.Core.Opt.SetLevels
|
|
| 1670 | + | FloatTick CoreTickish
|
|
| 1671 | + |
|
| 1672 | +floatsBinders :: FloatBinds -> [Var]
|
|
| 1673 | +floatsBinders fs = foldr ((++) . floatBinders) [] fs
|
|
| 1674 | + |
|
| 1675 | +floatBinders :: FloatBind -> [Var]
|
|
| 1676 | +floatBinders (FloatLet bnd) = bindersOf bnd
|
|
| 1677 | +floatBinders (FloatCase _ b _ bs) = b:bs
|
|
| 1678 | +floatBinders (FloatTick {}) = []
|
|
| 1679 | + |
|
| 1625 | 1680 | {-
|
| 1626 | 1681 | ************************************************************************
|
| 1627 | 1682 | * *
|
| ... | ... | @@ -18,11 +18,6 @@ module GHC.Core.Make ( |
| 18 | 18 | mkCharExpr, mkStringExpr, mkStringExprFS, mkStringExprFSWith,
|
| 19 | 19 | MkStringIds (..), getMkStringIds,
|
| 20 | 20 | |
| 21 | - -- * Floats
|
|
| 22 | - FloatBind(..), FloatBinds,
|
|
| 23 | - wrapFloat, wrapFloats, floatBindings,
|
|
| 24 | - emptyFloatBinds, isEmptyFloatBinds,
|
|
| 25 | - |
|
| 26 | 21 | -- * Constructing small tuples
|
| 27 | 22 | mkCoreVarTupTy, mkCoreTup, mkCoreUnboxedTuple, mkCoreUnboxedSum,
|
| 28 | 23 | mkCoreTupBoxity, unitExpr,
|
| ... | ... | @@ -43,6 +38,9 @@ module GHC.Core.Make ( |
| 43 | 38 | -- * Constructing Maybe expressions
|
| 44 | 39 | mkNothingExpr, mkJustExpr,
|
| 45 | 40 | |
| 41 | + -- * Floats
|
|
| 42 | + wrapFloat, wrapFloats,
|
|
| 43 | + |
|
| 46 | 44 | -- * Error Ids
|
| 47 | 45 | mkRuntimeErrorApp, mkImpossibleExpr, mkAbsentErrorApp, errorIds,
|
| 48 | 46 | rEC_CON_ERROR_ID,
|
| ... | ... | @@ -63,7 +61,6 @@ import GHC.Types.Basic( TypeOrConstraint(..) ) |
| 63 | 61 | import GHC.Types.Demand
|
| 64 | 62 | import GHC.Types.Name hiding ( varName )
|
| 65 | 63 | import GHC.Types.Literal
|
| 66 | -import GHC.Types.Tickish
|
|
| 67 | 64 | import GHC.Types.Unique.Supply
|
| 68 | 65 | |
| 69 | 66 | import GHC.Core
|
| ... | ... | @@ -740,54 +737,6 @@ mkSmallTupleCase vars body scrut_var scrut |
| 740 | 737 | = Case scrut scrut_var (exprType body)
|
| 741 | 738 | [Alt (DataAlt (tupleDataCon Boxed (length vars))) vars body]
|
| 742 | 739 | |
| 743 | -{-
|
|
| 744 | -************************************************************************
|
|
| 745 | -* *
|
|
| 746 | - Floats
|
|
| 747 | -* *
|
|
| 748 | -************************************************************************
|
|
| 749 | --}
|
|
| 750 | - |
|
| 751 | -type FloatBinds = OrdList FloatBind
|
|
| 752 | - |
|
| 753 | -emptyFloatBinds :: FloatBinds
|
|
| 754 | -emptyFloatBinds = nilOL
|
|
| 755 | - |
|
| 756 | -isEmptyFloatBinds :: FloatBinds -> Bool
|
|
| 757 | -isEmptyFloatBinds = isNilOL
|
|
| 758 | - |
|
| 759 | -data FloatBind
|
|
| 760 | - = FloatLet CoreBind
|
|
| 761 | - | FloatCase CoreExpr Id AltCon [Var]
|
|
| 762 | - -- case e of y { C ys -> ... }
|
|
| 763 | - -- See Note [Floating single-alternative cases] in GHC.Core.Opt.SetLevels
|
|
| 764 | - | FloatTick CoreTickish
|
|
| 765 | - |
|
| 766 | -instance Outputable FloatBind where
|
|
| 767 | - ppr (FloatTick t) = text "TICK" <+> ppr t
|
|
| 768 | - ppr (FloatLet b) = text "LET" <+> ppr b
|
|
| 769 | - ppr (FloatCase e b c bs) = hang (text "CASE" <+> ppr e <+> text "of" <+> ppr b)
|
|
| 770 | - 2 (ppr c <+> ppr bs)
|
|
| 771 | - |
|
| 772 | -wrapFloat :: FloatBind -> CoreExpr -> CoreExpr
|
|
| 773 | -wrapFloat (FloatTick t) body = mkTick t body
|
|
| 774 | -wrapFloat (FloatLet defns) body = Let defns body
|
|
| 775 | -wrapFloat (FloatCase e b con bs) body = mkSingleAltCase e b con bs body
|
|
| 776 | - |
|
| 777 | --- | Applies the floats from right to left. That is @wrapFloats [b1, b2, …, bn]
|
|
| 778 | --- u = let b1 in let b2 in … in let bn in u@
|
|
| 779 | -wrapFloats :: FloatBinds -> CoreExpr -> CoreExpr
|
|
| 780 | -wrapFloats floats expr = foldrOL wrapFloat expr floats
|
|
| 781 | - |
|
| 782 | -bindBindings :: CoreBind -> [Var]
|
|
| 783 | -bindBindings (NonRec b _) = [b]
|
|
| 784 | -bindBindings (Rec bnds) = map fst bnds
|
|
| 785 | - |
|
| 786 | -floatBindings :: FloatBind -> [Var]
|
|
| 787 | -floatBindings (FloatLet bnd) = bindBindings bnd
|
|
| 788 | -floatBindings (FloatCase _ b _ bs) = b:bs
|
|
| 789 | -floatBindings (FloatTick {}) = []
|
|
| 790 | - |
|
| 791 | 740 | {-
|
| 792 | 741 | ************************************************************************
|
| 793 | 742 | * *
|
| ... | ... | @@ -867,6 +816,25 @@ mkJustExpr :: Type -> CoreExpr -> CoreExpr |
| 867 | 816 | mkJustExpr ty val = mkConApp justDataCon [Type ty, val]
|
| 868 | 817 | |
| 869 | 818 | |
| 819 | +{-
|
|
| 820 | +************************************************************************
|
|
| 821 | +* *
|
|
| 822 | + Manipulating Floats
|
|
| 823 | +* *
|
|
| 824 | +************************************************************************
|
|
| 825 | +-}
|
|
| 826 | + |
|
| 827 | +wrapFloat :: FloatBind -> CoreExpr -> CoreExpr
|
|
| 828 | +wrapFloat (FloatTick t) body = mkTick t body
|
|
| 829 | +wrapFloat (FloatLet defns) body = Let defns body
|
|
| 830 | +wrapFloat (FloatCase e b con bs) body = mkSingleAltCase e b con bs body
|
|
| 831 | + |
|
| 832 | +-- | Applies the floats from right to left. That is @wrapFloats [b1, b2, …, bn]
|
|
| 833 | +-- u = let b1 in let b2 in … in let bn in u@
|
|
| 834 | +wrapFloats :: FloatBinds -> CoreExpr -> CoreExpr
|
|
| 835 | +wrapFloats floats expr = foldrOL wrapFloat expr floats
|
|
| 836 | + |
|
| 837 | + |
|
| 870 | 838 | {-
|
| 871 | 839 | ************************************************************************
|
| 872 | 840 | * *
|
| ... | ... | @@ -870,7 +870,7 @@ primOpRules nm = \case |
| 870 | 870 | |
| 871 | 871 | -- useful shorthands
|
| 872 | 872 | mkPrimOpRule :: Name -> Int -> [RuleM CoreExpr] -> Maybe CoreRule
|
| 873 | -mkPrimOpRule nm arity rules = Just $ mkBasicRule nm arity (msum rules)
|
|
| 873 | +mkPrimOpRule nm arity rules = Just $ mkBasicRule1 nm arity (msum rules)
|
|
| 874 | 874 | |
| 875 | 875 | mkRelOpRule :: Name -> (forall a . Ord a => a -> a -> Bool)
|
| 876 | 876 | -> [RuleM CoreExpr] -> Maybe CoreRule
|
| ... | ... | @@ -1679,16 +1679,35 @@ but that is only a historical accident. |
| 1679 | 1679 | ************************************************************************
|
| 1680 | 1680 | -}
|
| 1681 | 1681 | |
| 1682 | -mkBasicRule :: Name -> Int -> RuleM CoreExpr -> CoreRule
|
|
| 1682 | +mkBasicRule1 :: Name -> Int -> RuleM CoreExpr -> CoreRule
|
|
| 1683 | 1683 | -- Gives the Rule the same name as the primop itself
|
| 1684 | -mkBasicRule op_name n_args rm
|
|
| 1685 | - = BuiltinRule { ru_name = occNameFS (nameOccName op_name),
|
|
| 1686 | - ru_fn = op_name,
|
|
| 1687 | - ru_nargs = n_args,
|
|
| 1688 | - ru_try = runRuleM rm }
|
|
| 1689 | - |
|
| 1690 | -newtype RuleM r = RuleM
|
|
| 1691 | - { runRuleM :: RuleOpts -> InScopeEnv -> Id -> [CoreExpr] -> Maybe r }
|
|
| 1684 | +mkBasicRule1 op_name n_args rm
|
|
| 1685 | + = mkBasicRule (occNameFS (nameOccName op_name)) op_name n_args rm
|
|
| 1686 | + |
|
| 1687 | +mkBasicRule :: RuleName -> Name -> Int -> RuleM CoreExpr -> CoreRule
|
|
| 1688 | +-- The Builtin rules in this module all produce an expression
|
|
| 1689 | +-- with no args; hence rm_args = []. The `rm_rhs` is the complete
|
|
| 1690 | +-- result of the rule rewrite. This is OK because it's always
|
|
| 1691 | +-- small (I think).
|
|
| 1692 | +mkBasicRule rule_name op_name n_args rm
|
|
| 1693 | + = rule
|
|
| 1694 | + where
|
|
| 1695 | + rule = BuiltinRule { ru_name = rule_name
|
|
| 1696 | + , ru_fn = op_name
|
|
| 1697 | + , ru_nargs = n_args
|
|
| 1698 | + , ru_try = try }
|
|
| 1699 | + |
|
| 1700 | + try opts in_scope fn args
|
|
| 1701 | + = case runRuleM rm opts in_scope fn args of
|
|
| 1702 | + Nothing -> Nothing
|
|
| 1703 | + Just rhs -> Just (RM { rm_rule = rule
|
|
| 1704 | + , rm_rhs = rhs
|
|
| 1705 | + , rm_args = []
|
|
| 1706 | + , rm_floats = emptyFloatBinds })
|
|
| 1707 | + |
|
| 1708 | +type CFRuleFun r = RuleOpts -> InScopeEnv -> Id -> [CoreExpr] -> Maybe r
|
|
| 1709 | + |
|
| 1710 | +newtype RuleM r = RuleM { runRuleM :: CFRuleFun r }
|
|
| 1692 | 1711 | deriving (Functor)
|
| 1693 | 1712 | |
| 1694 | 1713 | instance Applicative RuleM where
|
| ... | ... | @@ -2132,28 +2151,16 @@ is fine. |
| 2132 | 2151 | builtinRules :: [CoreRule]
|
| 2133 | 2152 | -- Rules for non-primops that can't be expressed using a RULE pragma
|
| 2134 | 2153 | builtinRules
|
| 2135 | - = [BuiltinRule { ru_name = fsLit "CStringFoldrLit",
|
|
| 2136 | - ru_fn = unpackCStringFoldrName,
|
|
| 2137 | - ru_nargs = 4, ru_try = match_cstring_foldr_lit_C },
|
|
| 2138 | - BuiltinRule { ru_name = fsLit "CStringFoldrLitUtf8",
|
|
| 2139 | - ru_fn = unpackCStringFoldrUtf8Name,
|
|
| 2140 | - ru_nargs = 4, ru_try = match_cstring_foldr_lit_utf8 },
|
|
| 2141 | - BuiltinRule { ru_name = fsLit "CStringAppendLit",
|
|
| 2142 | - ru_fn = unpackCStringAppendName,
|
|
| 2143 | - ru_nargs = 2, ru_try = match_cstring_append_lit_C },
|
|
| 2144 | - BuiltinRule { ru_name = fsLit "CStringAppendLitUtf8",
|
|
| 2145 | - ru_fn = unpackCStringAppendUtf8Name,
|
|
| 2146 | - ru_nargs = 2, ru_try = match_cstring_append_lit_utf8 },
|
|
| 2147 | - BuiltinRule { ru_name = fsLit "EqString", ru_fn = eqStringName,
|
|
| 2148 | - ru_nargs = 2, ru_try = match_eq_string },
|
|
| 2149 | - BuiltinRule { ru_name = fsLit "CStringLength", ru_fn = cstringLengthName,
|
|
| 2150 | - ru_nargs = 1, ru_try = match_cstring_length },
|
|
| 2151 | - BuiltinRule { ru_name = fsLit "Inline", ru_fn = inlineIdName,
|
|
| 2152 | - ru_nargs = 2, ru_try = \_ _ _ -> match_inline },
|
|
| 2153 | - |
|
| 2154 | - mkBasicRule unsafeEqualityProofName 3 unsafeEqualityProofRule,
|
|
| 2155 | - |
|
| 2156 | - mkBasicRule divIntName 2 $ msum
|
|
| 2154 | + = [ mkBasicRule1 unpackCStringFoldrName 4 (RuleM match_cstring_foldr_lit_C)
|
|
| 2155 | + , mkBasicRule1 unpackCStringFoldrUtf8Name 4 (RuleM match_cstring_foldr_lit_utf8)
|
|
| 2156 | + , mkBasicRule1 unpackCStringAppendName 2 (RuleM match_cstring_append_lit_C)
|
|
| 2157 | + , mkBasicRule1 unpackCStringAppendUtf8Name 2 (RuleM match_cstring_append_lit_utf8)
|
|
| 2158 | + , mkBasicRule1 eqStringName 2 (RuleM match_eq_string)
|
|
| 2159 | + , mkBasicRule1 cstringLengthName 1 (RuleM match_cstring_length)
|
|
| 2160 | + , mkBasicRule1 inlineIdName 2 (RuleM match_inline)
|
|
| 2161 | + , mkBasicRule1 unsafeEqualityProofName 3 unsafeEqualityProofRule
|
|
| 2162 | + |
|
| 2163 | + , mkBasicRule1 divIntName 2 $ msum
|
|
| 2157 | 2164 | [ nonZeroLit 1 >> binaryLit (intOp2 div)
|
| 2158 | 2165 | , leftZero
|
| 2159 | 2166 | , do
|
| ... | ... | @@ -2161,9 +2168,9 @@ builtinRules |
| 2161 | 2168 | Just n <- return $ exactLog2 d
|
| 2162 | 2169 | platform <- getPlatform
|
| 2163 | 2170 | return $ Var (primOpId IntSraOp) `App` arg `App` mkIntVal platform n
|
| 2164 | - ],
|
|
| 2171 | + ]
|
|
| 2165 | 2172 | |
| 2166 | - mkBasicRule modIntName 2 $ msum
|
|
| 2173 | + , mkBasicRule1 modIntName 2 $ msum
|
|
| 2167 | 2174 | [ nonZeroLit 1 >> binaryLit (intOp2 mod)
|
| 2168 | 2175 | , leftZero
|
| 2169 | 2176 | , do
|
| ... | ... | @@ -2322,15 +2329,9 @@ builtinBignumRules = |
| 2322 | 2329 | encodeLitDouble LitDouble
|
| 2323 | 2330 | ]
|
| 2324 | 2331 | where
|
| 2325 | - mkRule str name nargs f = BuiltinRule
|
|
| 2326 | - { ru_name = fsLit str
|
|
| 2327 | - , ru_fn = name
|
|
| 2328 | - , ru_nargs = nargs
|
|
| 2329 | - , ru_try = runRuleM $ do
|
|
| 2330 | - env <- getRuleOpts
|
|
| 2331 | - guard (roBignumRules env)
|
|
| 2332 | - f
|
|
| 2333 | - }
|
|
| 2332 | + mkRule str name nargs f = mkBasicRule (fsLit str) name nargs rm
|
|
| 2333 | + where
|
|
| 2334 | + rm = do { env <- getRuleOpts; guard (roBignumRules env); f }
|
|
| 2334 | 2335 | |
| 2335 | 2336 | integer_to_lit str name convert = mkRule str name 1 $ do
|
| 2336 | 2337 | [a0] <- getArgs
|
| ... | ... | @@ -2506,15 +2507,15 @@ builtinBignumRules = |
| 2506 | 2507 | --
|
| 2507 | 2508 | |
| 2508 | 2509 | -- CString version
|
| 2509 | -match_cstring_append_lit_C :: RuleFun
|
|
| 2510 | +match_cstring_append_lit_C :: CFRuleFun CoreExpr
|
|
| 2510 | 2511 | match_cstring_append_lit_C = match_cstring_append_lit unpackCStringAppendIdKey unpackCStringIdKey
|
| 2511 | 2512 | |
| 2512 | 2513 | -- CStringUTF8 version
|
| 2513 | -match_cstring_append_lit_utf8 :: RuleFun
|
|
| 2514 | +match_cstring_append_lit_utf8 :: CFRuleFun CoreExpr
|
|
| 2514 | 2515 | match_cstring_append_lit_utf8 = match_cstring_append_lit unpackCStringAppendUtf8IdKey unpackCStringUtf8IdKey
|
| 2515 | 2516 | |
| 2516 | 2517 | {-# INLINE match_cstring_append_lit #-}
|
| 2517 | -match_cstring_append_lit :: Unique -> Unique -> RuleFun
|
|
| 2518 | +match_cstring_append_lit :: Unique -> Unique -> CFRuleFun CoreExpr
|
|
| 2518 | 2519 | match_cstring_append_lit append_key unpack_key _ env _ [lit1, e2]
|
| 2519 | 2520 | | Just (LitString s1) <- exprIsLiteral_maybe env lit1
|
| 2520 | 2521 | , (strTicks, Var unpk `App` lit2) <- stripStrTopTicks env e2
|
| ... | ... | @@ -2540,15 +2541,15 @@ match_cstring_append_lit _ _ _ _ _ _ = Nothing |
| 2540 | 2541 | -- See also Note [String literals in GHC] in CString.hs
|
| 2541 | 2542 | |
| 2542 | 2543 | -- CString version
|
| 2543 | -match_cstring_foldr_lit_C :: RuleFun
|
|
| 2544 | +match_cstring_foldr_lit_C :: CFRuleFun CoreExpr
|
|
| 2544 | 2545 | match_cstring_foldr_lit_C = match_cstring_foldr_lit unpackCStringFoldrIdKey
|
| 2545 | 2546 | |
| 2546 | 2547 | -- CStringUTF8 version
|
| 2547 | -match_cstring_foldr_lit_utf8 :: RuleFun
|
|
| 2548 | +match_cstring_foldr_lit_utf8 :: CFRuleFun CoreExpr
|
|
| 2548 | 2549 | match_cstring_foldr_lit_utf8 = match_cstring_foldr_lit unpackCStringFoldrUtf8IdKey
|
| 2549 | 2550 | |
| 2550 | 2551 | {-# INLINE match_cstring_foldr_lit #-}
|
| 2551 | -match_cstring_foldr_lit :: Unique -> RuleFun
|
|
| 2552 | +match_cstring_foldr_lit :: Unique -> CFRuleFun CoreExpr
|
|
| 2552 | 2553 | match_cstring_foldr_lit foldVariant _ env _
|
| 2553 | 2554 | [ Type ty1
|
| 2554 | 2555 | , lit1
|
| ... | ... | @@ -2595,7 +2596,7 @@ stripStrTopTicksT e = stripTicksTopT tickishFloatable e |
| 2595 | 2596 | -- eqString (unpackCString# (Lit s1)) (unpackCString# (Lit s2)) = s1==s2
|
| 2596 | 2597 | -- Also matches unpackCStringUtf8#
|
| 2597 | 2598 | |
| 2598 | -match_eq_string :: RuleFun
|
|
| 2599 | +match_eq_string :: CFRuleFun CoreExpr
|
|
| 2599 | 2600 | match_eq_string _ env _ [e1, e2]
|
| 2600 | 2601 | | (ticks1, Var unpk1 `App` lit1) <- stripStrTopTicks env e1
|
| 2601 | 2602 | , (ticks2, Var unpk2 `App` lit2) <- stripStrTopTicks env e2
|
| ... | ... | @@ -2628,7 +2629,7 @@ match_eq_string _ _ _ _ = Nothing |
| 2628 | 2629 | -- helpful when using OverloadedStrings to create a ByteString since the
|
| 2629 | 2630 | -- function computing the length of such ByteStrings can often be constant
|
| 2630 | 2631 | -- folded.
|
| 2631 | -match_cstring_length :: RuleFun
|
|
| 2632 | +match_cstring_length :: CFRuleFun CoreExpr
|
|
| 2632 | 2633 | match_cstring_length rule_env env _ [lit1]
|
| 2633 | 2634 | | Just (LitString str) <- exprIsLiteral_maybe env lit1
|
| 2634 | 2635 | -- If elemIndex returns Just, it has the index of the first embedded NUL
|
| ... | ... | @@ -2676,8 +2677,8 @@ The moving parts are simple: |
| 2676 | 2677 | Also, don't forget about 'inline's type argument!
|
| 2677 | 2678 | -}
|
| 2678 | 2679 | |
| 2679 | -match_inline :: [Expr CoreBndr] -> Maybe (Expr CoreBndr)
|
|
| 2680 | -match_inline (Type _ : e : _) = go e
|
|
| 2680 | +match_inline :: CFRuleFun CoreExpr
|
|
| 2681 | +match_inline _ _ _ (Type _ : e : _) = go e
|
|
| 2681 | 2682 | -- Maybe Monad ahead:
|
| 2682 | 2683 | where
|
| 2683 | 2684 | go (Var f) = -- Ignore the IdUnfoldingFun here!
|
| ... | ... | @@ -2689,7 +2690,7 @@ match_inline (Type _ : e : _) = go e |
| 2689 | 2690 | go (Tick t e) = do { app <- go e; pure (Tick t app) }
|
| 2690 | 2691 | go _ = Nothing
|
| 2691 | 2692 | |
| 2692 | -match_inline _ = Nothing
|
|
| 2693 | +match_inline _ _ _ _ = Nothing
|
|
| 2693 | 2694 | |
| 2694 | 2695 | --------------------------------------------------------
|
| 2695 | 2696 | -- Note [Constant folding through nested expressions]
|
| ... | ... | @@ -42,7 +42,7 @@ import GHC.Core.Opt.Arity ( ArityType, exprArity, arityTypeBotSigs_maybe |
| 42 | 42 | , typeArity, arityTypeArity, etaExpandAT )
|
| 43 | 43 | import GHC.Core.SimpleOpt ( exprIsConApp_maybe, joinPointBinding_maybe, joinPointBindings_maybe )
|
| 44 | 44 | import GHC.Core.FVs ( mkRuleInfo {- exprsFreeIds -} )
|
| 45 | -import GHC.Core.Rules ( RuleMatch(..), lookupRule, getRules )
|
|
| 45 | +import GHC.Core.Rules ( lookupRule, getRules )
|
|
| 46 | 46 | import GHC.Core.Multiplicity
|
| 47 | 47 | |
| 48 | 48 | import GHC.Hs.Extension
|
| ... | ... | @@ -2486,11 +2486,11 @@ simplOutId env fun cont |
| 2486 | 2486 | else return Nothing
|
| 2487 | 2487 | ; case mb_match of {
|
| 2488 | 2488 | Just (RM { rm_rule = rule, rm_rhs = rhs
|
| 2489 | - , rm_args = rhs_args, rm_binds = wrap })
|
|
| 2489 | + , rm_args = rhs_args, rm_floats = float_bs })
|
|
| 2490 | 2490 | -> simplExprF env rhs' $
|
| 2491 | 2491 | dropContArgs (ruleArity rule) cont
|
| 2492 | 2492 | where
|
| 2493 | - rhs' = GHC.Core.Make.wrapFloats wrap $
|
|
| 2493 | + rhs' = GHC.Core.Make.wrapFloats float_bs $
|
|
| 2494 | 2494 | mkApps rhs rhs_args
|
| 2495 | 2495 | ; Nothing ->
|
| 2496 | 2496 | |
| ... | ... | @@ -2765,15 +2765,15 @@ fireRuleAFTER :: SimplEnv -> RuleMatch |
| 2765 | 2765 | -> SimplM (SimplFloats, CoreExpr)
|
| 2766 | 2766 | fireRuleAFTER env rule_match arg_specs cont
|
| 2767 | 2767 | | RM { rm_rule = rule, rm_rhs = rhs, rm_args = rhs_args
|
| 2768 | - , rm_binds = wrap, rm_bndrs = bndrs } <- rule_match
|
|
| 2769 | - = do { let env' = env `addNewInScopeIds` bndrs
|
|
| 2768 | + , rm_floats = float_bs } <- rule_match
|
|
| 2769 | + = do { let env' = env `addNewInScopeIds` floatsBinders float_bs
|
|
| 2770 | 2770 | ; (floats, e') <- simplExprF env' rhs $
|
| 2771 | 2771 | pushOutArgs (exprType rhs) rhs_args $
|
| 2772 | 2772 | pushArgSpecs (drop (ruleArity rule) arg_specs) cont
|
| 2773 | 2773 | ; return $
|
| 2774 | - if isEmptyFloatBinds wrap -- Not very pretty
|
|
| 2774 | + if isEmptyFloatBinds float_bs -- Not very pretty
|
|
| 2775 | 2775 | then (floats, e')
|
| 2776 | - else (emptyFloats env', GHC.Core.Make.wrapFloats wrap $
|
|
| 2776 | + else (emptyFloats env', GHC.Core.Make.wrapFloats float_bs $
|
|
| 2777 | 2777 | wrapFloats floats e') }
|
| 2778 | 2778 | |
| 2779 | 2779 | |
| ... | ... | @@ -3895,10 +3895,10 @@ wrapDataConFloats env wfloats case_bndr cont thing_inside |
| 3895 | 3895 | -- scale_float scales case-floats by the multiplicity of the continuation hole
|
| 3896 | 3896 | -- (see Note [Scaling in case-of-case]).
|
| 3897 | 3897 | -- Let floats are _not_ scaled, because they are aliases anyway.
|
| 3898 | - scale_float (GHC.Core.Make.FloatCase scrut case_bndr con vars)
|
|
| 3899 | - = GHC.Core.Make.FloatCase scrut (scale_id case_bndr) con (map scale_id vars)
|
|
| 3900 | - scale_float flt@(GHC.Core.Make.FloatLet {}) = flt
|
|
| 3901 | - scale_float flt@(GHC.Core.Make.FloatTick {}) = flt
|
|
| 3898 | + scale_float (GHC.Core.FloatCase scrut case_bndr con vars)
|
|
| 3899 | + = GHC.Core.FloatCase scrut (scale_id case_bndr) con (map scale_id vars)
|
|
| 3900 | + scale_float flt@(GHC.Core.FloatLet {}) = flt
|
|
| 3901 | + scale_float flt@(GHC.Core.FloatTick {}) = flt
|
|
| 3902 | 3902 | |
| 3903 | 3903 | scale_id id = scaleVarBy holeScaling id
|
| 3904 | 3904 |
| ... | ... | @@ -2906,8 +2906,8 @@ betterPat is (CP { cp_qvars = vs1, cp_args = as1 }) |
| 2906 | 2906 | (CP { cp_qvars = vs2, cp_args = as2 })
|
| 2907 | 2907 | | equalLength as1 as2
|
| 2908 | 2908 | = case matchExprs ise vs1 as1 as2 of
|
| 2909 | - Just (ms,_,_) -> all exprIsTrivial ms
|
|
| 2910 | - Nothing -> False
|
|
| 2909 | + Just (ms,_) -> all exprIsTrivial ms
|
|
| 2910 | + Nothing -> False
|
|
| 2911 | 2911 | |
| 2912 | 2912 | | otherwise -- We must handle patterns of unequal length separately (#24282)
|
| 2913 | 2913 | = False -- For the pattern with more args, the last arg is "interesting"
|
| ... | ... | @@ -1823,8 +1823,8 @@ specLookupRule env fn args is_active rules |
| 1823 | 1823 | | otherwise
|
| 1824 | 1824 | = case lookupRule ropts in_scope_env is_active fn args rules of
|
| 1825 | 1825 | Just (RM { rm_rule = rule, rm_rhs = rule_rhs
|
| 1826 | - , rm_binds = wrap, rm_args = rule_args })
|
|
| 1827 | - -> Just (rule, wrapFloats wrap (mkApps rule_rhs rule_args))
|
|
| 1826 | + , rm_floats = float_bs, rm_args = rule_args })
|
|
| 1827 | + -> Just (rule, wrapFloats float_bs (mkApps rule_rhs rule_args))
|
|
| 1828 | 1828 | Nothing -> Nothing
|
| 1829 | 1829 | where
|
| 1830 | 1830 | dflags = se_dflags env
|
| ... | ... | @@ -80,6 +80,12 @@ instance OutputableBndr b => Outputable (Expr b) where |
| 80 | 80 | instance OutputableBndr b => Outputable (Alt b) where
|
| 81 | 81 | ppr expr = pprCoreAlt expr
|
| 82 | 82 | |
| 83 | +instance Outputable FloatBind where
|
|
| 84 | + ppr (FloatTick t) = text "TICK" <+> ppr t
|
|
| 85 | + ppr (FloatLet b) = text "LET" <+> ppr b
|
|
| 86 | + ppr (FloatCase e b c bs) = hang (text "CASE" <+> ppr e <+> text "of" <+> ppr b)
|
|
| 87 | + 2 (ppr c <+> ppr bs)
|
|
| 88 | + |
|
| 83 | 89 | {-
|
| 84 | 90 | ************************************************************************
|
| 85 | 91 | * *
|
| ... | ... | @@ -543,22 +543,6 @@ map. |
| 543 | 543 | ************************************************************************
|
| 544 | 544 | -}
|
| 545 | 545 | |
| 546 | -data RuleMatch
|
|
| 547 | - = RM { rm_rule :: CoreRule
|
|
| 548 | - , rm_rhs :: CoreExpr
|
|
| 549 | - , rm_args :: [CoreExpr]
|
|
| 550 | - , rm_binds :: FloatBinds -- Floated let-bindings
|
|
| 551 | - -- See Note [Matching lets]
|
|
| 552 | - , rm_bndrs :: [Var] -- Binders of rm_binds
|
|
| 553 | - }
|
|
| 554 | - -- E.g. match r = RULE forall x,y. f (Just (y,x)) = g x y True
|
|
| 555 | - -- target f (let v = ev in Just (ey, ex)) ez
|
|
| 556 | - -- We get the RuleMatch
|
|
| 557 | - -- RMM { rm_rule = r, rm_rhs = \xy. g x y True
|
|
| 558 | - -- , rm_args = [ex, ey]
|
|
| 559 | - -- , rm_binds = Let v=ev, rm_bndrs = [v] )
|
|
| 560 | - -- The leftover `ez` is not returned; the caller is responsible for
|
|
| 561 | - -- counting (ruleArity r) arguments
|
|
| 562 | 546 | |
| 563 | 547 | -- | The main rule matching function. Attempts to apply all (active)
|
| 564 | 548 | -- supplied rules to this instance of an application in a given
|
| ... | ... | @@ -592,7 +576,7 @@ lookupRule opts rule_env@(ISE in_scope _) is_active fn args rules |
| 592 | 576 | go ms [] = ms
|
| 593 | 577 | go ms (r:rs)
|
| 594 | 578 | | Just rm <- matchRule opts rule_env is_active fn args' rough_args r
|
| 595 | - = go (rm { rm_binds = toOL (map FloatTick ticks) `appOL` rm_binds rm } : ms) rs
|
|
| 579 | + = go (rm { rm_floats = toOL (map FloatTick ticks) `appOL` rm_floats rm } : ms) rs
|
|
| 596 | 580 | | otherwise
|
| 597 | 581 | = -- pprTrace "match failed" (ppr r $$ ppr args $$
|
| 598 | 582 | -- ppr [ (arg_id, maybeUnfoldingTemplate unf)
|
| ... | ... | @@ -741,14 +725,9 @@ matchRule :: HasDebugCallStack |
| 741 | 725 | -- of the actual arguments.
|
| 742 | 726 | |
| 743 | 727 | matchRule opts rule_env _is_active fn args _rough_args
|
| 744 | - rule@(BuiltinRule { ru_try = match_fn })
|
|
| 728 | + (BuiltinRule { ru_try = match_fn })
|
|
| 745 | 729 | = do { guard (roBuiltinRules opts)
|
| 746 | - ; rhs <- match_fn opts rule_env fn args
|
|
| 747 | - ; return (RM { rm_rule = rule
|
|
| 748 | - , rm_rhs = rhs
|
|
| 749 | - , rm_args = []
|
|
| 750 | - , rm_binds = emptyFloatBinds
|
|
| 751 | - , rm_bndrs = [] }) }
|
|
| 730 | + ; match_fn opts rule_env fn args }
|
|
| 752 | 731 | |
| 753 | 732 | matchRule _opts rule_env is_active _fn target_es rough_args
|
| 754 | 733 | rule@(Rule { ru_act = act, ru_rough = tpl_tops
|
| ... | ... | @@ -758,25 +737,22 @@ matchRule _opts rule_env is_active _fn target_es rough_args |
| 758 | 737 | | ruleCantMatch tpl_tops rough_args
|
| 759 | 738 | = Nothing
|
| 760 | 739 | | otherwise
|
| 761 | - = do { (matched_es, bind_wrapper, wrap_bndrs)
|
|
| 762 | - <- matchExprs rule_env tpl_vars tpl_args target_es
|
|
| 763 | - |
|
| 740 | + = do { (matched_es, float_bs) <- matchExprs rule_env tpl_vars tpl_args target_es
|
|
| 764 | 741 | ; return (RM { rm_rule = rule
|
| 765 | 742 | , rm_rhs = mkLams tpl_vars rhs
|
| 766 | 743 | , rm_args = matched_es
|
| 767 | - , rm_binds = bind_wrapper
|
|
| 768 | - , rm_bndrs = wrap_bndrs }) }
|
|
| 744 | + , rm_floats = float_bs }) }
|
|
| 769 | 745 | |
| 770 | 746 | matchExprs :: HasDebugCallStack
|
| 771 | 747 | => InScopeEnv -> [Var] -> [CoreExpr] -> [CoreExpr]
|
| 772 | - -> Maybe ( [CoreExpr] -- 1-1 with the incoming [Var]
|
|
| 773 | - , FloatBinds, [Var]) -- Floated binds
|
|
| 748 | + -> Maybe ( [CoreExpr] -- 1-1 with the incoming [Var]
|
|
| 749 | + , FloatBinds ) -- Floated binds
|
|
| 774 | 750 | matchExprs (ISE in_scope id_unf) tmpl_vars tmpl_es target_es
|
| 775 | 751 | = do { rule_subst <- match_exprs init_menv emptyRuleSubst tmpl_es target_es
|
| 776 | 752 | ; let (_, matched_es) = mapAccumL (lookup_tmpl rule_subst)
|
| 777 | 753 | (mkEmptySubst in_scope) $
|
| 778 | 754 | tmpl_vars `zip` tmpl_vars1
|
| 779 | - ; return (matched_es, rs_binds rule_subst, rs_bndrs rule_subst) }
|
|
| 755 | + ; return (matched_es, rs_binds rule_subst) }
|
|
| 780 | 756 | where
|
| 781 | 757 | (init_rn_env, tmpl_vars1) = mapAccumL rnBndrL (mkRnEnv2 in_scope) tmpl_vars
|
| 782 | 758 | -- See Note [Cloning the template binders]
|
| ... | ... | @@ -32,9 +32,9 @@ import GHC.Builtin.Types.Prim |
| 32 | 32 | import GHC.Core.Utils
|
| 33 | 33 | import GHC.Core.Opt.Arity
|
| 34 | 34 | import GHC.Core.Lint ( EndPassConfig(..), endPassIO )
|
| 35 | -import GHC.Core
|
|
| 35 | +import GHC.Core hiding( FloatBind(..) )
|
|
| 36 | 36 | import GHC.Core.Subst
|
| 37 | -import GHC.Core.Make hiding( FloatBind(..) ) -- We use our own FloatBind here
|
|
| 37 | +import GHC.Core.Make
|
|
| 38 | 38 | import GHC.Core.Type
|
| 39 | 39 | import GHC.Core.Coercion
|
| 40 | 40 | import GHC.Core.TyCon
|
| ... | ... | @@ -2108,6 +2108,8 @@ instance Outputable FloatInfo where |
| 2108 | 2108 | |
| 2109 | 2109 | -- See Note [Floating in CorePrep]
|
| 2110 | 2110 | -- and Note [BindInfo and FloatInfo]
|
| 2111 | +-- This data type is very like GHC.Core.FloatBind,
|
|
| 2112 | +-- but with extra info on the let-bindings
|
|
| 2111 | 2113 | data FloatingBind
|
| 2112 | 2114 | = Float !CoreBind !BindInfo !FloatInfo -- Never a join-point binding
|
| 2113 | 2115 | | UnsafeEqualityCase !CoreExpr !CoreBndr !AltCon ![CoreBndr]
|
| ... | ... | @@ -65,7 +65,7 @@ import GHC.Core.Map.Expr |
| 65 | 65 | import GHC.Core.Predicate (typeDeterminesValue, mkNomEqPred)
|
| 66 | 66 | import GHC.Core.SimpleOpt (simpleOptExpr, exprIsConApp_maybe)
|
| 67 | 67 | import GHC.Core.Utils (exprType)
|
| 68 | -import GHC.Core.Make (mkListExpr, mkCharExpr, mkImpossibleExpr, isEmptyFloatBinds)
|
|
| 68 | +import GHC.Core.Make (mkListExpr, mkCharExpr, mkImpossibleExpr)
|
|
| 69 | 69 | |
| 70 | 70 | import GHC.Data.FastString
|
| 71 | 71 | import GHC.Types.SrcLoc
|
| ... | ... | @@ -513,11 +513,7 @@ mkDictSelId name clas |
| 513 | 513 | |
| 514 | 514 | -- This is the built-in rule that goes
|
| 515 | 515 | -- op (dfT d1 d2) ---> opT d1 d2
|
| 516 | - rule = BuiltinRule { ru_name = fsLit "Class op " `appendFS`
|
|
| 517 | - occNameFS (getOccName name)
|
|
| 518 | - , ru_fn = name
|
|
| 519 | - , ru_nargs = n_ty_args + 1
|
|
| 520 | - , ru_try = dictSelRule val_index n_ty_args }
|
|
| 516 | + rule = dictSelRule name n_ty_args val_index
|
|
| 521 | 517 | |
| 522 | 518 | -- The strictness signature is of the form U(AAAVAAAA) -> T
|
| 523 | 519 | -- where the V depends on which item we are selecting
|
| ... | ... | @@ -561,20 +557,35 @@ mkDictSelRhs clas val_index |
| 561 | 557 | -- varToCoreExpr needed for equality superclass selectors
|
| 562 | 558 | -- sel a b d = case x of { MkC _ (g:a~b) _ -> CO g }
|
| 563 | 559 | |
| 564 | -dictSelRule :: Int -> Arity -> RuleFun
|
|
| 560 | +dictSelRule :: Name -> Arity -> Int -> CoreRule
|
|
| 565 | 561 | -- Tries to persuade the argument to look like a constructor
|
| 566 | 562 | -- application, using exprIsConApp_maybe, and then selects
|
| 567 | 563 | -- from it
|
| 568 | 564 | -- sel_i t1..tk (D t1..tk op1 ... opm) = opi
|
| 569 | 565 | --
|
| 570 | 566 | -- See Note [ClassOp/DFun selection] in GHC.Tc.TyCl.Instance
|
| 571 | -dictSelRule val_index n_ty_args _ in_scope_env _ args
|
|
| 572 | - | (dict_arg : _) <- drop n_ty_args args
|
|
| 573 | - , Just (_, floats, _, _, con_args)
|
|
| 574 | - <- exprIsConApp_maybe in_scope_env dict_arg
|
|
| 575 | - = Just (wrapFloats floats $ getNth con_args val_index)
|
|
| 576 | - | otherwise
|
|
| 577 | - = Nothing
|
|
| 567 | +dictSelRule name val_index n_ty_args
|
|
| 568 | + = rule
|
|
| 569 | + where
|
|
| 570 | + rule = BuiltinRule { ru_name = fsLit "Class op " `appendFS`
|
|
| 571 | + occNameFS (getOccName name)
|
|
| 572 | + , ru_fn = name
|
|
| 573 | + , ru_nargs = n_ty_args + 1
|
|
| 574 | + , ru_try = try }
|
|
| 575 | + |
|
| 576 | + |
|
| 577 | + try :: RuleFun
|
|
| 578 | + try _opts in_scope_env _fn args
|
|
| 579 | + | (dict_arg : _) <- drop n_ty_args args
|
|
| 580 | + , Just (_, floats, _, _, con_args) <- exprIsConApp_maybe in_scope_env dict_arg
|
|
| 581 | + , let meth_e = getNth con_args val_index
|
|
| 582 | + meth_id = mkTemplateLocal 1 (exprType meth_e)
|
|
| 583 | + = Just (RM { rm_floats = floats
|
|
| 584 | + , rm_rhs = Lam meth_id (Var meth_id)
|
|
| 585 | + , rm_args = [meth_e]
|
|
| 586 | + , rm_rule = rule })
|
|
| 587 | + | otherwise
|
|
| 588 | + = Nothing
|
|
| 578 | 589 | |
| 579 | 590 | {-
|
| 580 | 591 | ************************************************************************
|