2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section{Common subexpression}
11 #include "HsVersions.h"
13 import CmdLineOpts ( opt_D_dump_cse, opt_D_verbose_core2core )
14 import Id ( Id, idType )
15 import CoreUtils ( hashExpr, cheapEqExpr, exprIsBig )
16 import Const ( Con(..) )
17 import DataCon ( isUnboxedTupleCon )
18 import Type ( splitTyConApp_maybe )
21 import CoreLint ( beginPass, endPass )
23 import Util ( mapAccumL )
28 Simple common sub-expression
33 we build up a reverse mapping: C a b -> x1
35 and apply that to the rest of the program.
40 we replace the C a b with x1. But then we *dont* want to
41 add x1 -> y to the mapping. Rather, we want the reverse, y -> x1
42 so that a subsequent binding
44 will get transformed to C x1 b, and then to x2.
46 So we carry an extra var->var mapping which we apply before looking up in the
52 This pass relies on the no-shadowing invariant, so it must run
53 immediately after the simplifier.
56 f = \x -> let y = x+x in
60 Here we must *not* do CSE on the x+x!
63 %************************************************************************
65 \section{Common subexpression}
67 %************************************************************************
70 cseProgram :: [CoreBind] -> IO [CoreBind]
74 beginPass "Common sub-expression";
75 let { binds' = cseBinds emptyCSEnv binds };
76 endPass "Common sub-expression"
77 (opt_D_dump_cse || opt_D_verbose_core2core)
81 cseBinds :: CSEnv -> [CoreBind] -> [CoreBind]
83 cseBinds env (b:bs) = (b':bs')
85 (env1, b') = cseBind env b
86 bs' = cseBinds env1 bs
88 cseBind :: CSEnv -> CoreBind -> (CSEnv, CoreBind)
89 cseBind env (NonRec b e) = let (env', (_,e')) = do_one env (b, e)
90 in (env', NonRec b e')
91 cseBind env (Rec pairs) = let (env', pairs') = mapAccumL do_one env pairs
95 do_one env (id, rhs) = case lookupCSEnv env rhs' of
96 Just other_id -> (extendSubst env id other_id, (id, Var other_id))
97 Nothing -> (addCSEnvItem env id rhs', (id, rhs'))
99 rhs' = cseExpr env rhs
102 tryForCSE :: CSEnv -> CoreExpr -> CoreExpr
103 tryForCSE env (Type t) = Type t
104 tryForCSE env expr = case lookupCSEnv env expr' of
108 expr' = cseExpr env expr
111 cseExpr :: CSEnv -> CoreExpr -> CoreExpr
112 cseExpr env (Var v) = Var (lookupSubst env v)
113 cseExpr env (App f (Type t)) = App (cseExpr env f) (Type t)
114 cseExpr env (App f a) = App (cseExpr env f) (tryForCSE env a)
115 cseExpr env expr@(Con con args) = case lookupCSEnv env expr of
117 Nothing -> Con con [tryForCSE env arg | arg <- args]
118 cseExpr env (Note n e) = Note n (cseExpr env e)
119 cseExpr env (Lam b e) = Lam b (cseExpr env e)
120 cseExpr env (Let bind e) = let (env1, bind') = cseBind env bind
121 in Let bind' (cseExpr env1 e)
122 cseExpr env (Type t) = Type t
123 cseExpr env (Case scrut bndr alts) = Case (tryForCSE env scrut) bndr (cseAlts env bndr alts)
126 cseAlts env bndr alts
129 arg_tys = case splitTyConApp_maybe (idType bndr) of
130 Just (_, arg_tys) -> map Type arg_tys
131 other -> pprPanic "cseAlts" (ppr bndr)
133 cse_alt (con, args, rhs)
134 | ok_for_cse con = (con, args, cseExpr (extendCSEnv env bndr (Con con (arg_tys ++ (map varToCoreExpr args)))) rhs)
135 | otherwise = (con, args, cseExpr env rhs)
137 ok_for_cse DEFAULT = False
138 ok_for_cse (Literal l) = True
139 ok_for_cse (DataCon dc) = not (isUnboxedTupleCon dc)
140 -- Unboxed tuples aren't shared
144 %************************************************************************
146 \section{The CSE envt}
148 %************************************************************************
151 data CSEnv = CS (UniqFM [(Id, CoreExpr)]) -- The expr in the range has already been CSE'd
152 (IdEnv Id) -- Simple substitution
154 emptyCSEnv = CS emptyUFM emptyVarEnv
156 lookupCSEnv :: CSEnv -> CoreExpr -> Maybe Id
157 lookupCSEnv (CS cs _) expr
158 = case lookupUFM cs (hashExpr expr) of
160 Just pairs -> lookup_list pairs expr
162 lookup_list :: [(Id,CoreExpr)] -> CoreExpr -> Maybe Id
163 lookup_list [] expr = Nothing
164 lookup_list ((x,e):es) expr | cheapEqExpr e expr = Just x
165 | otherwise = lookup_list es expr
167 addCSEnvItem env id expr | exprIsBig expr = env
168 | otherwise = extendCSEnv env id expr
170 extendCSEnv (CS cs sub) id expr
171 = CS (addToUFM_C combine cs hash [(id, expr)]) sub
174 combine old new = WARN( length result > 4, text "extendCSEnv: long list:" <+> ppr result )
179 lookupSubst (CS _ sub) x = case lookupVarEnv sub x of
183 extendSubst (CS cs sub) x y = CS cs (extendVarEnv sub x y)