[GHC] #7360: Case-of-identical-alts optimisation fails abjectly
GHC
cvs-ghc at haskell.org
Tue Oct 23 00:12:41 CEST 2012
#7360: Case-of-identical-alts optimisation fails abjectly
---------------------------------+------------------------------------------
Reporter: simonpj | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.6.1
Keywords: | Os: Unknown/Multiple
Architecture: Unknown/Multiple | Failure: None/Unknown
Difficulty: Unknown | Testcase:
Blockedby: | Blocking:
Related: |
---------------------------------+------------------------------------------
Herbert Valerio Riedel writes: I've been trying to improve/fix a minor
optimization sub-optimality w.r.t to the following code (code like that
results from the generics-based NFData deriver[1]):
{{{
data Foo = Foo1 | Foo2 | Foo3 !Int
rnf1 :: Foo -> ()
rnf1 x = case x of
Foo1 -> ()
Foo2 -> ()
Foo3 {} -> ()
}}}
which the current GHC 7.6.1 translates to the following core
expression:
{{{
NFDataTest2.rnf1 =
\ x_aeG ->
case x_aeG of _ {
__DEFAULT -> GHC.Tuple.();
NFDataTest2.Foo3 ds_deT -> GHC.Tuple.()
}
}}}
...whereas I'd have expected it to to compile it to a collapsed
`__DEFAULT`-only case, i.e.
{{{
NFDataTest2.rnf1 =
\ x_aeG -> case x_aeG of _ { __DEFAULT -> GHC.Tuple.() }
}}}
Now I've been hunting it down to the function `SimplUtils.mkCase1` [2],
which according to the source-code comments, is supposed to merge
identical alternatives, i.e.:
{{{
| 3. Merge identical alternatives.
| If several alternatives are identical, merge them into
| a single DEFAULT alternative. I've occasionally seen this
| making a big difference:
|
| case e of =====> case e of
| C _ -> f x D v -> ....v....
| D v -> ....v.... DEFAULT -> f x
| DEFAULT -> f x
}}}
...and the `mkCase1` function itself reads as follows:
{{{
mkCase1 dflags scrut case_bndr alts_ty ((_con1,bndrs1,rhs1) :
con_alts)
| all isDeadBinder bndrs1 -- Remember the
default
, length filtered_alts < length con_alts -- alternative comes
first
-- Also Note [Dead binders]
= do { tick (AltMerge case_bndr)
; mkCase2 dflags scrut case_bndr alts_ty alts' }
where
alts' = (DEFAULT, [], rhs1) : filtered_alts
filtered_alts = filter keep con_alts
keep (_con,bndrs,rhs) = not (all isDeadBinder bndrs && rhs
`cheapEqExpr` rhs1)
}}}
Now the problem seems to be, that `isDeadBinder` returns `False`; so I
hacked up `mkCase1` and inserted a `occurAnalyseExpr` on artificially
constructed single-alternative 'Case' values before applying
`isDeadBinder`, and then it would return `True` and simplify the case
expression as expected.
So now my question is, why isn't the occurrence information available for
the case-alternative's binders (the occInfo is set to `NoOccInfo`) at
`mkCase1`-time? When is occurence analysis performed relative to the
simplifier?
* [1]: [http://hackage.haskell.org/package/deepseq-generics]
* [2]:
[http://www.haskell.org/ghc/docs/7.6.1/html/libraries/ghc-7.6.1/src/SimplUtils.html#mkCase1]
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7360>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list