2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %************************************************************************
6 \section[BinderInfo]{Information attached to binders by SubstAnal}
8 %************************************************************************
14 addBinderInfo, orBinderInfo,
16 deadOccurrence, funOccurrence, noBinderInfo,
18 markMany, markInsideLam, markInsideSCC,
20 setBinderInfoArityToZero,
25 #include "HsVersions.h"
27 import IdInfo ( OccInfo(..), InsideLam, insideLam, notInsideLam )
31 The @BinderInfo@ describes how a variable is used in a given scope.
33 NOTE: With SCCs we have to be careful what we unfold! We don't want to
34 change the attribution of execution costs. If we decide to unfold
35 within an SCC we can tag the definition as @DontKeepBinder@.
36 Definitions tagged as @KeepBinder@ are discarded when we enter the
41 = DeadCode -- Dead code; discard the binding.
43 | ManyOcc -- Everything else besides DeadCode and OneOccs
45 !Int -- number of arguments on stack when called; this is a minimum guarantee
48 | SingleOcc -- Just one occurrence (or one each in
49 -- mutually-exclusive case alts).
55 !Int -- Number of mutually-exclusive case alternatives
58 -- Note that we only worry about the case-alt counts
59 -- if the SingleOcc is substitutable -- that's the only
60 -- time we *use* the info; we could be more clever for
61 -- other cases if we really had to. (WDP/PS)
63 !Int -- number of arguments on stack when called; minimum guarantee
65 -- In general, we are feel free to substitute unless
66 -- (a) is in an argument position (ArgOcc)
67 -- (b) is inside a lambda [or type lambda?] (DupDanger)
68 -- (c) is inside an SCC expression (InsideSCC)
69 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
70 -- (because the RHS will be inlined regardless of its size)
74 = InsideSCC -- Inside an SCC; so be careful when substituting.
75 | NotInsideSCC -- It's ok.
77 noBinderInfo = ManyOcc 0 -- A non-committal value
81 binderInfoToOccInfo :: BinderInfo -> OccInfo
82 binderInfoToOccInfo DeadCode = IAmDead
83 binderInfoToOccInfo (SingleOcc in_lam NotInsideSCC n_alts _) = OneOcc in_lam (n_alts==1)
84 binderInfoToOccInfo other = NoOccInfo
92 deadOccurrence :: BinderInfo
93 deadOccurrence = DeadCode
95 funOccurrence :: Int -> BinderInfo
96 funOccurrence = SingleOcc notInsideLam NotInsideSCC 1
98 markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
100 markMany (SingleOcc _ _ _ ar) = ManyOcc ar
101 markMany (ManyOcc ar) = ManyOcc ar
102 markMany DeadCode = panic "markMany"
104 markInsideLam (SingleOcc _ in_scc n_alts ar) = SingleOcc insideLam in_scc n_alts ar
105 markInsideLam other = other
107 markInsideSCC (SingleOcc dup_danger _ n_alts ar) = SingleOcc dup_danger InsideSCC n_alts ar
108 markInsideSCC other = other
110 addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
112 addBinderInfo DeadCode info2 = info2
113 addBinderInfo info1 DeadCode = info1
114 addBinderInfo info1 info2
115 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
117 -- (orBinderInfo orig new) is used
118 -- when combining occurrence info from branches of a case
120 orBinderInfo DeadCode info2 = info2
121 orBinderInfo info1 DeadCode = info1
122 orBinderInfo (SingleOcc dup1 scc1 n_alts1 ar_1)
123 (SingleOcc dup2 scc2 n_alts2 ar_2)
125 scc = or_sccs scc1 scc2
126 dup = or_dups dup1 dup2
127 alts = n_alts1 + n_alts2
130 SingleOcc dup scc alts ar
132 orBinderInfo info1 info2
133 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
135 or_dups in_lam1 in_lam2 = in_lam1 || in_lam2
137 or_sccs InsideSCC _ = InsideSCC
138 or_sccs _ InsideSCC = InsideSCC
139 or_sccs _ _ = NotInsideSCC
141 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
142 setBinderInfoArityToZero DeadCode = DeadCode
143 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
144 setBinderInfoArityToZero (SingleOcc dd sc i _) = SingleOcc dd sc i 0
148 getBinderInfoArity (DeadCode) = 0
149 getBinderInfoArity (ManyOcc i) = i
150 getBinderInfoArity (SingleOcc _ _ _ i) = i
154 instance Outputable BinderInfo where
155 ppr DeadCode = ptext SLIT("Dead")
156 ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
157 ppr (SingleOcc dup_danger in_scc n_alts ar)
158 = hcat [ ptext SLIT("One-"), ppr dup_danger,
159 char '-', pp_scc in_scc, char '-', int n_alts,
162 pp_scc InsideSCC = ptext SLIT("*SCC*")
163 pp_scc NotInsideSCC = ptext SLIT("noscc")