diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2020-03-31 17:17:56 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2020-04-01 10:22:10 +0100 |
commit | 7052d7c7ce3418db9e66ad6ff31e80b2a2c724bb (patch) | |
tree | 407119957b7941f23e6b6e2764ad512ddd70f19d /compiler/GHC/Core/Unfold.hs | |
parent | 0002db1bf436cbd32f97b659a52b1eee4e8b21db (diff) | |
download | haskell-wip/T17966.tar.gz |
Major improvements to the specialiserwip/T17966
This patch is joint work of Alexis King and Simon PJ. It does some
significant refactoring of the type-class specialiser. Main highlights:
* We can specialise functions with types like
f :: Eq a => a -> Ord b => b => blah
where the classes aren't all at the front (#16473). Here we can
correctly specialise 'f' based on a call like
f @Int @Bool dEqInt x dOrdBool
This change really happened in an earlier patch
commit 2d0cf6252957b8980d89481ecd0b79891da4b14b
Author: Sandy Maguire <sandy@sandymaguire.me>
Date: Thu May 16 12:12:10 2019 -0400
work that this new patch builds directly on that work, and refactors
it a bit.
* We can specialise functions with implicit parameters (#17930)
g :: (?foo :: Bool, Show a) => a -> String
Previously we could not, but now they behave just like a non-class
argument as in 'f' above.
* We can specialise under-saturated calls, where some (but not all of
the dictionary arguments are provided (#17966). For example, we can
specialise the above 'f' based on a call
map (f @Int dEqInt) xs
even though we don't (and can't) give Ord dictionary.
This may sound exotic, but #17966 is a program from the wild, and
showed significant perf loss for functions like f, if you need
saturation of all dictionaries.
* We fix a buglet in which a floated dictionary had a bogus demand
(#17810), by using zapIdDemandInfo in the NonRec case of specBind.
* A tiny side benefit: we can drop dead arguments to specialised
functions; see Note [Drop dead args from specialisations]
* Fixed a bug in deciding what dictionaries are "interesting"; see
Note [Keep the old dictionaries interesting]
This is all achieved by by building on Sandy Macguire's work in
defining SpecArg, which mkCallUDs uses to describe the arguments of
the call. Main changes:
* Main work is in specHeader, which marched down the [InBndr] from the
function definition and the [SpecArg] from the call site, together.
* specCalls no longer has an arity check; the entire mechanism now
handles unders-saturated calls fine.
* mkCallUDs decides on an argument-by-argument basis whether to
specialise a particular dictionary argument; this is new.
See mk_spec_arg in mkCallUDs.
It looks as if there are many more lines of code, but I think that
all the extra lines are comments!
Diffstat (limited to 'compiler/GHC/Core/Unfold.hs')
-rw-r--r-- | compiler/GHC/Core/Unfold.hs | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/compiler/GHC/Core/Unfold.hs b/compiler/GHC/Core/Unfold.hs index 411a954428..4b7cb80daf 100644 --- a/compiler/GHC/Core/Unfold.hs +++ b/compiler/GHC/Core/Unfold.hs @@ -172,15 +172,16 @@ mkInlinableUnfolding dflags expr where expr' = simpleOptExpr dflags expr -specUnfolding :: DynFlags -> [Var] -> (CoreExpr -> CoreExpr) -> Arity +specUnfolding :: DynFlags -> Id -> [Var] -> (CoreExpr -> CoreExpr) -> Arity -> Unfolding -> Unfolding -- See Note [Specialising unfoldings] -- specUnfolding spec_bndrs spec_app arity_decrease unf -- = \spec_bndrs. spec_app( unf ) -- -specUnfolding dflags spec_bndrs spec_app arity_decrease +specUnfolding dflags fn spec_bndrs spec_app arity_decrease df@(DFunUnfolding { df_bndrs = old_bndrs, df_con = con, df_args = args }) - = ASSERT2( arity_decrease == count isId old_bndrs - count isId spec_bndrs, ppr df ) + = ASSERT2( arity_decrease == count isId old_bndrs - count isId spec_bndrs + , ppr df $$ ppr spec_bndrs $$ ppr (spec_app (Var fn)) $$ ppr arity_decrease ) mkDFunUnfolding spec_bndrs con (map spec_arg args) -- There is a hard-to-check assumption here that the spec_app has -- enough applications to exactly saturate the old_bndrs @@ -194,7 +195,7 @@ specUnfolding dflags spec_bndrs spec_app arity_decrease -- The beta-redexes created by spec_app will be -- simplified away by simplOptExpr -specUnfolding dflags spec_bndrs spec_app arity_decrease +specUnfolding dflags _ spec_bndrs spec_app arity_decrease (CoreUnfolding { uf_src = src, uf_tmpl = tmpl , uf_is_top = top_lvl , uf_guidance = old_guidance }) @@ -211,7 +212,7 @@ specUnfolding dflags spec_bndrs spec_app arity_decrease in mkCoreUnfolding src top_lvl new_tmpl guidance -specUnfolding _ _ _ _ _ = noUnfolding +specUnfolding _ _ _ _ _ _ = noUnfolding {- Note [Specialising unfoldings] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |