#4978: Continuation passing style loop doesn't compile into a loop
---------------------------------+------------------------------------------
Reporter: tibbe | Owner:
Type: bug | Status: new
Priority: normal | Milestone: 7.4.1
Component: Compiler | Version: 7.0.1
Keywords: | Testcase:
Blockedby: | Difficulty:
Os: Unknown/Multiple | Blocking:
Architecture: Unknown/Multiple | Failure: None/Unknown
---------------------------------+------------------------------------------
Comment(by tibbe):
With $weta inlined the code looks good enough; There's no longer any
allocation in the common case i.e. when there's still space in the write
buffer. Hopefully that also means there isn't a heap check in the common
path.
It seems to me that at least some primops should look really cheap, like
memory writes and reads, which only require a few instruction. Looking at
`primOpIsCheap` (which simply calls `primOpOkForSpeculation`) we don't
consider `writeWord8OffAddr#` cheap as it has side effects.
If `primOpIsCheap` would pattern match on the actual primop and return
`True` or `False` on a case-by-case basis, we could make
`writeWord8OffAddr#` look cheap. Shouldn't calls to out-of-line primops
(like `newPinnedByteArray#`) also look cheap, as the primop itself will
never be inlined?
The ''optimal'' Core for `$wa` would look something like:
{{{
$wa =
\ (xs :: [Word8])
(k :: Buffer -> [ByteString])
(addr :: Addr#)
(fp :: ForeignPtrContents)
(o :: Int#)
(u :: Int#)
(l :: Int#) ->
case xs of ys {
[] -> k (Buffer addr fp o u l);
: x xs1_awV ->
case <=# 1 l of _ {
False ->
case u of wild2_X18 {
__DEFAULT ->
: (PS addr fp o wild2_X18)
(case newPinnedByteArray# 32752 realWorld#
of _ { (# _, mbarr#_a10k #) ->
let { a2_s10s = byteArrayContents# (mbarr#_a10k `cast`
...) } in
let { fp' = PlainPtr mbarr#_a10k } in
case touch# fp' realWorld# of _ { __DEFAULT ->
$wa ys k a2_s10s fp' 0 0 32752
}
});
0 ->
case newPinnedByteArray# 32752 realWorld#
of _ { (# _, mbarr#_a10k #) ->
let { a2_s10w = byteArrayContents# (mbarr#_a10k `cast`
...) } in
let { fp' = PlainPtr mbarr#_a10k } in
case touch# fp' realWorld# of _ { __DEFAULT ->
$wa ys k a2_s10w fp' 0 0 32752
}
}
};
True ->
case x of _ { W8# x# ->
case writeWord8OffAddr#
(plusAddr# addr (+# o u)) 0 x# realWorld#
of s2_aYX { __DEFAULT ->
case touch# fp s2_aYX of _ { __DEFAULT ->
$wa
xs1_awV
k
addr
fp
o
(+# u 1)
(-# l 1)
}
}
}
}
}
}}}
I'm not sure it's possible to get there as the code transformations I
applied manually are non-obvious (i.e. I shared the call to
`writeWord8OffAddr#` between all three branches).
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/4978#comment:17>
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