[commit: ghc] master: Fix a long-standing bug in CSE (d03dd23)
git at git.haskell.org
git at git.haskell.org
Mon Dec 12 16:39:01 UTC 2016
Repository : ssh://git@git.haskell.org/ghc
On branch : master
Link : http://ghc.haskell.org/trac/ghc/changeset/d03dd23744799f7df1a73df26d7833887d8e97e9/ghc
>---------------------------------------------------------------
commit d03dd23744799f7df1a73df26d7833887d8e97e9
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date: Thu Dec 8 23:59:47 2016 +0000
Fix a long-standing bug in CSE
I had the environments wrong so that CSE could mis-clone
an expression, if the uniques just happened to be badly
arranged. It's hard to trigger the bug, so I can't make
a reliable test case.
Happily the fix is easy.
>---------------------------------------------------------------
d03dd23744799f7df1a73df26d7833887d8e97e9
compiler/simplCore/CSE.hs | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/compiler/simplCore/CSE.hs b/compiler/simplCore/CSE.hs
index f119f9f..039da8e 100644
--- a/compiler/simplCore/CSE.hs
+++ b/compiler/simplCore/CSE.hs
@@ -240,26 +240,34 @@ cseProgram binds = snd (mapAccumL cseBind emptyCSEnv binds)
cseBind :: CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind env (NonRec b e)
- = (env2, NonRec b'' e')
+ = (env2, NonRec b2 e2)
where
- (env1, b') = addBinder env b
- (env2, (b'', e')) = cseRhs env1 b b' e
+ e1 = tryForCSE env e
+ (env1, b1) = addBinder env b
+ (env2, (b2, e2)) = addBinding env1 b b1 e1
cseBind env (Rec pairs)
= (env2, Rec pairs')
where
- (env1, bs') = addRecBinders env (map fst pairs)
- (env2, pairs') = mapAccumL cse_rhs env1 (bs' `zip` pairs)
- cse_rhs env (b', (b,e)) = cseRhs env b b' e
-
-cseRhs :: CSEnv -> InId -> OutId -> InExpr -> (CSEnv, (OutId, OutExpr))
-cseRhs env in_id out_id rhs
+ (bndrs, rhss) = unzip pairs
+ (env1, bndrs1) = addRecBinders env bndrs
+ rhss1 = map (tryForCSE env1) rhss
+ -- Process rhss in extended env1
+ (env2, pairs') = mapAccumL cse_rhs env1 (zip3 bndrs bndrs1 rhss1)
+ cse_rhs env (b, b1, e1) = addBinding env b b1 e1
+
+addBinding :: CSEnv -- Includes InId->OutId cloning
+ -> InId
+ -> OutId -> OutExpr -- Processed binding
+ -> (CSEnv, (OutId, OutExpr)) -- Final env and binding
+-- Extend the CSE env with a mapping [rhs -> out-id]
+-- unless we can instead just substitute [in-id -> rhs]
+addBinding env in_id out_id rhs'
| no_cse = (env, (out_id, rhs'))
| ok_to_subst = (extendCSSubst env in_id rhs', (out_id, rhs'))
| otherwise = (extendCSEnv env rhs' id_expr', (zapped_id, rhs'))
where
id_expr' = varToCoreExpr out_id
- rhs' = tryForCSE env rhs
zapped_id = zapIdUsageInfo out_id
-- Putting the Id into the cs_map makes it possible that
-- it'll become shared more than it is now, which would
@@ -316,15 +324,17 @@ cseExpr env (Case e bndr ty alts) = cseCase env e bndr ty alts
cseCase :: CSEnv -> InExpr -> InId -> InType -> [InAlt] -> OutExpr
cseCase env scrut bndr ty alts
- = Case scrut' bndr3 ty (map cse_alt alts)
+ = Case scrut2 bndr3 ty (map cse_alt alts)
where
+ scrut1 = tryForCSE env scrut
+
bndr1 = zapIdOccInfo bndr
-- Zapping the OccInfo is needed because the extendCSEnv
-- in cse_alt may mean that a dead case binder
-- becomes alive, and Lint rejects that
(env1, bndr2) = addBinder env bndr1
- (alt_env, (bndr3, scrut')) = cseRhs env1 bndr bndr2 scrut
- -- cseRhs: see Note [CSE for case expressions]
+ (alt_env, (bndr3, scrut2)) = addBinding env1 bndr bndr2 scrut1
+ -- addBinding: see Note [CSE for case expressions]
con_target :: OutExpr
con_target = lookupSubst alt_env bndr
More information about the ghc-commits
mailing list