f7f67fa01373a698b9b268a20b25f173e27d99a2
[ghc-hetmet.git] / ghc / compiler / simplCore / SATMonad.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[SATMonad]{The Static Argument Transformation pass Monad}
7 %*                                                                      *
8 %************************************************************************
9
10 96/03: We aren't using the static-argument transformation right now.
11
12 \begin{code}
13 module SATMonad where
14
15 #include "HsVersions.h"
16
17 import Util             ( panic )
18
19 junk_from_SATMonad = panic "SATMonad.junk"
20
21 {- LATER: to end of file:
22
23 module SATMonad (
24         SATInfo(..), updSAEnv,
25         SatM(..), initSAT, emptyEnvSAT,
26         returnSAT, thenSAT, thenSAT_, mapSAT, getSATInfo, newSATName,
27         getArgLists, Arg(..), insSAEnv, saTransform,
28
29         SATEnv(..), isStatic, dropStatics
30     ) where
31
32 import Type             ( mkTyVarTy, mkSigmaTy, TyVarTemplate,
33                           splitSigmaTy, splitFunTys,
34                           glueTyArgs, instantiateTy, TauType,
35                           Class, ThetaType, SigmaType,
36                           InstTyEnv(..)
37                         )
38 import MkId             ( mkSysLocal )
39 import Id               ( idType )
40 import SrcLoc           ( SrcLoc, noSrcLoc )
41 import UniqSupply
42 import Util
43
44 infixr 9 `thenSAT`, `thenSAT_`
45 \end{code}
46
47 %************************************************************************
48 %*                                                                      *
49 \subsection{Static Argument Transformation Environment}
50 %*                                                                      *
51 %************************************************************************
52
53 \begin{code}
54 type SATEnv = IdEnv SATInfo
55
56 type SATInfo = ([Arg Type],[Arg Id])
57
58 data Arg a = Static a | NotStatic
59     deriving Eq
60
61 delOneFromSAEnv v us env
62   = ((), delOneFromIdEnv env v)
63
64 updSAEnv :: Maybe (Id,SATInfo) -> SatM ()
65 updSAEnv Nothing
66   = returnSAT ()
67 updSAEnv (Just (b,(tyargs,args)))
68   = getSATInfo b      `thenSAT` (\ r ->
69     case r of
70       Nothing              -> returnSAT ()
71       Just (tyargs',args') -> delOneFromSAEnv b `thenSAT_`
72                               insSAEnv b (checkArgs tyargs tyargs',
73                                           checkArgs args args')
74     )
75
76 checkArgs as [] = notStatics (length as)
77 checkArgs [] as = notStatics (length as)
78 checkArgs (a:as) (a':as') | a == a' = a:checkArgs as as'
79 checkArgs (_:as) (_:as') = NotStatic:checkArgs as as'
80
81 notStatics :: Int -> [Arg a]
82 notStatics n = nOfThem n NotStatic
83
84 insSAEnv :: Id -> SATInfo -> SatM ()
85 insSAEnv b info us env
86   = ((), addOneToIdEnv env b info)
87 \end{code}
88
89 %************************************************************************
90 %*                                                                      *
91 \subsection{Static Argument Transformation Monad}
92 %*                                                                      *
93 %************************************************************************
94
95 Two items of state to thread around: a UniqueSupply and a SATEnv.
96
97 \begin{code}
98 type SatM result
99   =  UniqSupply -> SATEnv -> (result, SATEnv)
100
101 initSAT :: SatM a -> UniqSupply -> a
102
103 initSAT f us = fst (f us nullIdEnv)
104
105 thenSAT m k us env
106   = case splitUniqSupply us     of { (s1, s2) ->
107     case m s1 env               of { (m_result, menv) ->
108     k m_result s2 menv }}
109
110 thenSAT_ m k us env
111   = case splitUniqSupply us     of { (s1, s2) ->
112     case m s1 env               of { (_, menv) ->
113     k s2 menv }}
114
115 emptyEnvSAT :: SatM ()
116 emptyEnvSAT us _ = ((), nullIdEnv)
117
118 returnSAT v us env = (v, env)
119
120 mapSAT f []     = returnSAT []
121 mapSAT f (x:xs)
122   = f x         `thenSAT` \ x'  ->
123     mapSAT f xs `thenSAT` \ xs' ->
124     returnSAT (x':xs')
125 \end{code}
126
127 %************************************************************************
128 %*                                                                      *
129 \subsection{Utility Functions}
130 %*                                                                      *
131 %************************************************************************
132
133 \begin{code}
134 getSATInfo :: Id -> SatM (Maybe SATInfo)
135 getSATInfo var us env
136   = (lookupIdEnv env var, env)
137
138 newSATName :: Id -> Type -> SatM Id
139 newSATName id ty us env
140   = case (getUnique us) of { unique ->
141     (mkSysLocal new_str unique ty noSrcLoc, env) }
142   where
143     new_str = getOccName id _APPEND_ SLIT("_sat")
144
145 getArgLists :: CoreExpr -> ([Arg Type],[Arg Id])
146 getArgLists expr
147   = let
148         (tvs, lambda_bounds, body) = collectBinders expr
149     in
150     ([ Static (mkTyVarTy tv) | tv <- tvs ],
151      [ Static v              | v <- lambda_bounds ])
152
153 dropArgs :: CoreExpr -> CoreExpr
154 dropArgs (Lam   _ e)    = dropArgs e
155 dropArgs (CoTyLam _ e)  = dropArgs e
156 dropArgs e              = e
157 \end{code}
158
159 We implement saTransform using shadowing of binders, that is
160 we transform
161 map = \f as -> case as of
162                  [] -> []
163                  (a':as') -> let x = f a'
164                                  y = map f as'
165                              in x:y
166 to
167 map = \f as -> let map = \f as -> map' as
168                in let rec map' = \as -> case as of
169                                           [] -> []
170                                           (a':as') -> let x = f a'
171                                                           y = map f as'
172                                                       in x:y
173                   in map' as
174
175 the inner map should get inlined and eliminated.
176 \begin{code}
177 saTransform :: Id -> CoreExpr -> SatM CoreBinding
178 saTransform binder rhs
179   = getSATInfo binder `thenSAT` \ r ->
180     case r of
181       -- [Andre] test: do it only if we have more than one static argument.
182       --Just (tyargs,args) | any isStatic args
183       Just (tyargs,args) | length (filter isStatic args) > 1
184         -> newSATName binder (new_ty tyargs args)  `thenSAT` \ binder' ->
185            mkNewRhs binder binder' tyargs args rhs `thenSAT` \ new_rhs ->
186            trace ("SAT "++ show (length (filter isStatic args))) (
187            returnSAT (NonRec binder new_rhs)
188            )
189       _ -> returnSAT (Rec [(binder, rhs)])
190   where
191     mkNewRhs binder binder' tyargs args rhs
192       = let
193             non_static_args :: [Id]
194             non_static_args
195                = get_nsa args (snd (getArgLists rhs))
196                where
197                  get_nsa :: [Arg a] -> [Arg a] -> [a]
198                  get_nsa [] _ = []
199                  get_nsa _ [] = []
200                  get_nsa (NotStatic:args) (Static v:as) = v:get_nsa args as
201                  get_nsa (_:args)         (_:as)        =   get_nsa args as
202
203             local_body = foldl App (Var binder')
204                                 [VarArg a | a <- non_static_args]
205
206             nonrec_rhs = origLams local_body
207
208             -- HACK! The following is a fake SysLocal binder with
209             -- *the same* unique as binder.
210             -- the reason for this is the following:
211             -- this binder *will* get inlined but if it happen to be
212             -- a top level binder it is never removed as dead code,
213             -- therefore we have to remove that information (of it being
214             -- top-level or exported somehow.)
215             -- A better fix is to use binder directly but with the TopLevel
216             -- tag (or Exported tag) modified.
217             fake_binder = mkSysLocal
218                             (getOccName binder _APPEND_ SLIT("_fsat"))
219                             (uniqueOf binder)
220                             (idType binder)
221                             noSrcLoc
222             rec_body = mkValLam non_static_args
223                                ( Let (NonRec fake_binder nonrec_rhs)
224                                  {-in-} (dropArgs rhs))
225         in
226         returnSAT (
227             origLams (Let (Rec [(binder',rec_body)]) {-in-} local_body)
228         )
229       where
230         origLams = origLams' rhs
231                  where
232                    origLams' (Lam v e)     e' = Lam   v  (origLams' e e')
233                    origLams' (CoTyLam ty e)  e' = CoTyLam ty (origLams' e e')
234                    origLams' _               e' = e'
235
236     new_ty tyargs args
237       = instantiateTy (mk_inst_tyenv tyargs tv_tmpl)
238                       (mkSigmaTy tv_tmpl' dict_tys' tau_ty')
239       where
240         -- get type info for the local function:
241         (tv_tmpl, dict_tys, tau_ty) = (splitSigmaTy . idType) binder
242         (reg_arg_tys, res_type)     = splitFunTys tau_ty
243
244         -- now, we drop the ones that are
245         -- static, that is, the ones we will not pass to the local function
246         l            = length dict_tys
247         tv_tmpl'     = dropStatics tyargs tv_tmpl
248         dict_tys'    = dropStatics (take l args) dict_tys
249         reg_arg_tys' = dropStatics (drop l args) reg_arg_tys
250         tau_ty'      = glueTyArgs reg_arg_tys' res_type
251
252         mk_inst_tyenv []                    _ = emptyTyVarEnv
253         mk_inst_tyenv (Static s:args) (t:ts)  = addToTyVarEnv (mk_inst_tyenv args ts) t s
254         mk_inst_tyenv (_:args)      (_:ts)    = mk_inst_tyenv args ts
255
256 dropStatics [] t = t
257 dropStatics (Static _:args) (t:ts) = dropStatics args ts
258 dropStatics (_:args)        (t:ts) = t:dropStatics args ts
259
260 isStatic :: Arg a -> Bool
261 isStatic NotStatic = False
262 isStatic _         = True
263 -}
264 \end{code}