Do CSE after CorePrep
Common sub-expression analysis is deliberately conservative, but it's really too conservative: we are missing obvious opportunities. Consider
{-# OPTIONS_GHC -XBangPatterns -XMagicHash #-}
module Foo where
import GHC.Base
-- CorePrep evaluates (reverse xs) twice
f xs = let !v1 = reverse (reverse xs)
!v2 = filter id (reverse xs)
in (v1, v2)
-- Even CSE inside CorePrep would not get this right;
-- the strict evaluation of (reverse xs) doesn't scope
-- over the non-strict version
g xs = reverse (reverse xs) ++ filter id (reverse xs)
-- Duplicate evaluation of (x +# 1#)
h :: Int# -> ( Int, Int )
h x = ( I# (x +# 1#), I# ((x +# 1#) *# 2#) )
If you compile this you'll see that there are obvious missed CSE opportunities in f
, g
and h
; but they only show up after CorePrep
.
I guess the right thing is to CSE after CorePrep
, but then CSE would have to maintain the CorePrep
invariants, which isn't trivial. Something to think about.
Simon
Trac metadata
Trac field | Value |
---|---|
Version | 6.10.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |