[project @ 1998-12-18 17:40:31 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / BinderInfo.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[BinderInfo]{Information attached to binders by SubstAnal}
7 %*                                                                      *
8 %************************************************************************
9
10 \begin{code}
11 module BinderInfo (
12         BinderInfo(..),
13
14         addBinderInfo, orBinderInfo,
15
16         deadOccurrence, funOccurrence, noBinderInfo,
17
18         markLazy, markMany, markInsideLam, markInsideSCC,
19         getBinderInfoArity,
20         setBinderInfoArityToZero,
21
22         occInfoToInlinePrag
23     ) where
24
25 #include "HsVersions.h"
26
27 import IdInfo           ( InlinePragInfo(..), OccInfo(..) )
28 import GlaExts          ( Int(..), (+#) )
29 import Outputable
30 \end{code}
31
32 The @BinderInfo@ describes how a variable is used in a given scope.
33
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
38 scope of an SCC.
39
40 \begin{code}
41 data BinderInfo
42   = DeadCode    -- Dead code; discard the binding.
43
44   | ManyOcc     -- Everything else besides DeadCode and OneOccs
45
46         !Int    -- number of arguments on stack when called; this is a minimum guarantee
47
48
49   | OneOcc      -- Just one occurrence (or one each in
50                 -- mutually-exclusive case alts).
51
52       !OccInfo
53
54       !InsideSCC
55
56       !Int      -- Number of mutually-exclusive case alternatives
57                 -- in which it occurs
58
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)
63
64       !Int      -- number of arguments on stack when called; minimum guarantee
65
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)
72 --      [again, DupDanger]
73
74 data InsideSCC
75   = InsideSCC       -- Inside an SCC; so be careful when substituting.
76   | NotInsideSCC    -- It's ok.
77
78 noBinderInfo = ManyOcc 0        -- A non-committal value
79 \end{code} 
80
81 \begin{code}
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
86 \end{code}
87
88
89
90 Construction
91 ~~~~~~~~~~~~~
92 \begin{code}
93 deadOccurrence :: BinderInfo
94 deadOccurrence = DeadCode
95
96 funOccurrence :: Int -> BinderInfo
97 funOccurrence = OneOcc StrictOcc NotInsideSCC 1
98
99 markLazy, markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
100
101 markMany (OneOcc _ _ _ ar) = ManyOcc ar
102 markMany (ManyOcc ar)      = ManyOcc ar
103 markMany DeadCode          = panic "markMany"
104
105 markInsideLam (OneOcc _ in_scc n_alts ar) = OneOcc InsideLam in_scc n_alts ar
106 markInsideLam other                       = other
107
108 markInsideSCC (OneOcc dup_danger _ n_alts ar) = OneOcc dup_danger InsideSCC n_alts ar
109 markInsideSCC other                           = other
110
111 markLazy (OneOcc StrictOcc scc n_alts ar) = OneOcc LazyOcc scc n_alts ar
112 markLazy other                            = other
113
114 addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
115
116 addBinderInfo DeadCode info2 = info2
117 addBinderInfo info1 DeadCode = info1
118 addBinderInfo info1 info2
119  = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
120
121 -- (orBinderInfo orig new) is used
122 -- when combining occurrence info from branches of a case
123
124 orBinderInfo DeadCode info2 = info2
125 orBinderInfo info1 DeadCode = info1
126 orBinderInfo (OneOcc dup1 scc1 n_alts1 ar_1)
127              (OneOcc dup2 scc2 n_alts2 ar_2)
128   = let
129      scc  = or_sccs  scc1  scc2
130      dup  = or_dups  dup1  dup2
131      alts = n_alts1 + n_alts2
132      ar   = min ar_1 ar_2
133    in
134    OneOcc dup scc alts ar
135
136 orBinderInfo info1 info2
137  = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
138
139 or_dups InsideLam _         = InsideLam
140 or_dups _         InsideLam = InsideLam
141 or_dups StrictOcc StrictOcc = StrictOcc
142 or_dups _         _         = LazyOcc
143
144 or_sccs InsideSCC _ = InsideSCC
145 or_sccs _ InsideSCC = InsideSCC
146 or_sccs _ _         = NotInsideSCC
147
148 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
149 setBinderInfoArityToZero DeadCode    = DeadCode
150 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
151 setBinderInfoArityToZero (OneOcc dd sc i _) = OneOcc dd sc i 0
152 \end{code}
153
154 \begin{code}
155 getBinderInfoArity (DeadCode) = 0
156 getBinderInfoArity (ManyOcc i) = i
157 getBinderInfoArity (OneOcc _ _ _ i) = i
158 \end{code}
159
160 \begin{code}
161 instance Outputable BinderInfo where
162   ppr DeadCode     = ptext SLIT("Dead")
163   ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
164   ppr (OneOcc dup_danger in_scc n_alts ar)
165     = hcat [ ptext SLIT("One-"), ppr dup_danger,
166                   char '-', pp_scc in_scc,  char '-', int n_alts,
167                   char '-', int ar ]
168     where
169       pp_scc InsideSCC    = ptext SLIT("*SCC*")
170       pp_scc NotInsideSCC = ptext SLIT("noscc")
171 \end{code}
172