2 % (c) The AQUA Project, Glasgow University, 1993-1996
4 \section[SimplPgm]{Interface to the simplifier}
7 #include "HsVersions.h"
9 module SimplPgm ( simplifyPgm ) where
13 import CmdLineOpts ( opt_D_verbose_core2core,
14 switchIsOn, SimplifierSwitch(..)
17 import CoreUnfold ( SimpleUnfolding )
18 import CoreUtils ( substCoreExpr )
19 import Id ( externallyVisibleId,
20 mkIdEnv, lookupIdEnv, SYN_IE(IdEnv),
21 GenId{-instance Ord3-}
23 import Maybes ( catMaybes )
24 import OccurAnal ( occurAnalyseBinds )
25 import Pretty ( ppAboves, ppBesides, ppInt, ppChar, ppStr )
28 import Simplify ( simplTopBinds )
29 import TyVar ( nullTyVarEnv, SYN_IE(TyVarEnv) )
30 import UniqSupply ( thenUs, returnUs, mapUs, splitUniqSupply, SYN_IE(UniqSM) )
31 import Util ( isIn, isn'tIn, removeDups, pprTrace )
35 simplifyPgm :: [CoreBinding] -- input
36 -> (SimplifierSwitch->SwitchResult)
37 -> SimplCount -- info about how many times
38 -- each transformation has occurred
40 -> ([CoreBinding], -- output
41 Int, -- info about how much happened
42 SimplCount) -- accumulated simpl stats
44 simplifyPgm binds s_sw_chkr simpl_stats us
45 = case (splitUniqSupply us) of { (s1, s2) ->
46 case (initSmpl s1 (simpl_pgm 0 1 binds)) of { ((pgm2, it_count, simpl_stats2), _) ->
47 case (tidy_top pgm2 s2) of { pgm3 ->
48 (pgm3, it_count, combineSimplCounts simpl_stats simpl_stats2) }}}
50 simpl_switch_is_on = switchIsOn s_sw_chkr
52 occur_anal = occurAnalyseBinds
54 max_simpl_iterations = getSimplIntSwitch s_sw_chkr MaxSimplifierIterations
56 simpl_pgm :: Int -> Int -> [CoreBinding] -> SmplM ([CoreBinding], Int, SimplCount)
58 simpl_pgm n iterations pgm
59 = -- find out what top-level binders are used,
60 -- and prepare to unfold all the "simple" bindings
62 tagged_pgm = occur_anal pgm simpl_switch_is_on
65 simplTopBinds (nullSimplEnv s_sw_chkr) tagged_pgm `thenSmpl` \ new_pgm ->
67 -- Quit if we didn't actually do anything; otherwise,
68 -- try again (if suitable flags)
70 simplCount `thenSmpl` \ r ->
71 detailedSimplCount `thenSmpl` \ dr ->
73 show_status = pprTrace "NewSimpl: " (ppAboves [
74 ppBesides [ppInt iterations, ppChar '/', ppInt max_simpl_iterations],
75 ppStr (showSimplCount dr)
76 --DEBUG: , ppAboves (map (pprCoreBinding PprDebug) new_pgm)
80 (if opt_D_verbose_core2core
81 || simpl_switch_is_on ShowSimplifierProgress
85 (let stop_now = r == n {-nothing happened-}
86 || (if iterations > max_simpl_iterations then
87 (if max_simpl_iterations > 1 {-otherwise too boring-} then
89 ("NOTE: Simplifier still going after "++show max_simpl_iterations++" iterations; bailing out.")
96 returnSmpl (new_pgm, iterations, dr)
98 simpl_pgm r (iterations + 1) new_pgm
102 In @tidy_top@, we look for things at the top-level of the form...
106 x_exported = x_local -- or perhaps...
108 x_exported = /\ tyvars -> x_local tyvars -- where this is eta-reducible
110 In cases we find like this, we go {\em backwards} and replace
111 \tr{x_local} with \tr{x_exported}. This save a gratuitous jump
112 (from \tr{x_exported} to \tr{x_local}), and makes strictness
113 information propagate better.
115 If more than one exported thing is equal to a local thing (i.e., the
116 local thing really is shared), then obviously we give up.
118 Strategy: first collect the info; then make a \tr{Id -> Id} mapping.
119 Then blast the whole program (LHSs as well as RHSs) with it.
122 type BlastEnv = IdEnv Id -- domain is local Ids; range is exported Ids
124 not_elem = isn'tIn "undup"
126 tidy_top :: [CoreBinding] -> UniqSM [CoreBinding]
129 = if null blast_alist then
130 returnUs binds_in -- no joy there
132 mapUs blast binds_in `thenUs` \ binds_maybe ->
133 returnUs (catMaybes binds_maybe)
135 blast_alist = undup (foldl find_cand [] binds_in)
136 blast_id_env = mkIdEnv blast_alist
137 blast_val_env= mkIdEnv [ (l, Var e) | (l,e) <- blast_alist ]
138 blast_all_exps = map snd blast_alist
141 find_cand blast_list (Rec _) = blast_list -- recursively paranoid, as usual
143 find_cand blast_list (NonRec binder rhs)
144 = if not (externallyVisibleId binder) then
147 case rhs_equiv_to_local_var rhs of
148 Nothing -> blast_list
149 Just local -> (local, binder) : blast_list -- tag it on
151 ------------------------------------------
152 -- if an Id appears >1 time in the domain,
153 -- *all* occurrences must be expunged.
154 undup :: [(Id, Id)] -> [(Id, Id)]
158 (singles, dups) = removeDups compare blast_list
159 list_of_dups = concat dups
161 [ s | s <- singles, s `not_elem` list_of_dups ]
163 compare (x,_) (y,_) = x `cmp` y
165 ------------------------------------------
166 rhs_equiv_to_local_var (Var x)
167 = if externallyVisibleId x then Nothing else Just x
169 rhs_equiv_to_local_var expr = Nothing
171 ------------------------------------------
172 -- "blast" does the substitution:
173 -- returns Nothing if a binding goes away
174 -- returns "Just b" to give back a fixed-up binding
176 blast :: CoreBinding -> UniqSM (Maybe CoreBinding)
179 = mapUs blast_pr pairs `thenUs` \ blasted_pairs ->
180 returnUs (Just (Rec blasted_pairs))
182 blast_pr (binder, rhs)
183 = substCoreExpr blast_val_env nullTyVarEnv rhs `thenUs` \ new_rhs ->
185 case (lookupIdEnv blast_id_env binder) of
186 Just exportee -> (exportee, new_rhs)
187 Nothing -> (binder, new_rhs)
190 blast (NonRec binder rhs)
191 = if binder `is_elem` blast_all_exps then
192 returnUs Nothing -- this binding dies!
194 substCoreExpr blast_val_env nullTyVarEnv rhs `thenUs` \ new_rhs ->
196 case (lookupIdEnv blast_id_env binder) of
197 Just exportee -> NonRec exportee new_rhs
198 Nothing -> NonRec binder new_rhs
201 is_elem = isIn "blast"