2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 %************************************************************************
6 \section[BinderInfo]{Information attached to binders by SubstAnal}
8 %************************************************************************
12 #include "HsVersions.h"
16 FunOrArg, DuplicationDanger, InsideSCC, -- NB: all abstract (yay!)
18 inlineUnconditionally, oneTextualOcc, oneSafeOcc,
20 combineBinderInfo, combineAltsBinderInfo,
22 argOccurrence, funOccurrence,
23 markMany, markDangerousToDup, markInsideSCC,
25 setBinderInfoArityToZero,
27 isFun, isDupDanger -- for Simon Marlow deforestation
30 IMPORT_Trace -- ToDo: rm (debugging)
35 import Util -- for pragmas only
38 The @BinderInfo@ describes how a variable is used in a given scope.
40 NOTE: With SCCs we have to be careful what we unfold! We don't want to
41 change the attribution of execution costs. If we decide to unfold
42 within an SCC we can tag the definition as @DontKeepBinder@.
43 Definitions tagged as @KeepBinder@ are discarded when we enter the
48 = DeadCode -- Dead code; discard the binding.
50 | ManyOcc -- Everything else besides DeadCode and OneOccs
52 Int -- number of arguments on stack when called
55 | OneOcc -- Just one occurrence (or one each in
56 -- mutually-exclusive case alts).
58 FunOrArg -- How it occurs
64 Int -- Number of mutually-exclusive case alternatives
67 -- Note that we only worry about the case-alt counts
68 -- if the OneOcc is substitutable -- that's the only
69 -- time we *use* the info; we could be more clever for
70 -- other cases if we really had to. (WDP/PS)
72 Int -- number of arguments on stack when called
74 -- In general, we are feel free to substitute unless
75 -- (a) is in an argument position (ArgOcc)
76 -- (b) is inside a lambda [or type lambda?] (DupDanger)
77 -- (c) is inside an SCC expression (InsideSCC)
78 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
79 -- (because the RHS will be inlined regardless of its size)
83 = FunOcc -- An occurrence in a function position
84 | ArgOcc -- Other arg occurrence
86 -- When combining branches of a case, only report FunOcc if
87 -- both branches are FunOccs
89 data DuplicationDanger
90 = DupDanger -- Inside a non-linear lambda (that is, a lambda which
91 -- is sure to be instantiated only once), or inside
92 -- the rhs of an INLINE-pragma'd thing. Either way,
93 -- substituting a redex for this occurrence is
94 -- dangerous because it might duplicate work.
96 | NoDupDanger -- It's ok; substitution won't duplicate work.
99 = InsideSCC -- Inside an SCC; so be careful when substituting.
100 | NotInsideSCC -- It's ok.
107 @oneTextualOcc@ checks for one occurrence, in any position.
108 The occurrence may be inside a lambda, that's all right.
111 oneTextualOcc :: Bool -> BinderInfo -> Bool
113 oneTextualOcc ok_to_dup (OneOcc _ _ _ n_alts _) = n_alts <= 1 || ok_to_dup
114 oneTextualOcc _ other = False
117 @safeSingleOcc@ detects single occurences of values that are safe to
118 inline, {\em including} ones in an argument position.
121 oneSafeOcc :: Bool -> BinderInfo -> Bool
122 oneSafeOcc ok_to_dup (OneOcc _ NoDupDanger NotInsideSCC n_alts _)
123 = n_alts <= 1 || ok_to_dup
124 oneSafeOcc _ other = False
127 @inlineUnconditionally@ decides whether a let-bound thing can
128 definitely be inlined.
131 inlineUnconditionally :: Bool -> BinderInfo -> Bool
133 --inlineUnconditionally ok_to_dup DeadCode = True
134 inlineUnconditionally ok_to_dup (OneOcc FunOcc NoDupDanger NotInsideSCC n_alt_occs _)
135 = n_alt_occs <= 1 || ok_to_dup
136 -- We [i.e., Patrick] don't mind the code explosion,
137 -- though. We could have a flag to limit the
138 -- damage, e.g., limit to M alternatives.
140 inlineUnconditionally _ _ = False
144 isFun :: FunOrArg -> Bool
148 isDupDanger :: DuplicationDanger -> Bool
149 isDupDanger DupDanger = True
150 isDupDanger _ = False
157 argOccurrence, funOccurrence :: Int -> BinderInfo
159 funOccurrence = OneOcc FunOcc NoDupDanger NotInsideSCC 1
160 argOccurrence = OneOcc ArgOcc NoDupDanger NotInsideSCC 1
162 markMany, markDangerousToDup, markInsideSCC :: BinderInfo -> BinderInfo
164 markMany (OneOcc _ _ _ _ ar) = ManyOcc ar
165 markMany (ManyOcc ar) = ManyOcc ar
166 markMany DeadCode = panic "markMany"
168 markDangerousToDup (OneOcc posn _ in_scc n_alts ar)
169 = OneOcc posn DupDanger in_scc n_alts ar
170 markDangerousToDup other = other
172 markInsideSCC (OneOcc posn dup_danger _ n_alts ar)
173 = OneOcc posn dup_danger InsideSCC n_alts ar
174 markInsideSCC other = other
176 combineBinderInfo, combineAltsBinderInfo
177 :: BinderInfo -> BinderInfo -> BinderInfo
179 combineBinderInfo DeadCode info2 = info2
180 combineBinderInfo info1 DeadCode = info1
181 combineBinderInfo info1 info2
182 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
184 combineAltsBinderInfo DeadCode info2 = info2
185 combineAltsBinderInfo info1 DeadCode = info1
186 combineAltsBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
187 (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
188 = OneOcc (combine_posns posn1 posn2)
189 (combine_dups dup1 dup2)
190 (combine_sccs scc1 scc2)
194 combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
195 combine_posns _ _ = ArgOcc
197 combine_dups DupDanger _ = DupDanger -- Too paranoid?? ToDo
198 combine_dups _ DupDanger = DupDanger
199 combine_dups _ _ = NoDupDanger
201 combine_sccs InsideSCC _ = InsideSCC -- Too paranoid?? ToDo
202 combine_sccs _ InsideSCC = InsideSCC
203 combine_sccs _ _ = NotInsideSCC
205 combineAltsBinderInfo info1 info2
206 = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
208 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
209 setBinderInfoArityToZero DeadCode = DeadCode
210 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
211 setBinderInfoArityToZero (OneOcc fa dd sc i _) = OneOcc fa dd sc i 0
215 getBinderInfoArity (DeadCode) = 0
216 getBinderInfoArity (ManyOcc i) = i
217 getBinderInfoArity (OneOcc _ _ _ _ i) = i
221 instance Outputable BinderInfo where
222 ppr sty DeadCode = ppStr "Dead"
223 ppr sty (ManyOcc ar) = ppBesides [ ppStr "Many-", ppInt ar ]
224 ppr sty (OneOcc posn dup_danger in_scc n_alts ar)
225 = ppBesides [ ppStr "One-", pp_posn posn, ppChar '-', pp_danger dup_danger,
226 ppChar '-', pp_scc in_scc, ppChar '-', ppInt n_alts,
227 ppChar '-', ppInt ar ]
229 pp_posn FunOcc = ppStr "fun"
230 pp_posn ArgOcc = ppStr "arg"
232 pp_danger DupDanger = ppStr "*dup*"
233 pp_danger NoDupDanger = ppStr "nodup"
235 pp_scc InsideSCC = ppStr "*SCC*"
236 pp_scc NotInsideSCC = ppStr "noscc"