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 markLazy, markMany, markInsideLam, markInsideSCC,
20 setBinderInfoArityToZero,
25 #include "HsVersions.h"
27 import IdInfo ( InlinePragInfo(..), OccInfo(..) )
29 import GlaExts ( Int(..), (+#) )
33 The @BinderInfo@ describes how a variable is used in a given scope.
35 NOTE: With SCCs we have to be careful what we unfold! We don't want to
36 change the attribution of execution costs. If we decide to unfold
37 within an SCC we can tag the definition as @DontKeepBinder@.
38 Definitions tagged as @KeepBinder@ are discarded when we enter the
43 = DeadCode -- Dead code; discard the binding.
45 | ManyOcc -- Everything else besides DeadCode and OneOccs
47 !Int -- number of arguments on stack when called; this is a minimum guarantee
50 | OneOcc -- Just one occurrence (or one each in
51 -- mutually-exclusive case alts).
57 !Int -- Number of mutually-exclusive case alternatives
60 -- Note that we only worry about the case-alt counts
61 -- if the OneOcc is substitutable -- that's the only
62 -- time we *use* the info; we could be more clever for
63 -- other cases if we really had to. (WDP/PS)
65 !Int -- number of arguments on stack when called; minimum guarantee
67 -- In general, we are feel free to substitute unless
68 -- (a) is in an argument position (ArgOcc)
69 -- (b) is inside a lambda [or type lambda?] (DupDanger)
70 -- (c) is inside an SCC expression (InsideSCC)
71 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
72 -- (because the RHS will be inlined regardless of its size)
76 = InsideSCC -- Inside an SCC; so be careful when substituting.
77 | NotInsideSCC -- It's ok.
79 noBinderInfo = ManyOcc 0 -- A non-committal value
83 occInfoToInlinePrag :: BinderInfo -> InlinePragInfo
84 occInfoToInlinePrag DeadCode = IAmDead
85 occInfoToInlinePrag (OneOcc occ_info NotInsideSCC n_alts _) = ICanSafelyBeINLINEd occ_info (n_alts==1)
86 occInfoToInlinePrag other = NoInlinePragInfo
94 deadOccurrence :: BinderInfo
95 deadOccurrence = DeadCode
97 funOccurrence :: Int -> BinderInfo
98 funOccurrence = OneOcc StrictOcc NotInsideSCC 1
100 markLazy, markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
102 markMany (OneOcc _ _ _ ar) = ManyOcc ar
103 markMany (ManyOcc ar) = ManyOcc ar
104 markMany DeadCode = panic "markMany"
106 markInsideLam (OneOcc _ in_scc n_alts ar) = OneOcc InsideLam in_scc n_alts ar
107 markInsideLam other = other
109 markInsideSCC (OneOcc dup_danger _ n_alts ar) = OneOcc dup_danger InsideSCC n_alts ar
110 markInsideSCC other = other
112 markLazy (OneOcc StrictOcc scc n_alts ar) = OneOcc LazyOcc scc n_alts ar
113 markLazy other = other
115 addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
117 addBinderInfo DeadCode info2 = info2
118 addBinderInfo info1 DeadCode = info1
119 addBinderInfo info1 info2
120 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
122 -- (orBinderInfo orig new) is used
123 -- when combining occurrence info from branches of a case
125 orBinderInfo DeadCode info2 = info2
126 orBinderInfo info1 DeadCode = info1
127 orBinderInfo (OneOcc dup1 scc1 n_alts1 ar_1)
128 (OneOcc dup2 scc2 n_alts2 ar_2)
130 scc = or_sccs scc1 scc2
131 dup = or_dups dup1 dup2
132 alts = n_alts1 + n_alts2
135 OneOcc dup scc alts ar
137 orBinderInfo info1 info2
138 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
140 or_dups InsideLam _ = InsideLam
141 or_dups _ InsideLam = InsideLam
142 or_dups StrictOcc StrictOcc = StrictOcc
143 or_dups _ _ = LazyOcc
145 or_sccs InsideSCC _ = InsideSCC
146 or_sccs _ InsideSCC = InsideSCC
147 or_sccs _ _ = NotInsideSCC
149 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
150 setBinderInfoArityToZero DeadCode = DeadCode
151 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
152 setBinderInfoArityToZero (OneOcc dd sc i _) = OneOcc dd sc i 0
156 getBinderInfoArity (DeadCode) = 0
157 getBinderInfoArity (ManyOcc i) = i
158 getBinderInfoArity (OneOcc _ _ _ i) = i
162 instance Outputable BinderInfo where
163 ppr DeadCode = ptext SLIT("Dead")
164 ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
165 ppr (OneOcc dup_danger in_scc n_alts ar)
166 = hcat [ ptext SLIT("One-"), ppr dup_danger,
167 char '-', pp_scc in_scc, char '-', int n_alts,
170 pp_scc InsideSCC = ptext SLIT("*SCC*")
171 pp_scc NotInsideSCC = ptext SLIT("noscc")