%************************************************************************
\begin{code}
--- CoreRules is used only in an idSpecialisation (move to IdInfo?)
data SpecInfo
- = SpecInfo [CoreRule] VarSet -- Locally-defined free vars of RHSs
+ = SpecInfo
+ [CoreRule]
+ VarSet -- Locally-defined free vars of *both* LHS and RHS of rules
+ -- Note [Rule dependency info]
emptySpecInfo :: SpecInfo
emptySpecInfo = SpecInfo [] emptyVarSet
seqSpecInfo (SpecInfo rules fvs) = seqRules rules `seq` seqVarSet fvs
\end{code}
+Note [Rule dependency info]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+THe VarSet in a SpecInfo is used for dependency analysis in the
+occurrence analyser. We must track free vars in *both* lhs and rhs. Why both?
+Consider
+ x = y
+ RULE f x = 4
+Then if we substitute y for x, we'd better do so in the
+ rule's LHS too, so we'd better ensure the dependency is respsected
+
+
%************************************************************************
%* *
exprFreeNames, exprsFreeNames,
idRuleVars, idFreeVars, varTypeTyVars,
- ruleRhsFreeVars, rulesRhsFreeVars,
+ ruleRhsFreeVars, rulesFreeVars,
ruleLhsFreeNames, ruleLhsFreeIds,
CoreExprWithFVs, -- = AnnExpr Id VarSet
ruleRhsFreeVars :: CoreRule -> VarSet
ruleRhsFreeVars (BuiltinRule {}) = noFVs
ruleRhsFreeVars (Rule { ru_fn = fn, ru_bndrs = bndrs, ru_rhs = rhs })
- = delFromUFM fvs fn
- -- Hack alert!
- -- Don't include the Id in its own rhs free-var set.
- -- Otherwise the occurrence analyser makes bindings recursive
- -- that shoudn't be. E.g.
- -- RULE: f (f x y) z ==> f x (f y z)
+ = delFromUFM fvs fn -- Note [Rule free var hack]
where
fvs = addBndrs bndrs (expr_fvs rhs) isLocalVar emptyVarSet
-rulesRhsFreeVars :: [CoreRule] -> VarSet
-rulesRhsFreeVars rules
- = foldr (unionVarSet . ruleRhsFreeVars) emptyVarSet rules
+ruleFreeVars :: CoreRule -> VarSet -- All free variables, both left and right
+ruleFreeVars (Rule { ru_fn = fn, ru_bndrs = bndrs, ru_rhs = rhs, ru_args = args })
+ = delFromUFM fvs fn -- Note [Rule free var hack]
+ where
+ fvs = addBndrs bndrs (exprs_fvs (rhs:args)) isLocalVar emptyVarSet
+
+rulesFreeVars :: [CoreRule] -> VarSet
+rulesFreeVars rules = foldr (unionVarSet . ruleFreeVars) emptyVarSet rules
ruleLhsFreeIds :: CoreRule -> VarSet
-- This finds all locally-defined free Ids on the LHS of the rule
= addBndrs bndrs (exprs_fvs args) isLocalId emptyVarSet
\end{code}
+Note [Rule free var hack]
+~~~~~~~~~~~~~~~~~~~~~~~~~
+Don't include the Id in its own rhs free-var set.
+Otherwise the occurrence analyser makes bindings recursive
+that shoudn't be. E.g.
+ RULE: f (f x y) z ==> f x (f y z)
+
+Also since rule_fn is a Name, not a Var, we have to use the grungy delUFM.
%************************************************************************
%* *
import CoreSyn -- All of it
import OccurAnal ( occurAnalyseExpr )
-import CoreFVs ( exprFreeVars, exprsFreeVars, bindFreeVars, rulesRhsFreeVars )
+import CoreFVs ( exprFreeVars, exprsFreeVars, bindFreeVars, rulesFreeVars )
import CoreUnfold ( isCheapUnfolding, unfoldingTemplate )
import CoreUtils ( tcEqExprX, exprType )
import PprCore ( pprRules )
\begin{code}
mkSpecInfo :: [CoreRule] -> SpecInfo
-mkSpecInfo rules = SpecInfo rules (rulesRhsFreeVars rules)
+mkSpecInfo rules = SpecInfo rules (rulesFreeVars rules)
extendSpecInfo :: SpecInfo -> [CoreRule] -> SpecInfo
extendSpecInfo (SpecInfo rs1 fvs1) rs2
- = SpecInfo (rs2 ++ rs1) (rulesRhsFreeVars rs2 `unionVarSet` fvs1)
+ = SpecInfo (rs2 ++ rs1) (rulesFreeVars rs2 `unionVarSet` fvs1)
addSpecInfo :: SpecInfo -> SpecInfo -> SpecInfo
addSpecInfo (SpecInfo rs1 fvs1) (SpecInfo rs2 fvs2)