[project @ 1997-03-14 07:52:06 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplVar.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1996
3 %
4 \section[SimplVar]{Simplifier stuff related to variables}
5
6 \begin{code}
7 #include "HsVersions.h"
8
9 module SimplVar (
10         completeVar
11     ) where
12
13 IMP_Ubiq(){-uitous-}
14 IMPORT_DELOOPER(SmplLoop)               ( simplExpr )
15
16 import Constants        ( uNFOLDING_USE_THRESHOLD,
17                           uNFOLDING_CON_DISCOUNT_WEIGHT
18                         )
19 import CmdLineOpts      ( switchIsOn, SimplifierSwitch(..) )
20 import CoreSyn
21 import CoreUnfold       ( Unfolding(..), UfExpr, RdrName, UnfoldingGuidance(..), SimpleUnfolding(..),
22                           FormSummary,
23                           okToInline, smallEnoughToInline )
24 import BinderInfo       ( BinderInfo, noBinderInfo )
25
26 import CostCentre       ( CostCentre, noCostCentreAttached )
27 import Id               ( idType, getIdInfo, getIdUnfolding, getIdSpecialisation,
28                           idMustBeINLINEd, GenId{-instance Outputable-}
29                         )
30 import SpecEnv          ( SpecEnv, lookupSpecEnv )
31 import IdInfo           ( DeforestInfo(..) )
32 import Literal          ( isNoRepLit )
33 import MagicUFs         ( applyMagicUnfoldingFun, MagicUnfoldingFun )
34 import PprStyle         ( PprStyle(..) )
35 import PprType          ( GenType{-instance Outputable-} )
36 --import Pretty         ( ppBesides, ppStr )
37 import SimplEnv
38 import SimplMonad
39 import TyCon            ( tyConFamilySize )
40 import Util             ( pprTrace, assertPanic, panic )
41 import Maybes           ( maybeToBool )
42 \end{code}
43
44 %************************************************************************
45 %*                                                                      *
46 \subsection[Simplify-var]{Completing variables}
47 %*                                                                      *
48 %************************************************************************
49
50 This where all the heavy-duty unfolding stuff comes into its own.
51
52 \begin{code}
53 completeVar env var args
54
55   | maybeToBool maybe_magic_result
56   = tick MagicUnfold    `thenSmpl_`
57     magic_result
58
59   | not do_deforest &&
60     maybeToBool maybe_unfolding_info &&
61     (not essential_unfoldings_only || idMustBeINLINEd var) && 
62     ok_to_inline &&
63         -- If "essential_unfolds_only" is true we do no inlinings at all,
64         -- EXCEPT for things that absolutely have to be done
65         -- (see comments with idMustBeINLINEd)
66         --
67         -- Need to be careful: the RHS of INLINE functions is protected against inlining
68         -- by essential_unfoldings_only being set true; we must not inline workers back into
69         -- wrappers, even thouth the former have an unfold-always guidance.
70     costCentreOk (getEnclosingCC env) (getEnclosingCC unfold_env)
71   = tick UnfoldingDone  `thenSmpl_`
72 #ifdef DEBUG
73 --    simplCount                `thenSmpl` \ n ->
74 --    (if n > 3000 then
75 --      pprTrace "Ticks > 3000 and unfolding" (ppr PprDebug var)
76 --    else
77 --      id
78 --    )
79 #endif
80     simplExpr unfold_env unf_template args
81
82   | maybeToBool maybe_specialisation
83   = tick SpecialisationDone     `thenSmpl_`
84     simplExpr (extendTyEnvList env spec_bindings) 
85               spec_template
86               (map TyArg leftover_ty_args ++ remaining_args)
87
88   | otherwise
89   = returnSmpl (mkGenApp (Var var) args)
90
91   where
92     unfolding_from_id = getIdUnfolding var
93
94         ---------- Magic unfolding stuff
95     maybe_magic_result  = case unfolding_from_id of
96                                 MagicUnfolding _ magic_fn -> applyMagicUnfoldingFun magic_fn 
97                                                                                     env args
98                                 other                     -> Nothing
99     (Just magic_result) = maybe_magic_result
100
101         ---------- Unfolding stuff
102     maybe_unfolding_info 
103         = case (lookupOutIdEnv env var, unfolding_from_id) of
104
105              (Just (_, occ_info, OutUnfolding enc_cc unf), _)
106                 -> Just (occ_info, setEnclosingCC env enc_cc, unf)      
107
108              (Just (_, occ_info, InUnfolding env_unf unf), _)
109                 -> Just (occ_info, env_unf, unf)        
110 --                      This combineSimplEnv is WRONG.  InUnfoldings are used for
111 --                      recursive decls, and we're relying on using the old unfold enf
112 --                      to avoid getting outselves in a loop!
113 --              -> Just (occ_info, combineSimplEnv env env_unf, unf)    
114
115              (_, CoreUnfolding unf)
116                 -> Just (noBinderInfo, env, unf)
117
118              other -> Nothing
119
120     Just (occ_info, unfold_env, simple_unfolding)     = maybe_unfolding_info
121     SimpleUnfolding form guidance unf_template = simple_unfolding
122
123         ---------- Specialisation stuff
124     (ty_args, remaining_args) = initialTyArgs args
125     maybe_specialisation = lookupSpecEnv (getIdSpecialisation var) ty_args
126     (Just (spec_template, (spec_bindings, leftover_ty_args))) = maybe_specialisation
127
128
129         ---------- Switches
130     sw_chkr                   = getSwitchChecker env
131     essential_unfoldings_only = switchIsOn sw_chkr EssentialUnfoldingsOnly
132     always_inline             = case guidance of {UnfoldAlways -> True; other -> False}
133     ok_to_inline              = okToInline form 
134                                            occ_info
135                                            small_enough
136     small_enough = smallEnoughToInline arg_evals guidance
137     arg_evals = [is_evald arg | arg <- args, isValArg arg]
138   
139     is_evald (VarArg v) = isEvaluated (lookupRhsInfo env v)
140     is_evald (LitArg l) = True
141
142 #if OMIT_DEFORESTER
143     do_deforest = False
144 #else
145     do_deforest = case (getDeforestInfo (getIdInfo var)) of { DoDeforest -> True; _ -> False }
146 #endif
147
148
149 -- costCentreOk checks that it's ok to inline this thing
150 -- The time it *isn't* is this:
151 --
152 --      f x = let y = E in
153 --            scc "foo" (...y...)
154 --
155 -- Here y has a subsumed cost centre, and we can't inline it inside "foo",
156 -- regardless of whether E is a WHNF or not.
157
158 costCentreOk cc_encl cc_rhs
159   = noCostCentreAttached cc_encl || not (noCostCentreAttached cc_rhs)
160 \end{code}                 
161