#2422: Unrelated instance foils optimizer
--------------------------+-------------------------------------------------
Reporter: sedillard | Owner:
Type: bug | Status: new
Priority: normal | Milestone: 6.10 branch
Component: Compiler | Version: 6.8.3
Severity: normal | Resolution:
Keywords: | Difficulty: Unknown
Testcase: | Os: Linux
Architecture: x86 |
--------------------------+-------------------------------------------------
Comment (by simonpj):
Good example! This is indeed what is making #2416 go bad, but it's much
easier to see here.
I've unraveled what's happening; just recording it here so I don't forget
again. These remarks are mainly for me, so they may seem a bit cryptic.
From the instance for `(Storable (a:.a:.v))` we get something like
{{{
Rec {
$f3 = \d. MkStorable ...(pbo d)...
pbo = \d. let pbo1 = peekByteOff ($f3 d) in \p q r. blah
end Rec }
}}}
where `peekByteOff` is the method selector from the `Storable` class.
(See `Note [How instance declarations are translated]` in `TcInstDcls` for
the overall game plan.) Then the simplifier inlines `$f3`, thereby
breaking the recursion, to give
{{{
pbo = \d. let ...d... in \p q r. blah
$f3 = \d. MkStorable ...(pbo d)...
}}}
Now, when you add the "unrelated" instance, the specialiser kicks in, and
makes a specialised version of both functions:
{{{
$spbo = \p q r. blah blah blah
$sf3 = MkStorable ...$spbo...
}}}
We've specialised for a particular dictionary `d`, and that means we can
inline the specialised methods into `$spbo`. Alas, that makes `$spbo`
big, so now it does not inline into the users of `$sf3`. Before, it did.
In effect the unspecialised version looked a lot smaller than the
specialised version.
But what about the INLINE pragma, you say? Well, it's hard to make it
work right. If it attaches to the whole `pbo` we'd get
{{{
Rec {
$f3 = \d. MkStorable ...(pbo d)...
pbo = __inline_me__ (\d. let pbo1 = peekByteOff ($f3 d) in \p q r. blah)
end Rec }
}}}
But (for good reasons) we don't inline inside `__inline_me__`, so we won't
get to break the recursive loop with `$f3`, which is terrible. GHC 6.10
currently pins the pragma on the body thus:
{{{
Rec {
$f3 = \d. MkStorable ...(pbo d)...
pbo = \d. let pbo1 = peekByteOff ($f3 d) in
__inline_me__ (\p q r. blah)
end Rec }
}}}
but this does not work right either (because eta expansion loses that
`__inline_me__`).
I think the new inlining mechanism will help a lot, but I need to get it
installed first. Stay tuned.
Simon
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2422#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs