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 ( InlinePragInfo(..), OccInfo(..) )
28 import GlaExts ( Int(..), (+#) )
32 The @BinderInfo@ describes how a variable is used in a given scope.
34 NOTE: With SCCs we have to be careful what we unfold! We don't want to
35 change the attribution of execution costs. If we decide to unfold
36 within an SCC we can tag the definition as @DontKeepBinder@.
37 Definitions tagged as @KeepBinder@ are discarded when we enter the
42 = DeadCode -- Dead code; discard the binding.
44 | ManyOcc -- Everything else besides DeadCode and OneOccs
46 !Int -- number of arguments on stack when called; this is a minimum guarantee
49 | OneOcc -- Just one occurrence (or one each in
50 -- mutually-exclusive case alts).
56 !Int -- Number of mutually-exclusive case alternatives
59 -- Note that we only worry about the case-alt counts
60 -- if the OneOcc is substitutable -- that's the only
61 -- time we *use* the info; we could be more clever for
62 -- other cases if we really had to. (WDP/PS)
64 !Int -- number of arguments on stack when called; minimum guarantee
66 -- In general, we are feel free to substitute unless
67 -- (a) is in an argument position (ArgOcc)
68 -- (b) is inside a lambda [or type lambda?] (DupDanger)
69 -- (c) is inside an SCC expression (InsideSCC)
70 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
71 -- (because the RHS will be inlined regardless of its size)
75 = InsideSCC -- Inside an SCC; so be careful when substituting.
76 | NotInsideSCC -- It's ok.
78 noBinderInfo = ManyOcc 0 -- A non-committal value
82 occInfoToInlinePrag :: BinderInfo -> InlinePragInfo
83 occInfoToInlinePrag DeadCode = IAmDead
84 occInfoToInlinePrag (OneOcc occ_info NotInsideSCC n_alts _) = ICanSafelyBeINLINEd occ_info (n_alts==1)
85 occInfoToInlinePrag other = NoInlinePragInfo
93 deadOccurrence :: BinderInfo
94 deadOccurrence = DeadCode
96 funOccurrence :: Int -> BinderInfo
97 funOccurrence = OneOcc NotInsideLam NotInsideSCC 1
99 markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
101 markMany (OneOcc _ _ _ ar) = ManyOcc ar
102 markMany (ManyOcc ar) = ManyOcc ar
103 markMany DeadCode = panic "markMany"
105 markInsideLam (OneOcc _ in_scc n_alts ar) = OneOcc InsideLam in_scc n_alts ar
106 markInsideLam other = other
108 markInsideSCC (OneOcc dup_danger _ n_alts ar) = OneOcc dup_danger InsideSCC n_alts ar
109 markInsideSCC other = other
111 addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
113 addBinderInfo DeadCode info2 = info2
114 addBinderInfo info1 DeadCode = info1
115 addBinderInfo info1 info2
116 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
118 -- (orBinderInfo orig new) is used
119 -- when combining occurrence info from branches of a case
121 orBinderInfo DeadCode info2 = info2
122 orBinderInfo info1 DeadCode = info1
123 orBinderInfo (OneOcc dup1 scc1 n_alts1 ar_1)
124 (OneOcc dup2 scc2 n_alts2 ar_2)
126 scc = or_sccs scc1 scc2
127 dup = or_dups dup1 dup2
128 alts = n_alts1 + n_alts2
131 OneOcc dup scc alts ar
133 orBinderInfo info1 info2
134 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
136 or_dups InsideLam _ = InsideLam
137 or_dups _ InsideLam = InsideLam
138 or_dups _ _ = NotInsideLam
140 or_sccs InsideSCC _ = InsideSCC
141 or_sccs _ InsideSCC = InsideSCC
142 or_sccs _ _ = NotInsideSCC
144 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
145 setBinderInfoArityToZero DeadCode = DeadCode
146 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
147 setBinderInfoArityToZero (OneOcc dd sc i _) = OneOcc dd sc i 0
151 getBinderInfoArity (DeadCode) = 0
152 getBinderInfoArity (ManyOcc i) = i
153 getBinderInfoArity (OneOcc _ _ _ i) = i
157 instance Outputable BinderInfo where
158 ppr DeadCode = ptext SLIT("Dead")
159 ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
160 ppr (OneOcc dup_danger in_scc n_alts ar)
161 = hcat [ ptext SLIT("One-"), ppr dup_danger,
162 char '-', pp_scc in_scc, char '-', int n_alts,
165 pp_scc InsideSCC = ptext SLIT("*SCC*")
166 pp_scc NotInsideSCC = ptext SLIT("noscc")