Floating of unsafeEqualityProof
In #19539 (closed) Ben discovered that an unsafeEqualityProof
call was impeding optimisation. This ticket is to track that problem.
Ben saw this:
mapAccumL
= ...
case GHC.Prim.newPinnedByteArray# @GHC.Prim.RealWorld dt2 s of
{ (# ipv [Occ=Once1], ipv1 #) ->
let {
ipv2 :: ForeignPtr Word8
[LclId]
ipv2
= case Unsafe.Coerce.unsafeEqualityProof
@(TYPE 'GHC.Types.UnliftedRep)
@(GHC.Prim.MutableByteArray# GHC.Prim.RealWorld)
@GHC.Prim.ByteArray#
of
{ Unsafe.Coerce.UnsafeRefl co ->
GHC.ForeignPtr.ForeignPtr
@Word8
(GHC.Prim.byteArrayContents# (ipv1 `cast` ...))
(GHC.ForeignPtr.PlainPtr ipv1)
}
} in
So any case ipv2 of ForeignPtr x y -> blah
in the body of that let
aren't going to optimise as they should.
We have to be careful about floating unsafeEqualityProof
outwards -- see Note [Implementing unsafeCoerce]
in base:Unsafe.Coerce
.
Rather, I think we want to float it inwards so we get
ipv2 = ForeignPtr (byteArrayContents# (case unsafeEqualityProof of UnsafeRefl co -> ipv1 `cast` co)) (PlainPtr ipv1)
This is not entirely straightforward; see Note [Floating primops]
in GHC.Core.Opt.FloatIn. But it should be entirely do-able, by treating usafeEqualityProof
as magical, as we already do in GHC.Core.Unfold.inlineBoringOk
.
I'm not sure how urgent this ticket is. Obviously it affects only programs that do unsafeCoerce#
. But they tend to be performance-hungry programs...