2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 \section[Core2Def]{Translate the CoreProgram into a DefProgram}
6 >#include "HsVersions.h"
11 > PlainCoreProgram(..), DefProgram(..),
12 > CoreBinding, Id, DefBindee ) where
23 > import BinderInfo -- ( BinderInfo(..), isFun, isDupDanger )
24 > import CmdLineOpts ( switchIsOn, SwitchResult, SimplifierSwitch )
25 > import OccurAnal ( occurAnalyseBinds )
26 > import SimplEnv ( SwitchChecker(..) )
31 This module translates the PlainCoreProgram into a DefCoreProgram,
32 which includes non-atomic right-hand sides. The decisions about which
33 expressions to inline are left to the substitution analyser, which we
38 1. Inline all non-recursive non-top-level lets that occur only
39 once (including inside lambdas, hoping full laziness
40 will sort things out later).
42 2. We don't inline top-level lets that occur only once, because these
43 might not be pulled out again by the let-floater, due to non-
44 garbage collection of CAFs.
46 2.1. Also, what about these lit things that occur at the top level,
47 and are usually marked as macros?
49 3. No recusrive functions are unfolded.
52 4. Lambdas and case alternatives that bind a variable that occurs
53 multiple times are transformed:
54 \x -> ..x..x.. ===> \x -> let x' = x in ..x'..x'..
57 > core2def :: (GlobalSwitch -> SwitchResult) -> PlainCoreProgram -> DefProgram
59 > map coreBinding2def tagged_program
61 > tagged_program = occurAnalyseBinds prog switch_is_on (const False)
62 > switch_is_on = switchIsOn sw
65 > coreBinding2def :: SimplifiableCoreBinding -> DefBinding
66 > coreBinding2def (CoNonRec (v,_) e) = CoNonRec v (c2d nullIdEnv e)
67 > coreBinding2def (CoRec bs) = CoRec (map recBind2def bs)
68 > where recBind2def ((v,_),e) = (v, c2d nullIdEnv e)
71 > coreAtom2def :: IdEnv DefExpr -> PlainCoreAtom -> DefAtom
72 > coreAtom2def p (CoVarAtom v) = CoVarAtom (DefArgExpr (lookup p v))
73 > coreAtom2def p (CoLitAtom l) = CoVarAtom (DefArgExpr (CoLit l))
75 > isTrivial (CoCon c [] []) = True
76 > isTrivial (CoVar v) = True
77 > isTrivial (CoLit l) = True
80 > c2d :: IdEnv DefExpr -> SimplifiableCoreExpr -> DefExpr
83 > CoVar v -> lookup p v
87 > CoCon c ts es -> CoCon c ts (map (coreAtom2def p) es)
89 > CoPrim op ts es -> CoPrim op ts (map (coreAtom2def p) es)
91 > CoLam vs e -> CoLam (map fst vs) (c2d p e)
93 > CoTyLam alpha e -> CoTyLam alpha (c2d p e)
95 > CoApp e v -> CoApp (c2d p e) (coreAtom2def p v)
97 > CoTyApp e t -> CoTyApp (c2d p e) t
99 > CoCase e ps -> CoCase (c2d p e) (coreCaseAlts2def p ps)
101 > CoLet (CoNonRec (v,ManyOcc _) e) e'
102 > | isTrivial e -> c2d (addOneToIdEnv p v (c2d p e)) e'
104 > trace ("Not inlining ManyOcc " ++ ppShow 80 (ppr PprDebug v)) (
105 > CoLet (CoNonRec v (c2d p e)) (c2d p e'))
107 > CoLet (CoNonRec (v,DeadCode) e) e' ->
108 > panic "Core2Def(c2d): oops, unexpected DeadCode"
110 > CoLet (CoNonRec (v,OneOcc fun_or_arg dup_danger _ _ _) e) e'
111 > | isTrivial e -> inline_it
112 > | isDupDanger dup_danger ->
113 > trace ("Not inlining DupDanger " ++ ppShow 80 (ppr PprDebug v))(
114 > CoLet (CoNonRec v (c2d p e)) (c2d p e'))
115 > | isFun fun_or_arg ->
116 > panic "Core2Def(c2d): oops, unexpected Macro"
117 > | otherwise -> inline_it
118 > where inline_it = c2d (addOneToIdEnv p v (c2d p e)) e'
120 > CoLet (CoRec bs) e -> CoLet (CoRec (map recBind2def bs)) (c2d p e)
121 > where recBind2def ((v,_),e) = (v, c2d p e)
123 > CoSCC l e -> CoSCC l (c2d p e)
128 > -> SimplifiableCoreCaseAlternatives
129 > -> DefCaseAlternatives
131 > coreCaseAlts2def p alts = case alts of
132 > CoAlgAlts as def -> CoAlgAlts (map algAlt2def as) (defAlt2def def)
133 > CoPrimAlts as def -> CoPrimAlts (map primAlt2def as) (defAlt2def def)
137 > algAlt2def (c, vs, e) = (c, (map fst vs), c2d p e)
138 > primAlt2def (l, e) = (l, c2d p e)
140 > defAlt2def CoNoDefault = CoNoDefault
141 > defAlt2def (CoBindDefault (v,_) e) = CoBindDefault v (c2d p e)
144 > lookup :: IdEnv DefExpr -> Id -> DefExpr
145 > lookup p v = case lookupIdEnv p v of
146 > Nothing -> CoVar (DefArgVar v)