summaryrefslogtreecommitdiff
path: root/compiler/iface
diff options
context:
space:
mode:
authorsimonpj@microsoft.com <unknown>2009-03-18 10:59:11 +0000
committersimonpj@microsoft.com <unknown>2009-03-18 10:59:11 +0000
commit4bc25e8c30559b7a6a87b39afcc79340ae778788 (patch)
tree3748224610d91cc835c08e55967d08808637c4ba /compiler/iface
parentbd78c94a3b41f8d2097efc0415fa26e0cd1140ef (diff)
downloadhaskell-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.hs18
-rw-r--r--compiler/iface/IfaceSyn.lhs4
-rw-r--r--compiler/iface/MkIface.lhs12
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