summaryrefslogtreecommitdiff
path: root/libraries
diff options
context:
space:
mode:
authorSimon Peyton Jones <simonpj@microsoft.com>2021-04-15 15:20:26 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-04-26 23:56:53 -0400
commit6c7fff0b6f9514d6572cbe6bbfa4aafc259caebe (patch)
treebefd67e0d63bef6c6aee6b318e4ef6e287a62797 /libraries
parent06654a6e0e4c1f9eb58947439092ae27b00d8c10 (diff)
downloadhaskell-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.hs32
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