869bc1a6652a1d5376372367e756793bff0c3e78
[ghc-hetmet.git] / ghc / compiler / simplCore / BinderInfo.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[BinderInfo]{Information attached to binders by SubstAnal}
7 %*                                                                      *
8 %************************************************************************
9
10 \begin{code}
11 #include "HsVersions.h"
12
13 module BinderInfo (
14         BinderInfo(..),
15         FunOrArg, DuplicationDanger, InsideSCC,  -- NB: all abstract (yay!)
16
17         addBinderInfo, orBinderInfo, andBinderInfo,
18
19         argOccurrence, funOccurrence, dangerousArgOcc, noBinderInfo,
20         markMany, markDangerousToDup, markInsideSCC,
21         getBinderInfoArity,
22         setBinderInfoArityToZero,
23
24         isFun, isDupDanger -- for Simon Marlow deforestation
25     ) where
26
27 IMP_Ubiq(){-uitous-}
28
29 import Pretty
30 import Util             ( panic )
31 #if __GLASGOW_HASKELL__ >= 202
32 import Outputable 
33 #endif
34
35 \end{code}
36
37 The @BinderInfo@ describes how a variable is used in a given scope.
38
39 NOTE: With SCCs we have to be careful what we unfold! We don't want to
40 change the attribution of execution costs. If we decide to unfold
41 within an SCC we can tag the definition as @DontKeepBinder@.
42 Definitions tagged as @KeepBinder@ are discarded when we enter the
43 scope of an SCC.
44
45 \begin{code}
46 data BinderInfo
47   = DeadCode    -- Dead code; discard the binding.
48
49   | ManyOcc     -- Everything else besides DeadCode and OneOccs
50
51         Int     -- number of arguments on stack when called; this is a minimum guarantee
52
53
54   | OneOcc      -- Just one occurrence (or one each in
55                 -- mutually-exclusive case alts).
56
57       FunOrArg  -- How it occurs
58
59       DuplicationDanger
60
61       InsideSCC
62
63       Int       -- Number of mutually-exclusive case alternatives
64                 -- in which it occurs
65
66                 -- Note that we only worry about the case-alt counts
67                 -- if the OneOcc is substitutable -- that's the only
68                 -- time we *use* the info; we could be more clever for
69                 -- other cases if we really had to. (WDP/PS)
70
71       Int       -- number of arguments on stack when called; minimum guarantee
72
73 -- In general, we are feel free to substitute unless
74 -- (a) is in an argument position (ArgOcc)
75 -- (b) is inside a lambda [or type lambda?] (DupDanger)
76 -- (c) is inside an SCC expression (InsideSCC)
77 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
78 --      (because the RHS will be inlined regardless of its size)
79 --      [again, DupDanger]
80
81 data FunOrArg
82   = FunOcc      -- An occurrence in a function position
83   | ArgOcc      -- Other arg occurrence
84
85     -- When combining branches of a case, only report FunOcc if
86     -- both branches are FunOccs
87
88 data DuplicationDanger
89   = DupDanger   -- Inside a non-linear lambda (that is, a lambda which
90                 -- is sure to be instantiated only once), or inside
91                 -- the rhs of an INLINE-pragma'd thing.  Either way,
92                 -- substituting a redex for this occurrence is
93                 -- dangerous because it might duplicate work.
94
95   | NoDupDanger -- It's ok; substitution won't duplicate work.
96
97 data InsideSCC
98   = InsideSCC       -- Inside an SCC; so be careful when substituting.
99   | NotInsideSCC    -- It's ok.
100
101 noBinderInfo = ManyOcc 0        -- A non-committal value
102 \end{code}
103
104
105
106 \begin{code}
107 isFun :: FunOrArg -> Bool
108 isFun FunOcc = True
109 isFun _ = False
110
111 isDupDanger :: DuplicationDanger -> Bool
112 isDupDanger DupDanger = True
113 isDupDanger _ = False
114 \end{code}
115
116 @inlineUnconditionally@ decides whether a let-bound thing can
117 definitely be inlined.
118
119 \begin{code}
120 {-      NOT USED
121
122 inlineUnconditionally :: Bool -> BinderInfo -> Bool
123
124 --inlineUnconditionally ok_to_dup DeadCode = True
125 inlineUnconditionally ok_to_dup (OneOcc FunOcc NoDupDanger NotInsideSCC n_alt_occs _)
126   = n_alt_occs <= 1 || ok_to_dup
127             -- We [i.e., Patrick] don't mind the code explosion,
128             -- though.  We could have a flag to limit the
129             -- damage, e.g., limit to M alternatives.
130
131 inlineUnconditionally _ _ = False
132 -}
133 \end{code}
134
135
136 Construction
137 ~~~~~~~~~~~~~
138 \begin{code}
139 argOccurrence, funOccurrence :: Int -> BinderInfo
140
141 funOccurrence = OneOcc FunOcc NoDupDanger NotInsideSCC 1
142 argOccurrence = OneOcc ArgOcc NoDupDanger NotInsideSCC 1
143
144 markMany, markDangerousToDup, markInsideSCC :: BinderInfo -> BinderInfo
145
146 markMany (OneOcc _ _ _ _ ar) = ManyOcc ar
147 markMany (ManyOcc ar)        = ManyOcc ar
148 markMany DeadCode            = panic "markMany"
149
150 markDangerousToDup (OneOcc posn _ in_scc n_alts ar)
151   = OneOcc posn DupDanger in_scc n_alts ar
152 markDangerousToDup other = other
153
154 dangerousArgOcc = OneOcc ArgOcc DupDanger NotInsideSCC 1 0
155
156 markInsideSCC (OneOcc posn dup_danger _ n_alts ar)
157   = OneOcc posn dup_danger InsideSCC n_alts ar
158 markInsideSCC other = other
159
160 addBinderInfo, orBinderInfo
161         :: BinderInfo -> BinderInfo -> BinderInfo
162
163 addBinderInfo DeadCode info2 = info2
164 addBinderInfo info1 DeadCode = info1
165 addBinderInfo info1 info2
166  = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
167      (I# i#) -> ManyOcc (I# i#)
168       -- ManyOcc min (getBinderInfoArity info1) (getBinderInfoArity info2))
169
170 -- (orBinderInfo orig new) is used when combining occurrence 
171 -- info from branches of a case
172
173 orBinderInfo DeadCode info2 = info2
174 orBinderInfo info1 DeadCode = info1
175 orBinderInfo (OneOcc posn1 dup1 scc1 n_alts1 ar_1)
176              (OneOcc posn2 dup2 scc2 n_alts2 ar_2)
177   = let
178       -- Seriously maligned in order to make it stricter,
179       -- let's hope it is worth it..
180      posn = combine_posns posn1 posn2
181      scc  = combine_sccs  scc1  scc2
182      dup  = combine_dups  dup1  dup2
183      alts = n_alts1 + n_alts2
184      ar   = min ar_1 ar_2
185
186       -- No CSE, please!
187      cont1 = case scc  of { InsideSCC -> cont2; _ -> cont2 }
188      cont2 = case dup  of { DupDanger -> cont3; _ -> cont3 }
189      cont3 = case alts of { (I# 0#)   -> cont4; _ -> cont4 }
190      cont4 = case ar   of { (I# 0#)   -> cont5; _ -> cont5 }
191      cont5 = OneOcc posn dup scc alts ar
192     in
193     case posn of { FunOcc -> cont1; _ -> cont1 }
194 orBinderInfo info1 info2
195  = case (min (getBinderInfoArity info1) (getBinderInfoArity info2)) of
196      (I# i#) -> ManyOcc (I# i#)
197
198 -- (andBinderInfo orig new) is used in two situations:
199 -- First, when a variable whose occurrence info
200 --   is currently "orig" is bound to a variable whose occurrence info is "new"
201 --      eg  (\new -> e) orig
202 --   What we want to do is to *worsen* orig's info to take account of new's
203 --
204 -- second, when completing a let-binding
205 --      let new = ...orig...
206 -- we compute the way orig occurs in (...orig...), and then use orBinderInfo
207 -- to worsen this info by the way new occurs in the let body; then we use
208 -- that to worsen orig's currently recorded occurrence info.
209
210 andBinderInfo DeadCode info2 = DeadCode
211 andBinderInfo info1 DeadCode = DeadCode
212 andBinderInfo (OneOcc posn1 dup1 scc1 (I# n_alts1#) (I# ar_1#))
213               (OneOcc posn2 dup2 scc2 (I# n_alts2#) ar_2)
214   = let
215       -- Perversly maligned in order to make it stricter.
216      posn = combine_posns posn1 posn2
217      scc  = combine_sccs  scc1  scc2
218      dup  = combine_dups  dup1  dup2
219      alts = I# (n_alts1# +# n_alts2#)
220
221       -- No CSE, please!
222      cont1 = case scc  of { InsideSCC -> cont2; _ -> cont2 }
223      cont2 = case dup  of { DupDanger -> cont3; _ -> cont3 }
224      cont3 = case alts of { (I# 0#) -> cont4;   _ -> cont4 }
225      cont4 = OneOcc posn dup scc alts (I# ar_1#)
226     in
227     case posn of {FunOcc -> cont1; _ -> cont1}
228
229 andBinderInfo info1 info2 = 
230  case getBinderInfoArity info1 of
231    (I# i#) -> ManyOcc (I# i#)
232                --ManyOcc (getBinderInfoArity info1)
233
234
235 combine_posns FunOcc FunOcc = FunOcc -- see comment at FunOrArg defn
236 combine_posns _          _  = ArgOcc
237
238 combine_dups DupDanger _ = DupDanger    -- Too paranoid?? ToDo
239 combine_dups _ DupDanger = DupDanger
240 combine_dups _ _             = NoDupDanger
241
242 combine_sccs InsideSCC _ = InsideSCC    -- Too paranoid?? ToDo
243 combine_sccs _ InsideSCC = InsideSCC
244 combine_sccs _ _             = NotInsideSCC
245
246 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
247 setBinderInfoArityToZero DeadCode    = DeadCode
248 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
249 setBinderInfoArityToZero (OneOcc fa dd sc i _) = OneOcc fa dd sc i 0
250 \end{code}
251
252 \begin{code}
253 getBinderInfoArity (DeadCode) = 0
254 getBinderInfoArity (ManyOcc i) = i
255 getBinderInfoArity (OneOcc _ _ _ _ i) = i
256 \end{code}
257
258 \begin{code}
259 instance Outputable BinderInfo where
260   ppr sty DeadCode     = ptext SLIT("Dead")
261   ppr sty (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
262   ppr sty (OneOcc posn dup_danger in_scc n_alts ar)
263     = hcat [ ptext SLIT("One-"), pp_posn posn, char '-', pp_danger dup_danger,
264                   char '-', pp_scc in_scc,  char '-', int n_alts,
265                   char '-', int ar ]
266     where
267       pp_posn FunOcc = ptext SLIT("fun")
268       pp_posn ArgOcc = ptext SLIT("arg")
269
270       pp_danger DupDanger   = ptext SLIT("*dup*")
271       pp_danger NoDupDanger = ptext SLIT("nodup")
272
273       pp_scc InsideSCC    = ptext SLIT("*SCC*")
274       pp_scc NotInsideSCC = ptext SLIT("noscc")
275 \end{code}
276