diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2017-10-02 15:25:02 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2017-10-03 09:52:39 +0100 |
commit | dbbee1bacef1a8accc630908c31cf267a3cb98a9 (patch) | |
tree | 8ad36f1ed3b80f4bdd9a081aa6cb2fd201eb8a8e /compiler/stranal | |
parent | b1e0c65a1302f998917e6d33d6e1ebb84cd09fa8 (diff) | |
download | haskell-dbbee1bacef1a8accc630908c31cf267a3cb98a9.tar.gz |
Fix nasty bug in w/w for absence analysis
This dark corner was exposed by Trac #14285. It involves the
interaction between absence analysis and INLINABLE pragmas.
There is a full explanation in Note [aBSENT_ERROR_ID] in MkCore,
which you can read there. The changes in this patch are
* Make exprIsHNF return True for absentError, treating
absentError like an honorary data constructor.
* Make absentError /not/ be diverging, unlike other error Ids.
This is all a bit horrible.
* While doing this I found that exprOkForSpeculation didn't
have a case for value lambdas so I added one. It's not
really called on lifted types much, but it seems like the
right thing
Diffstat (limited to 'compiler/stranal')
-rw-r--r-- | compiler/stranal/WwLib.hs | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/compiler/stranal/WwLib.hs b/compiler/stranal/WwLib.hs index 474743a955..9d957c4251 100644 --- a/compiler/stranal/WwLib.hs +++ b/compiler/stranal/WwLib.hs @@ -21,11 +21,12 @@ import Id import IdInfo ( JoinArity, vanillaIdInfo ) import DataCon import Demand -import MkCore ( mkRuntimeErrorApp, aBSENT_ERROR_ID, mkCoreUbxTup +import MkCore ( mkAbsentErrorApp, mkCoreUbxTup , mkCoreApp, mkCoreLet ) import MkId ( voidArgId, voidPrimId ) -import TysPrim ( voidPrimTy ) import TysWiredIn ( tupleDataCon ) +import TysPrim ( voidPrimTy ) +import Literal ( absentLiteralOf ) import VarEnv ( mkInScopeSet ) import VarSet ( VarSet ) import Type @@ -33,7 +34,6 @@ import RepType ( isVoidTy ) import Coercion import FamInstEnv import BasicTypes ( Boxity(..) ) -import Literal ( absentLiteralOf ) import TyCon import UniqSupply import Unique @@ -895,15 +895,24 @@ example, Trac #4306. For these we find a suitable literal, using Literal.absentLiteralOf. We don't have literals for every primitive type, so the function is partial. - [I did try the experiment of using an error thunk for unlifted - things too, relying on the simplifier to drop it as dead code, - by making absentError - (a) *not* be a bottoming Id, - (b) be "ok for speculation" - But that relies on the simplifier finding that it really - is dead code, which is fragile, and indeed failed when - profiling is on, which disables various optimisations. So - using a literal will do.] +Note: I did try the experiment of using an error thunk for unlifted +things too, relying on the simplifier to drop it as dead code. +But this is fragile + + - It fails when profiling is on, which disables various optimisations + + - It fails when reboxing happens. E.g. + data T = MkT Int Int# + f p@(MkT a _) = ...g p.... + where g is /lazy/ in 'p', but only uses the first component. Then + 'f' is /strict/ in 'p', and only uses the first component. So we only + pass that component to the worker for 'f', which reconstructs 'p' to + pass it to 'g'. Alas we can't say + ...f (MkT a (absentError Int# "blah"))... + bacause `MkT` is strict in its Int# argument, so we get an absentError + exception when we shouldn't. Very annoying! + +So absentError is only used for lifted types. -} mk_absent_let :: DynFlags -> Id -> Maybe (CoreExpr -> CoreExpr) @@ -919,12 +928,12 @@ mk_absent_let dflags arg = WARN( True, text "No absent value for" <+> ppr arg_ty ) Nothing where - arg_ty = idType arg - abs_rhs = mkRuntimeErrorApp aBSENT_ERROR_ID arg_ty msg lifted_arg = arg `setIdStrictness` exnSig -- Note in strictness signature that this is bottoming -- (for the sake of the "empty case scrutinee not known to -- diverge for sure lint" warning) + arg_ty = idType arg + abs_rhs = mkAbsentErrorApp arg_ty msg msg = showSDoc (gopt_set dflags Opt_SuppressUniques) (ppr arg <+> ppr (idType arg)) -- We need to suppress uniques here because otherwise they'd |