[project @ 2000-11-16 14:43:05 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplCore.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[SimplCore]{Driver for simplifying @Core@ programs}
5
6 \begin{code}
7 module SimplCore ( core2core, simplifyExpr ) where
8
9 #include "HsVersions.h"
10
11 import CmdLineOpts      ( CoreToDo(..), SimplifierSwitch(..), 
12                           SwitchResult(..), intSwitchSet,
13                           DynFlags, DynFlag(..), dopt, dopt_CoreToDo
14                         )
15 import CoreLint         ( showPass, endPass )
16 import CoreSyn
17 import CoreFVs          ( ruleRhsFreeVars )
18 import HscTypes         ( PersistentCompilerState(..),
19                           PackageRuleBase, HomeSymbolTable, IsExported, ModDetails(..)
20                         )
21 import CSE              ( cseProgram )
22 import Rules            ( RuleBase, emptyRuleBase, ruleBaseFVs, ruleBaseIds, 
23                           extendRuleBaseList, addRuleBaseFVs )
24 import Module           ( moduleEnvElts )
25 import CoreUnfold
26 import PprCore          ( pprCoreBindings, pprIdCoreRule, pprCoreExpr )
27 import OccurAnal        ( occurAnalyseBinds )
28 import CoreUtils        ( etaReduceExpr, coreBindsSize )
29 import Simplify         ( simplTopBinds, simplExpr )
30 import SimplUtils       ( simplBinders )
31 import SimplMonad
32 import ErrUtils         ( dumpIfSet, dumpIfSet_dyn )
33 import FloatIn          ( floatInwards )
34 import FloatOut         ( floatOutwards )
35 import Id               ( idName, isDataConWrapId, setIdNoDiscard, isLocalId )
36 import VarSet
37 import LiberateCase     ( liberateCase )
38 import SAT              ( doStaticArgs )
39 import Specialise       ( specProgram)
40 import UsageSPInf       ( doUsageSPInf )
41 import StrictAnal       ( saBinds )
42 import WorkWrap         ( wwTopBinds )
43 import CprAnalyse       ( cprAnalyse )
44
45 import UniqSupply       ( UniqSupply, mkSplitUniqSupply, splitUniqSupply )
46 import IO               ( hPutStr, stderr )
47 import Outputable
48
49 import Maybes           ( orElse )
50 import List             ( partition )
51 \end{code}
52
53 %************************************************************************
54 %*                                                                      *
55 \subsection{The driver for the simplifier}
56 %*                                                                      *
57 %************************************************************************
58
59 \begin{code}
60 core2core :: DynFlags           -- includes spec of what core-to-core passes to do
61           -> PersistentCompilerState
62           -> HomeSymbolTable
63           -> IsExported
64           -> [CoreBind]         -- Binds in
65           -> [IdCoreRule]       -- Rules in
66           -> IO ([CoreBind], [IdCoreRule])  -- binds, local orphan rules out
67
68 core2core dflags pcs hst is_exported binds rules
69   = do
70         let core_todos    = dopt_CoreToDo dflags
71         let pkg_rule_base = pcs_rules pcs               -- Rule-base accumulated from imported packages
72
73         us <-  mkSplitUniqSupply 's'
74         let (cp_us, ru_us) = splitUniqSupply us
75
76                 -- COMPUTE THE RULE BASE TO USE
77         (rule_base, local_rule_stuff, orphan_rules)
78                 <- prepareRules dflags pkg_rule_base hst ru_us binds rules
79
80                 -- PREPARE THE BINDINGS
81         let binds1 = updateBinders local_rule_stuff is_exported binds
82
83                 -- DO THE BUSINESS
84         (stats, processed_binds)
85                 <- doCorePasses dflags rule_base (zeroSimplCount dflags) cp_us binds1 core_todos
86
87         dumpIfSet_dyn dflags Opt_D_dump_simpl_stats
88                   "Grand total simplifier statistics"
89                   (pprSimplCount stats)
90
91         -- Return results
92         -- We only return local orphan rules, i.e., local rules not attached to an Id
93         -- The bindings cotain more rules, embedded in the Ids
94         return (processed_binds, orphan_rules)
95
96
97 simplifyExpr :: DynFlags                -- includes spec of what core-to-core passes to do
98              -> PersistentCompilerState
99              -> HomeSymbolTable
100              -> CoreExpr
101              -> IO CoreExpr
102 simplifyExpr dflags pcs hst expr
103   = do  {
104         ; us <-  mkSplitUniqSupply 's'
105
106         ; let (expr', counts) = initSmpl dflags sw_chkr us emptyVarSet black_list_all   
107                                          (simplExpr expr)
108
109         ; dumpIfSet_dyn dflags Opt_D_dump_simpl "Simplfied expression"
110                         (pprCoreExpr expr')
111
112         ; return expr'
113         }
114   where
115     sw_chkr any      = SwBool False     -- A bit bogus
116     black_list_all v = True             -- Black list everything
117
118
119 doCorePasses :: DynFlags
120              -> RuleBase        -- the main rule base
121              -> SimplCount      -- simplifier stats
122              -> UniqSupply      -- uniques
123              -> [CoreBind]      -- local binds in (with rules attached)
124              -> [CoreToDo]      -- which passes to do
125              -> IO (SimplCount, [CoreBind])  -- stats, binds, local orphan rules
126
127 doCorePasses dflags rb stats us binds []
128   = return (stats, binds)
129
130 doCorePasses dflags rb stats us binds (to_do : to_dos) 
131   = do
132         let (us1, us2) = splitUniqSupply us
133
134         (stats1, binds1) <- doCorePass dflags rb us1 binds to_do
135
136         doCorePasses dflags rb (stats `plusSimplCount` stats1) us2 binds1 to_dos
137
138 doCorePass dfs rb us binds (CoreDoSimplify sw_chkr) 
139    = _scc_ "Simplify"      simplifyPgm dfs rb sw_chkr us binds
140 doCorePass dfs rb us binds CoreCSE                      
141    = _scc_ "CommonSubExpr" noStats dfs (cseProgram dfs binds)
142 doCorePass dfs rb us binds CoreLiberateCase             
143    = _scc_ "LiberateCase"  noStats dfs (liberateCase dfs binds)
144 doCorePass dfs rb us binds CoreDoFloatInwards       
145    = _scc_ "FloatInwards"  noStats dfs (floatInwards dfs binds)
146 doCorePass dfs rb us binds (CoreDoFloatOutwards f)  
147    = _scc_ "FloatOutwards" noStats dfs (floatOutwards dfs f us binds)
148 doCorePass dfs rb us binds CoreDoStaticArgs             
149    = _scc_ "StaticArgs"    noStats dfs (doStaticArgs us binds)
150 doCorePass dfs rb us binds CoreDoStrictness             
151    = _scc_ "Stranal"       noStats dfs (saBinds dfs binds)
152 doCorePass dfs rb us binds CoreDoWorkerWrapper      
153    = _scc_ "WorkWrap"      noStats dfs (wwTopBinds dfs us binds)
154 doCorePass dfs rb us binds CoreDoSpecialising       
155    = _scc_ "Specialise"    noStats dfs (specProgram dfs us binds)
156 doCorePass dfs rb us binds CoreDoCPResult               
157    = _scc_ "CPResult"      noStats dfs (cprAnalyse dfs binds)
158 doCorePass dfs rb us binds CoreDoPrintCore              
159    = _scc_ "PrintCore"     noStats dfs (printCore binds)
160 doCorePass dfs rb us binds CoreDoUSPInf             
161    = _scc_ "CoreUsageSPInf" noStats dfs (doUsageSPInf dfs us binds)
162 doCorePass dfs rb us binds CoreDoGlomBinds              
163    = noStats dfs (glomBinds dfs binds)
164 doCorePass dfs rb us binds CoreDoNothing
165    = noStats dfs (return binds)
166
167 printCore binds = do dumpIfSet True "Print Core"
168                                (pprCoreBindings binds)
169                      return binds
170
171 -- most passes return no stats and don't change rules
172 noStats dfs thing = do { binds <- thing; return (zeroSimplCount dfs, binds) }
173 \end{code}
174
175
176
177 %************************************************************************
178 %*                                                                      *
179 \subsection{Dealing with rules}
180 %*                                                                      *
181 %************************************************************************
182
183 -- prepareLocalRuleBase takes the CoreBinds and rules defined in this module.
184 -- It attaches those rules that are for local Ids to their binders, and
185 -- returns the remainder attached to Ids in an IdSet.  It also returns
186 -- Ids mentioned on LHS of some rule; these should be blacklisted.
187
188 -- The rule Ids and LHS Ids are black-listed; that is, they aren't inlined
189 -- so that the opportunity to apply the rule isn't lost too soon
190
191 \begin{code}
192 prepareRules :: DynFlags -> PackageRuleBase -> HomeSymbolTable
193              -> UniqSupply
194              -> [CoreBind]
195              -> [IdCoreRule]            -- Local rules
196              -> IO (RuleBase,           -- Full rule base
197                     (IdSet,IdSet),      -- Local rule Ids, and RHS fvs
198                     [IdCoreRule])       -- Orphan rules
199
200 prepareRules dflags pkg_rule_base hst us binds rules
201   = do  { let (better_rules,_) = initSmpl dflags sw_chkr us local_ids black_list_all 
202                                           (mapSmpl simplRule rules)
203
204         ; dumpIfSet_dyn dflags Opt_D_dump_rules "Transformation rules"
205                         (vcat (map pprIdCoreRule better_rules))
206
207         ; let (local_rules, orphan_rules) = partition (isLocalId . fst) better_rules
208               local_rule_rhs_fvs          = unionVarSets (map (ruleRhsFreeVars . snd) local_rules)
209               local_rule_base             = extendRuleBaseList emptyRuleBase local_rules
210               local_rule_ids              = ruleBaseIds local_rule_base -- Local Ids with rules attached
211               imp_rule_base               = foldl add_rules pkg_rule_base (moduleEnvElts hst)
212               rule_base                   = extendRuleBaseList imp_rule_base orphan_rules
213               final_rule_base             = addRuleBaseFVs rule_base (ruleBaseFVs local_rule_base)
214                 -- The last step black-lists the free vars of local rules too
215
216         ; return (final_rule_base, (local_rule_ids, local_rule_rhs_fvs), orphan_rules)
217     }
218   where
219     sw_chkr any      = SwBool False                     -- A bit bogus
220     black_list_all v = not (isDataConWrapId v)
221                 -- This stops all inlining except the
222                 -- wrappers for data constructors
223
224     add_rules rule_base mds = extendRuleBaseList rule_base (md_rules mds)
225
226         -- Boringly, we need to gather the in-scope set.
227         -- Typically this thunk won't even be forced, but the test in
228         -- simpVar fails if it isn't right, and it might conceiveably matter
229     local_ids = foldr (unionVarSet . mkVarSet . bindersOf) emptyVarSet binds
230
231
232 updateBinders :: (IdSet,                -- Locally defined ids with their Rules attached
233                   IdSet)                -- Ids free in the RHS of local rules
234               -> IsExported
235               -> [CoreBind] -> [CoreBind]
236         -- A horrible function
237
238 -- Update the binders of top-level bindings as follows
239 --      a) Attach the rules for each locally-defined Id to that Id.
240 --      b) Set the no-discard flag if either the Id is exported,
241 --         or it's mentoined in the RHS of a rule
242 -- 
243 -- Reason for (a)
244 --      - It makes the rules easier to look up
245 --      - It means that transformation rules and specialisations for
246 --        locally defined Ids are handled uniformly
247 --      - It keeps alive things that are referred to only from a rule
248 --        (the occurrence analyser knows about rules attached to Ids)
249 --      - It makes sure that, when we apply a rule, the free vars
250 --        of the RHS are more likely to be in scope
251 --
252 -- Reason for (b)
253 --     It means that the binding won't be discarded EVEN if the binding
254 --     ends up being trivial (v = w) -- the simplifier would usually just 
255 --     substitute w for v throughout, but we don't apply the substitution to
256 --     the rules (maybe we should?), so this substitution would make the rule
257 --     bogus.
258
259 updateBinders (rule_ids, rule_rhs_fvs) is_exported binds
260   = map update_bndrs binds
261   where
262     update_bndrs (NonRec b r) = NonRec (update_bndr b) r
263     update_bndrs (Rec prs)    = Rec [(update_bndr b, r) | (b,r) <- prs]
264
265     update_bndr bndr 
266         |  is_exported (idName bndr)
267         || bndr `elemVarSet` rule_rhs_fvs = setIdNoDiscard bndr'
268         | otherwise                       = bndr'
269         where
270           bndr' = lookupVarSet rule_ids bndr `orElse` bndr
271 \end{code}
272
273
274 We must do some gentle simplification on the template (but not the RHS)
275 of each rule.  The case that forced me to add this was the fold/build rule,
276 which without simplification looked like:
277         fold k z (build (/\a. g a))  ==>  ...
278 This doesn't match unless you do eta reduction on the build argument.
279
280 \begin{code}
281 simplRule rule@(id, BuiltinRule _)
282   = returnSmpl rule
283 simplRule rule@(id, Rule name bndrs args rhs)
284   = simplBinders bndrs                  $ \ bndrs' -> 
285     mapSmpl simpl_arg args              `thenSmpl` \ args' ->
286     simplExpr rhs                       `thenSmpl` \ rhs' ->
287     returnSmpl (id, Rule name bndrs' args' rhs')
288
289 simpl_arg e 
290 --  I've seen rules in which a LHS like 
291 --      augment g (build h) 
292 -- turns into
293 --      augment (\a. g a) (build h)
294 -- So it's a help to eta-reduce the args as we simplify them.
295 -- Otherwise we don't match when given an argument like
296 --      (\a. h a a)
297   = simplExpr e         `thenSmpl` \ e' ->
298     returnSmpl (etaReduceExpr e')
299 \end{code}
300
301
302 %************************************************************************
303 %*                                                                      *
304 \subsection{Glomming}
305 %*                                                                      *
306 %************************************************************************
307
308 \begin{code}
309 glomBinds :: DynFlags -> [CoreBind] -> IO [CoreBind]
310 -- Glom all binds together in one Rec, in case any
311 -- transformations have introduced any new dependencies
312 --
313 -- NB: the global invariant is this:
314 --      *** the top level bindings are never cloned, and are always unique ***
315 --
316 -- We sort them into dependency order, but applying transformation rules may
317 -- make something at the top refer to something at the bottom:
318 --      f = \x -> p (q x)
319 --      h = \y -> 3
320 --      
321 --      RULE:  p (q x) = h x
322 --
323 -- Applying this rule makes f refer to h, 
324 -- although it doesn't appear to in the source program.  
325 -- This pass lets us control where it happens.
326 --
327 -- NOTICE that this cannot happen for rules whose head is a locally-defined
328 -- function.  It only happens for rules whose head is an imported function
329 -- (p in the example above).  So, for example, the rule had been
330 --      RULE: f (p x) = h x
331 -- then the rule for f would be attached to f itself (in its IdInfo) 
332 -- by prepareLocalRuleBase and h would be regarded by the occurrency 
333 -- analyser as free in f.
334
335 glomBinds dflags binds
336   = do { showPass dflags "GlomBinds" ;
337          let { recd_binds = [Rec (flattenBinds binds)] } ;
338          return recd_binds }
339         -- Not much point in printing the result... 
340         -- just consumes output bandwidth
341 \end{code}
342
343
344 %************************************************************************
345 %*                                                                      *
346 \subsection{The driver for the simplifier}
347 %*                                                                      *
348 %************************************************************************
349
350 \begin{code}
351 simplifyPgm :: DynFlags 
352             -> RuleBase
353             -> (SimplifierSwitch -> SwitchResult)
354             -> UniqSupply
355             -> [CoreBind]                   -- Input
356             -> IO (SimplCount, [CoreBind])  -- New bindings
357
358 simplifyPgm dflags rule_base
359             sw_chkr us binds
360   = do {
361         showPass dflags "Simplify";
362
363         (termination_msg, it_count, counts_out, binds') 
364            <- iteration us 1 (zeroSimplCount dflags) binds;
365
366         dumpIfSet (dopt Opt_D_verbose_core2core dflags 
367                    && dopt Opt_D_dump_simpl_stats dflags)
368                   "Simplifier statistics"
369                   (vcat [text termination_msg <+> text "after" <+> ppr it_count <+> text "iterations",
370                          text "",
371                          pprSimplCount counts_out]);
372
373         endPass dflags "Simplify" 
374                 (dopt Opt_D_verbose_core2core dflags 
375                  && not (dopt Opt_D_dump_simpl_iterations dflags))
376                 binds' ;
377
378         return (counts_out, binds')
379     }
380   where
381     max_iterations    = getSimplIntSwitch sw_chkr MaxSimplifierIterations
382     black_list_fn     = blackListed rule_lhs_fvs (intSwitchSet sw_chkr SimplInlinePhase)
383     imported_rule_ids = ruleBaseIds rule_base
384     rule_lhs_fvs      = ruleBaseFVs rule_base
385  
386     iteration us iteration_no counts binds
387       -- Try and force thunks off the binds; significantly reduces
388       -- space usage, especially with -O.  JRS, 000620.
389       | let sz = coreBindsSize binds in sz == sz
390       = do {
391                 -- Occurrence analysis
392            let { tagged_binds = _scc_ "OccAnal" occurAnalyseBinds binds } ;
393
394            dumpIfSet_dyn dflags Opt_D_dump_occur_anal "Occurrence analysis"
395                      (pprCoreBindings tagged_binds);
396
397                 -- SIMPLIFY
398                 -- We do this with a *case* not a *let* because lazy pattern
399                 -- matching bit us with bad space leak!
400                 -- With a let, we ended up with
401                 --   let
402                 --      t = initSmpl ...
403                 --      counts' = snd t
404                 --   in
405                 --      case t of {(_,counts') -> if counts'=0 then ...
406                 -- So the conditional didn't force counts', because the
407                 -- selection got duplicated.  Sigh!
408            case initSmpl dflags sw_chkr us1 imported_rule_ids black_list_fn 
409                          (simplTopBinds tagged_binds)
410                 of { (binds', counts') -> do {
411                         -- The imported_rule_ids are used by initSmpl to initialise
412                         -- the in-scope set.  That way, the simplifier will change any
413                         -- occurrences of the imported id to the one in the imported_rule_ids
414                         -- set, which are decorated with their rules.
415
416            let { all_counts = counts `plusSimplCount` counts' } ;
417
418                 -- Stop if nothing happened; don't dump output
419            if isZeroSimplCount counts' then
420                 return ("Simplifier reached fixed point", iteration_no, all_counts, binds')
421            else do {
422
423                 -- Dump the result of this iteration
424            dumpIfSet_dyn dflags Opt_D_dump_simpl_iterations
425                      ("Simplifier iteration " ++ show iteration_no 
426                       ++ " out of " ++ show max_iterations)
427                      (pprSimplCount counts') ;
428
429            if dopt Opt_D_dump_simpl_iterations dflags then
430                 endPass dflags 
431                         ("Simplifier iteration " ++ show iteration_no ++ " result")
432                         (dopt Opt_D_verbose_core2core dflags)
433                         binds'
434            else
435                 return [] ;
436
437                 -- Stop if we've run out of iterations
438            if iteration_no == max_iterations then
439                 do {
440 #ifdef DEBUG
441                     if  max_iterations > 2 then
442                             hPutStr stderr ("NOTE: Simplifier still going after " ++ 
443                                     show max_iterations ++ 
444                                     " iterations; bailing out.\n")
445                     else 
446 #endif
447                         return ();
448
449                     return ("Simplifier baled out", iteration_no, all_counts, binds')
450                 }
451
452                 -- Else loop
453            else iteration us2 (iteration_no + 1) all_counts binds'
454         }  } } }
455       where
456           (us1, us2) = splitUniqSupply us
457 \end{code}