2 % (c) The AQUA Project, Glasgow University, 1993-1996
4 \section[SimplMonad]{The simplifier Monad}
7 #include "HsVersions.h"
11 initSmpl, returnSmpl, thenSmpl, thenSmpl_,
12 mapSmpl, mapAndUnzipSmpl,
15 SimplCount{-abstract-}, TickType(..), tick, tickN,
16 simplCount, detailedSimplCount,
17 zeroSimplCount, showSimplCount, combineSimplCounts,
20 cloneId, cloneIds, cloneTyVarSmpl, newIds, newId
22 -- and to make the interface self-sufficient...
27 import SmplLoop -- well, cheating sort of
29 import Id ( mkSysLocal )
31 import SrcLoc ( mkUnknownSrcLoc )
32 import UniqSupply ( getUnique, getUniques, splitUniqSupply,
35 import Util ( zipWithEqual, panic )
37 infixr 9 `thenSmpl`, `thenSmpl_`
39 cloneTyVar = panic "cloneTyVar (SimplMonad)"
40 mkIdWithNewUniq = panic "mkIdWithNewUniq (SimplMonad)"
43 %************************************************************************
45 \subsection{Monad plumbing}
47 %************************************************************************
49 For the simplifier monad, we want to {\em thread} a unique supply and a counter.
50 (Command-line switches move around through the explicitly-passed SimplEnv.)
55 -> SimplCount -- things being threaded
56 -> (result, SimplCount)
60 initSmpl :: UniqSupply -- no init count; set to 0
64 initSmpl us m = m us zeroSimplCount
66 {-# INLINE thenSmpl #-}
67 {-# INLINE thenSmpl_ #-}
68 {-# INLINE returnSmpl #-}
70 returnSmpl :: a -> SmplM a
71 returnSmpl e us sc = (e, sc)
73 thenSmpl :: SmplM a -> (a -> SmplM b) -> SmplM b
74 thenSmpl_ :: SmplM a -> SmplM b -> SmplM b
77 = case splitUniqSupply us of { (s1, s2) ->
78 case (m s1 sc0) of { (m_result, sc1) ->
82 = case splitUniqSupply us of { (s1, s2) ->
83 case (m s1 sc0) of { (_, sc1) ->
86 mapSmpl :: (a -> SmplM b) -> [a] -> SmplM [b]
87 mapAndUnzipSmpl :: (a -> SmplM (b, c)) -> [a] -> SmplM ([b],[c])
89 mapSmpl f [] = returnSmpl []
91 = f x `thenSmpl` \ x' ->
92 mapSmpl f xs `thenSmpl` \ xs' ->
95 mapAndUnzipSmpl f [] = returnSmpl ([],[])
96 mapAndUnzipSmpl f (x:xs)
97 = f x `thenSmpl` \ (r1, r2) ->
98 mapAndUnzipSmpl f xs `thenSmpl` \ (rs1, rs2) ->
99 returnSmpl (r1:rs1, r2:rs2)
103 %************************************************************************
105 \subsection{Counting up what we've done}
107 %************************************************************************
109 The assoc list isn't particularly costly, because we only use
110 the number of ticks in ``real life.''
112 The right thing to do, if you want that to go fast, is thread
113 a mutable array through @SimplM@.
117 = SimplCount FAST_INT -- number of ticks
118 [(TickType, Int)] -- assoc list of all diff kinds of ticks
121 = UnfoldingDone | MagicUnfold | ConReused
122 | CaseFloatFromLet | CaseOfCase
123 | LetFloatFromLet | LetFloatFromCase
124 | KnownBranch | Let2Case
125 | CaseMerge | CaseElim
127 | AtomicRhs -- Rhs of a let-expression was an atom
132 {- BEGIN F/B ENTRIES -}
134 | FoldrBuild -- foldr f z (build g) ==>
135 | FoldrAugment -- foldr f z (augment g z) ==>
136 | Foldr_Nil -- foldr f z [] ==>
137 | Foldr_List -- foldr f z (x:...) ==>
139 | FoldlBuild -- foldl f z (build g) ==>
140 | FoldlAugment -- foldl f z (augment g z) ==>
141 | Foldl_Nil -- foldl f z [] ==>
142 | Foldl_List -- foldl f z (x:...) ==>
144 | Foldr_Cons_Nil -- foldr (:) [] => id
145 | Foldr_Cons -- foldr (:) => flip (++)
147 | Str_FoldrStr -- foldr f z "hello" => unpackFoldrPS# f z "hello"
148 | Str_UnpackCons -- unpackFoldrPS# (:) z "hello" => unpackAppendPS# z "hello"
149 | Str_UnpackNil -- unpackAppendPS# [] "hello" => "hello"
150 {- END F/B ENTRIES -}
151 deriving (Eq, Ord, Ix)
153 instance Text TickType where
154 showsPrec p UnfoldingDone = showString "UnfoldingDone "
155 showsPrec p MagicUnfold = showString "MagicUnfold "
156 showsPrec p ConReused = showString "ConReused "
157 showsPrec p CaseFloatFromLet= showString "CaseFloatFromLet "
158 showsPrec p CaseOfCase = showString "CaseOfCase "
159 showsPrec p LetFloatFromLet = showString "LetFloatFromLet "
160 showsPrec p LetFloatFromCase= showString "LetFloatFromCase "
161 showsPrec p KnownBranch = showString "KnownBranch "
162 showsPrec p Let2Case = showString "Let2Case "
163 showsPrec p CaseMerge = showString "CaseMerge "
164 showsPrec p CaseElim = showString "CaseElim "
165 showsPrec p CaseIdentity = showString "CaseIdentity "
166 showsPrec p AtomicRhs = showString "AtomicRhs "
167 showsPrec p EtaExpansion = showString "EtaExpansion "
168 showsPrec p CaseOfError = showString "CaseOfError "
169 showsPrec p TyBetaReduction = showString "TyBetaReduction "
170 showsPrec p BetaReduction = showString "BetaReduction "
171 -- Foldr/Build Stuff:
172 showsPrec p FoldrBuild = showString "FoldrBuild "
173 showsPrec p FoldrAugment = showString "FoldrAugment "
174 showsPrec p Foldr_Nil = showString "Foldr_Nil "
175 showsPrec p Foldr_List = showString "Foldr_List "
177 showsPrec p FoldlBuild = showString "FoldlBuild "
178 showsPrec p FoldlAugment = showString "FoldlAugment "
179 showsPrec p Foldl_Nil = showString "Foldl_Nil "
180 showsPrec p Foldl_List = showString "Foldl_List "
182 showsPrec p Foldr_Cons_Nil = showString "Foldr_Cons_Nil "
183 showsPrec p Foldr_Cons = showString "Foldr_Cons "
185 showsPrec p Str_FoldrStr = showString "Str_FoldrStr "
186 showsPrec p Str_UnpackCons = showString "Str_UnpackCons "
187 showsPrec p Str_UnpackNil = showString "Str_UnpackNil "
189 showSimplCount :: SimplCount -> String
191 showSimplCount (SimplCount _ stuff)
195 shw ((t,n):tns) | n /= 0 = show t ++ ('\t' : show n) ++ ('\n' : shw tns)
196 | otherwise = shw tns
198 zeroSimplCount :: SimplCount
201 [ (UnfoldingDone, 0),
204 (CaseFloatFromLet, 0),
206 (LetFloatFromLet, 0),
207 (LetFloatFromCase, 0),
218 -- Foldr/Build Stuff:
234 --= array (con2tag_TickType UnfoldingDone, con2tag_TickType FoldrInline)
235 -- [ i := 0 | i <- indices zeroSimplCount ]
238 Counting-related monad functions:
240 tick :: TickType -> SmplM ()
242 tick tick_type us (SimplCount n stuff)
243 = ((), SimplCount (n _ADD_ ILIT(1))
244 #ifdef OMIT_SIMPL_COUNTS
245 stuff -- don't change anything
251 inc_tick [] = panic "couldn't inc_tick!"
252 inc_tick (x@(ttype, cnt) : xs)
253 = if ttype == tick_type then
261 tickN :: TickType -> Int -> SmplM ()
263 tickN tick_type IBOX(increment) us (SimplCount n stuff)
264 = ((), SimplCount (n _ADD_ increment)
265 #ifdef OMIT_SIMPL_COUNTS
266 stuff -- don't change anything
272 inc_tick [] = panic "couldn't inc_tick!"
273 inc_tick (x@(ttype, cnt) : xs)
274 = if ttype == tick_type then
276 incd = cnt + IBOX(increment)
282 simplCount :: SmplM Int
283 simplCount us sc@(SimplCount n _) = (IBOX(n), sc)
285 detailedSimplCount :: SmplM SimplCount
286 detailedSimplCount us sc = (sc, sc)
288 combineSimplCounts :: SimplCount -> SimplCount -> SimplCount
290 #ifdef OMIT_SIMPL_COUNTS
291 combineSimplCounts (SimplCount n1 stuff1) (SimplCount n2 stuff2)
292 = SimplCount (n1 _ADD_ n2)
293 stuff1 -- just pick one
295 combineSimplCounts (SimplCount n1 stuff1) (SimplCount n2 stuff2)
296 = SimplCount (n1 _ADD_ n2)
297 (zipWithEqual (\ (t1,c1) (t2,c2) -> (t1,c1+c2)) stuff1 stuff2)
301 %************************************************************************
303 \subsection{Monad primitives}
305 %************************************************************************
308 newId :: Type -> SmplM Id
310 = (mkSysLocal SLIT("s") uniq ty mkUnknownSrcLoc, sc)
314 newIds :: [Type] -> SmplM [Id]
316 = (zipWithEqual mk_id tys uniqs, sc)
318 uniqs = getUniques (length tys) us
319 mk_id ty uniq = mkSysLocal SLIT("s") uniq ty mkUnknownSrcLoc
321 cloneTyVarSmpl :: TyVar -> SmplM TyVar
323 cloneTyVarSmpl tyvar us sc
327 new_tyvar = cloneTyVar tyvar uniq
329 cloneId :: SimplEnv -> InBinder -> SmplM OutId
330 cloneId env (id,_) us sc
331 = (mkIdWithNewUniq id_with_new_ty uniq, sc)
333 id_with_new_ty = simplTyInId env id
336 cloneIds :: SimplEnv -> [InBinder] -> SmplM [OutId]
337 cloneIds env binders = mapSmpl (cloneId env) binders