Roman I pushed a patch that tidies this up a lot. Not absolutely perfect, but a useful improvement I think. Thanks for raising it.
Sat Sep 20 18:52:38 GMT Daylight Time 2008 [EMAIL PROTECTED] * Tidy up the treatment of dead binders Simon | -----Original Message----- | From: Simon Peyton-Jones | Sent: 15 September 2008 08:47 | To: Roman Leshchinskiy | Cc: Manuel Chakravarty; Simon Peyton-Jones | Subject: RE: mkWildId | | Yes, that's an excellent point. I think I originally intended mkWildId to be | used only where I knew just what the case alternatives were, and they did not | use the wild-id. But then perhaps usage has slipped over time. | | I can think of several possibilities | | - Always use a fresh unique. This is quite inconvenient, because it'd add a | usually-unused Unique argument to lots of MkCore functions | | - Make sure that the simplifier always freshens the unique. We can do this | easily by pretending that the wild-id is always in scope (so that any | binding will be freshened). We can do that by making emptyInScopeSet | contain the unique 1. | | - Have a new kind of Id that does not create a binding. A real "_" Id. | I have no idea of the consequences of this, so I'm not inclined to | do it yet. | | That's all I can think of right now, alas. We could add ASSERTs to the | places where the potentially-shadowing occurrences happen (there are no so | many). Meanwhile in the vectoriser you have lots of Cases with mkWildIds -- | you could just use a fresh varaible in all of those. | | Simon | | | -----Original Message----- | | From: Roman Leshchinskiy [mailto:[EMAIL PROTECTED] | | Sent: 15 September 2008 05:03 | | To: Simon Peyton-Jones | | Cc: Manuel Chakravarty | | Subject: mkWildId | | | | Simon, | | | | I've found a problem with the vectoriser but I'm not entirely sure if | | it's really a bug although I suspect so. First, consider this code: | | | | data T a = T a a | | | | foo :: Int -> T a -> a | | foo n t@(T x y) | n == 0 = x | | | otherwise = bar t | | | | The gentle phase transforms this to: | | | | T.foo = | | \ (@ a_afA) (n_afh :: GHC.Types.Int) (t_afj :: T.T a_afA) -> | | case t_afj of wild_B1 { T.T x_afl y_afn -> | | case GHC.Classes.== | | @ GHC.Types.Int GHC.Base.$f2 n_afh (GHC.Types.I# 0) | | of wild_Xh [ALWAYS Dead Nothing] { | | GHC.Bool.False -> T.bar @ a_afA wild_B1; GHC.Bool.True -> x_afl | | } | | } | | | | Note that wild_B1 (the result of mkWildId) is referenced in the call | | to bar. Now, the vectoriser will sometimes insert (Case ... (mkWildId | | ty) ...) between the binding and the use of wild_B1 which is, of | | course, completely wrong. This is easily fixed by not using mkWildId | | here, but that makes me wonder. For instance, in CoreUtils we have: | | | | mkIfThenElse :: CoreExpr -> CoreExpr -> CoreExpr -> CoreExpr | | mkIfThenElse guard then_expr else_expr | | -- Not going to be refining, so okay to take the type of the "then" | | clause | | = Case guard (mkWildId boolTy) (exprType then_expr) | | [ (DataAlt falseDataCon, [], else_expr), -- Increasing order | of tag! | | (DataAlt trueDataCon, [], then_expr) ] | | | | This only works if the WildId isn't free in then_expr and else_expr. | | That seems awfully fragile. Do you have any thoughts on this? | | | | Roman | | | | _______________________________________________ Cvs-ghc mailing list [email protected] http://www.haskell.org/mailman/listinfo/cvs-ghc
