[project @ 2001-01-12 11:36:24 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         markMany, markInsideLam, markInsideSCC,
19         getBinderInfoArity,
20         setBinderInfoArityToZero,
21
22         binderInfoToOccInfo
23     ) where
24
25 #include "HsVersions.h"
26
27 import IdInfo           ( OccInfo(..), InsideLam, insideLam, notInsideLam )
28 import Outputable
29 \end{code}
30
31 The @BinderInfo@ describes how a variable is used in a given scope.
32
33 NOTE: With SCCs we have to be careful what we unfold! We don't want to
34 change the attribution of execution costs. If we decide to unfold
35 within an SCC we can tag the definition as @DontKeepBinder@.
36 Definitions tagged as @KeepBinder@ are discarded when we enter the
37 scope of an SCC.
38
39 \begin{code}
40 data BinderInfo
41   = DeadCode    -- Dead code; discard the binding.
42
43   | ManyOcc     -- Everything else besides DeadCode and OneOccs
44
45         !Int    -- number of arguments on stack when called; this is a minimum guarantee
46
47
48   | SingleOcc   -- Just one occurrence (or one each in
49                 -- mutually-exclusive case alts).
50
51       !InsideLam
52
53       !InsideSCC
54
55       !Int      -- Number of mutually-exclusive case alternatives
56                 -- in which it occurs
57
58                 -- Note that we only worry about the case-alt counts
59                 -- if the SingleOcc is substitutable -- that's the only
60                 -- time we *use* the info; we could be more clever for
61                 -- other cases if we really had to. (WDP/PS)
62
63       !Int      -- number of arguments on stack when called; minimum guarantee
64
65 -- In general, we are feel free to substitute unless
66 -- (a) is in an argument position (ArgOcc)
67 -- (b) is inside a lambda [or type lambda?] (DupDanger)
68 -- (c) is inside an SCC expression (InsideSCC)
69 -- (d) is in the RHS of a binding for a variable with an INLINE pragma
70 --      (because the RHS will be inlined regardless of its size)
71 --      [again, DupDanger]
72
73 data InsideSCC
74   = InsideSCC       -- Inside an SCC; so be careful when substituting.
75   | NotInsideSCC    -- It's ok.
76
77 noBinderInfo = ManyOcc 0        -- A non-committal value
78 \end{code} 
79
80 \begin{code}
81 binderInfoToOccInfo :: BinderInfo -> OccInfo
82 binderInfoToOccInfo DeadCode                                 = IAmDead
83 binderInfoToOccInfo (SingleOcc in_lam NotInsideSCC n_alts _) = OneOcc in_lam (n_alts==1)
84 binderInfoToOccInfo other                                    = NoOccInfo
85 \end{code}
86
87
88
89 Construction
90 ~~~~~~~~~~~~~
91 \begin{code}
92 deadOccurrence :: BinderInfo
93 deadOccurrence = DeadCode
94
95 funOccurrence :: Int -> BinderInfo
96 funOccurrence = SingleOcc notInsideLam NotInsideSCC 1
97
98 markMany, markInsideLam, markInsideSCC :: BinderInfo -> BinderInfo
99
100 markMany (SingleOcc _ _ _ ar) = ManyOcc ar
101 markMany (ManyOcc ar)      = ManyOcc ar
102 markMany DeadCode          = panic "markMany"
103
104 markInsideLam (SingleOcc _ in_scc n_alts ar) = SingleOcc insideLam in_scc n_alts ar
105 markInsideLam other                       = other
106
107 markInsideSCC (SingleOcc dup_danger _ n_alts ar) = SingleOcc dup_danger InsideSCC n_alts ar
108 markInsideSCC other                           = other
109
110 addBinderInfo, orBinderInfo :: BinderInfo -> BinderInfo -> BinderInfo
111
112 addBinderInfo DeadCode info2 = info2
113 addBinderInfo info1 DeadCode = info1
114 addBinderInfo info1 info2
115  = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
116
117 -- (orBinderInfo orig new) is used
118 -- when combining occurrence info from branches of a case
119
120 orBinderInfo DeadCode info2 = info2
121 orBinderInfo info1 DeadCode = info1
122 orBinderInfo (SingleOcc dup1 scc1 n_alts1 ar_1)
123              (SingleOcc dup2 scc2 n_alts2 ar_2)
124   = let
125      scc  = or_sccs  scc1  scc2
126      dup  = or_dups  dup1  dup2
127      alts = n_alts1 + n_alts2
128      ar   = min ar_1 ar_2
129    in
130    SingleOcc dup scc alts ar
131
132 orBinderInfo info1 info2
133  = ManyOcc (min (getBinderInfoArity info1) (getBinderInfoArity info2))
134
135 or_dups in_lam1 in_lam2 = in_lam1 || in_lam2
136
137 or_sccs InsideSCC _ = InsideSCC
138 or_sccs _ InsideSCC = InsideSCC
139 or_sccs _ _         = NotInsideSCC
140
141 setBinderInfoArityToZero :: BinderInfo -> BinderInfo
142 setBinderInfoArityToZero DeadCode    = DeadCode
143 setBinderInfoArityToZero (ManyOcc _) = ManyOcc 0
144 setBinderInfoArityToZero (SingleOcc dd sc i _) = SingleOcc dd sc i 0
145 \end{code}
146
147 \begin{code}
148 getBinderInfoArity (DeadCode) = 0
149 getBinderInfoArity (ManyOcc i) = i
150 getBinderInfoArity (SingleOcc _ _ _ i) = i
151 \end{code}
152
153 \begin{code}
154 instance Outputable BinderInfo where
155   ppr DeadCode     = ptext SLIT("Dead")
156   ppr (ManyOcc ar) = hcat [ ptext SLIT("Many-"), int ar ]
157   ppr (SingleOcc dup_danger in_scc n_alts ar)
158     = hcat [ ptext SLIT("One-"), ppr dup_danger,
159                   char '-', pp_scc in_scc,  char '-', int n_alts,
160                   char '-', int ar ]
161     where
162       pp_scc InsideSCC    = ptext SLIT("*SCC*")
163       pp_scc NotInsideSCC = ptext SLIT("noscc")
164 \end{code}