summaryrefslogtreecommitdiff
path: root/compiler/specialise
diff options
context:
space:
mode:
authorsimonpj@microsoft.com <unknown>2009-01-13 16:29:18 +0000
committersimonpj@microsoft.com <unknown>2009-01-13 16:29:18 +0000
commit120c4c72d6b12e765da9e69612351a53fb7cef4b (patch)
treef60990d4edc0353864c190c8696b3b521fe05cb2 /compiler/specialise
parentb74af13a63693dd13bff5f3b66223ac977fbcc73 (diff)
downloadhaskell-120c4c72d6b12e765da9e69612351a53fb7cef4b.tar.gz
Do not do SpecConstr on functions that unconditionally diverge
There is no point in specialising a function that is guaranteed to diverge, and doing so screwed up arity stuff. See Note [Do not specialise diverging functions].
Diffstat (limited to 'compiler/specialise')
-rw-r--r--compiler/specialise/SpecConstr.lhs18
1 files changed, 16 insertions, 2 deletions
diff --git a/compiler/specialise/SpecConstr.lhs b/compiler/specialise/SpecConstr.lhs
index 23127f440f..3dfda94ca3 100644
--- a/compiler/specialise/SpecConstr.lhs
+++ b/compiler/specialise/SpecConstr.lhs
@@ -365,6 +365,19 @@ specialising the loops arising from stream fusion, for example in NDP where
we were getting literally hundreds of (mostly unused) specialisations of
a local function.
+Note [Do not specialise diverging functions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Specialising a function that just diverges is a waste of code.
+Furthermore, it broke GHC (simpl014) thus:
+ {-# STR Sb #-}
+ f = \x. case x of (a,b) -> f x
+If we specialise f we get
+ f = \x. case x of (a,b) -> fspec a b
+But fspec doesn't have decent strictnes info. As it happened,
+(f x) :: IO t, so the state hack applied and we eta expanded fspec,
+and hence f. But now f's strictness is less than its arity, which
+breaks an invariant.
+
-----------------------------------------------------
Stuff not yet handled
-----------------------------------------------------
@@ -1006,8 +1019,9 @@ specialise
specialise env bind_calls (fn, arg_bndrs, body, arg_occs)
spec_info@(SI specs spec_count mb_unspec)
- | notNull arg_bndrs, -- Only specialise functions
- Just all_calls <- lookupVarEnv bind_calls fn
+ | not (isBottomingId fn) -- Note [Do not specialise diverging functions]
+ , notNull arg_bndrs -- Only specialise functions
+ , Just all_calls <- lookupVarEnv bind_calls fn
= do { (boring_call, pats) <- callsToPats env specs arg_occs all_calls
-- ; pprTrace "specialise" (vcat [ppr fn <+> ppr arg_occs,
-- text "calls" <+> ppr all_calls,