diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2021-04-15 15:20:26 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-04-26 23:56:53 -0400 |
commit | 6c7fff0b6f9514d6572cbe6bbfa4aafc259caebe (patch) | |
tree | befd67e0d63bef6c6aee6b318e4ef6e287a62797 /libraries | |
parent | 06654a6e0e4c1f9eb58947439092ae27b00d8c10 (diff) | |
download | haskell-6c7fff0b6f9514d6572cbe6bbfa4aafc259caebe.tar.gz |
Eliminate unsafeEqualityProof in CorePrep
The main idea here is to avoid treating
* case e of {}
* case unsafeEqualityProof of UnsafeRefl co -> blah
specially in CoreToStg. Instead, nail them in CorePrep,
by converting
case e of {}
==> e |> unsafe-co
case unsafeEqualityProof of UnsafeRefl cv -> blah
==> blah[unsafe-co/cv]
in GHC.Core.Prep. Now expressions that we want to treat as trivial
really are trivial. We can get rid of cpExprIsTrivial.
And we fix #19700.
A downside is that, at least under unsafeEqualityProof, we substitute
in types and coercions, which is more work. But a big advantage is
that it's all very simple and principled: CorePrep really gets rid of
the unsafeCoerce stuff, as it does empty case, runRW#, lazyId etc.
I've updated the overview in GHC.Core.Prep, and added
Note [Unsafe coercions] in GHC.Core.Prep
Note [Implementing unsafeCoerce] in base:Unsafe.Coerce
We get 3% fewer bytes allocated when compiling perf/compiler/T5631,
which uses a lot of unsafeCoerces. (It's a happy-generated parser.)
Metric Decrease:
T5631
Diffstat (limited to 'libraries')
-rw-r--r-- | libraries/base/Unsafe/Coerce.hs | 32 |
1 files changed, 9 insertions, 23 deletions
diff --git a/libraries/base/Unsafe/Coerce.hs b/libraries/base/Unsafe/Coerce.hs index 07d1f2da9f..5ebc9c637e 100644 --- a/libraries/base/Unsafe/Coerce.hs +++ b/libraries/base/Unsafe/Coerce.hs @@ -90,10 +90,10 @@ several ways (U1) unsafeEqualityProof is /never/ inlined. -(U2) In CoreToStg.coreToStg, we transform - case unsafeEqualityProof of UnsafeRefl -> blah +(U2) In CoreToStg.Prep, we transform + case unsafeEqualityProof of UnsafeRefl g -> blah ==> - blah + blah[unsafe-co/g] This eliminates the overhead of evaluating the unsafe equality proof. @@ -127,18 +127,15 @@ several ways and produce a thunk even after discarding the unsafeEqualityProof. So instead we float out the case to give case unsafeEqualityProof ... of { UnsafeRefl -> - let a = K e + let a = e x = K a - in ... - Flaoting the case is OK here, even though it broardens the + in ... } + Floating the case is OK here, even though it broadens the scope, because we are done with simplification. -(U4) GHC.CoreToStg.Prep.cpeExprIsTrivial anticipates the - upcoming discard of unsafeEqualityProof. - -(U4a) Ditto GHC.Core.Unfold.inlineBoringOk we want to treat - the RHS of unsafeCoerce as very small; see - Note [Inline unsafeCoerce] in that module. +(U4) Ditto GHC.Core.Unfold.inlineBoringOk we want to treat + the RHS of unsafeCoerce as very small; see + Note [Inline unsafeCoerce] in that module. (U5) The definition of unsafeEqualityProof in Unsafe.Coerce looks very strange: @@ -212,17 +209,6 @@ There are yet more wrinkles the kind-/homogeneous/ unsafeEqualityProof twice. See Note [Wiring in unsafeCoerce#] in Desugar. - -(U11) We must also be careful to discard unsafeEqualityProof in the - bytecode generator; see ByteCodeGen.bcView. Here we don't really - care about fast execution, but (annoyingly) we /do/ care about the - GHCi debugger, and GHCi itself uses unsafeCoerce. - - Moreover, in GHC.Tc.Module.tcGhciStmts we use unsafeCoerce#, rather - than the more kosher unsafeCoerce, because (with -O0) the latter - may not be inlined. - - Sigh -} -- | This type is treated magically within GHC. Any pattern match of the |