diff options
author | simonpj@microsoft.com <unknown> | 2009-03-18 10:59:11 +0000 |
---|---|---|
committer | simonpj@microsoft.com <unknown> | 2009-03-18 10:59:11 +0000 |
commit | 4bc25e8c30559b7a6a87b39afcc79340ae778788 (patch) | |
tree | 3748224610d91cc835c08e55967d08808637c4ba /compiler/iface | |
parent | bd78c94a3b41f8d2097efc0415fa26e0cd1140ef (diff) | |
download | haskell-4bc25e8c30559b7a6a87b39afcc79340ae778788.tar.gz |
Add the notion of "constructor-like" Ids for rule-matching
This patch adds an optional CONLIKE modifier to INLINE/NOINLINE pragmas,
{-# NOINLINE CONLIKE [1] f #-}
The effect is to allow applications of 'f' to be expanded in a potential
rule match. Example
{-# RULE "r/f" forall v. r (f v) = f (v+1) #-}
Consider the term
let x = f v in ..x...x...(r x)...
Normally the (r x) would not match the rule, because GHC would be scared
about duplicating the redex (f v). However the CONLIKE modifier says to
treat 'f' like a constructor in this situation, and "look through" the
unfolding for x. So (r x) fires, yielding (f (v+1)).
The main changes are:
- Syntax
- The inlinePragInfo field of an IdInfo has a RuleMatchInfo
component, which records whether or not the Id is CONLIKE.
Of course, this needs to be serialised in interface files too.
- The occurrence analyser (OccAnal) and simplifier (Simplify) treat
CONLIKE thing like constructors, by ANF-ing them
- New function coreUtils.exprIsExpandable is like exprIsCheap, but
additionally spots applications of CONLIKE functions
- A CoreUnfolding has a field that caches exprIsExpandable
- The rule matcher consults this field. See
Note [Expanding variables] in Rules.lhs.
On the way I fixed a lurking variable bug in the way variables are
expanded. See Note [Do not expand locally-bound variables] in
Rule.lhs. I also did a bit of reformatting and refactoring in
Rules.lhs, so the module has more lines changed than are really
different.
Diffstat (limited to 'compiler/iface')
-rw-r--r-- | compiler/iface/BinIface.hs | 18 | ||||
-rw-r--r-- | compiler/iface/IfaceSyn.lhs | 4 | ||||
-rw-r--r-- | compiler/iface/MkIface.lhs | 12 |
3 files changed, 27 insertions, 7 deletions
diff --git a/compiler/iface/BinIface.hs b/compiler/iface/BinIface.hs index 7a274011b7..1a4a65a290 100644 --- a/compiler/iface/BinIface.hs +++ b/compiler/iface/BinIface.hs @@ -578,6 +578,24 @@ instance Binary Activation where _ -> do ab <- get bh return (ActiveAfter ab) +instance Binary RuleMatchInfo where + put_ bh FunLike = putByte bh 0 + put_ bh ConLike = putByte bh 1 + get bh = do + h <- getByte bh + if h == 1 then return ConLike + else return FunLike + +instance Binary InlinePragma where + put_ bh (InlinePragma activation match_info) = do + put_ bh activation + put_ bh match_info + + get bh = do + act <- get bh + info <- get bh + return (InlinePragma act info) + instance Binary StrictnessMark where put_ bh MarkedStrict = putByte bh 0 put_ bh MarkedUnboxed = putByte bh 1 diff --git a/compiler/iface/IfaceSyn.lhs b/compiler/iface/IfaceSyn.lhs index b679cf68c1..51e5f8a231 100644 --- a/compiler/iface/IfaceSyn.lhs +++ b/compiler/iface/IfaceSyn.lhs @@ -203,7 +203,7 @@ data IfaceIdInfo data IfaceInfoItem = HsArity Arity | HsStrictness StrictSig - | HsInline Activation + | HsInline InlinePragma | HsUnfold IfaceExpr | HsNoCafRefs | HsWorker Name Arity -- Worker, if any see IdInfo.WorkerInfo @@ -660,7 +660,7 @@ instance Outputable IfaceIdInfo where instance Outputable IfaceInfoItem where ppr (HsUnfold unf) = ptext (sLit "Unfolding:") <+> parens (pprIfaceExpr noParens unf) - ppr (HsInline act) = ptext (sLit "Inline:") <+> ppr act + ppr (HsInline prag) = ptext (sLit "Inline:") <+> ppr prag ppr (HsArity arity) = ptext (sLit "Arity:") <+> int arity ppr (HsStrictness str) = ptext (sLit "Strictness:") <+> pprIfaceStrictSig str ppr HsNoCafRefs = ptext (sLit "HasNoCafRefs") diff --git a/compiler/iface/MkIface.lhs b/compiler/iface/MkIface.lhs index 22c1756e00..8cfc08f329 100644 --- a/compiler/iface/MkIface.lhs +++ b/compiler/iface/MkIface.lhs @@ -1440,8 +1440,8 @@ toIfaceLetBndr id = IfLetBndr (occNameFS (getOccName id)) -- See Note [IdInfo on nested let-bindings] in IfaceSyn id_info = idInfo id inline_prag = inlinePragInfo id_info - prag_info | isAlwaysActive inline_prag = NoInfo - | otherwise = HasInfo [HsInline inline_prag] + prag_info | isDefaultInlinePragma inline_prag = NoInfo + | otherwise = HasInfo [HsInline inline_prag] -------------------------- toIfaceIdDetails :: IdDetails -> IfaceIdDetails @@ -1495,11 +1495,13 @@ toIfaceIdInfo id_info ------------ Inline prag -------------- inline_prag = inlinePragInfo id_info - inline_hsinfo | isAlwaysActive inline_prag = Nothing - | no_unfolding && not has_worker = Nothing + inline_hsinfo | isDefaultInlinePragma inline_prag = Nothing + | no_unfolding && not has_worker + && isFunLike (inlinePragmaRuleMatchInfo inline_prag) + = Nothing -- If the iface file give no unfolding info, we -- don't need to say when inlining is OK! - | otherwise = Just (HsInline inline_prag) + | otherwise = Just (HsInline inline_prag) -------------------------- coreRuleToIfaceRule :: Module -> CoreRule -> IfaceRule |