| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Consider
lvl = Just True
foo :: Maybe Bool -> Int -> Int
foo (Just True) i = i
foo _ i = foo lvl i
SpecConstr should specialise foo, but it wasn't doing so (spotted
by Roman).
Reason: lvl's unfolding wasn't in the cloned version of lvl.
Solution: extend the value environment to record top-level bindings too
At the same time I made it work if 'lvl' is a lambda, in which case it
is again worth specialisg. This meant renaming ConEnv to ValueEnv,
and adding a case for 'LambdaVal'.
(To make specialisation on lambdas work properly, we have to do lambda
lifting as well, but this gets part of the way, and fixes a bug too.)
|
|
|
|
| |
This has been a long-standing ToDo.
|
|
|
|
|
|
|
| |
These bugs produced a core-lint error when compiling
GHC.PArr with -O2. Roman found and fixed them; this
patch also includes some type synonyms to make things a
bit clearer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch improves the SpecConstr pass, by
a) making it work with join points
b) making it generate specialisations transitively
As part of it, SpecConstr now carries a substitution with it, which
runs over the whole program as it goes. This turned out to be
a big win; simplified the implementation quite a bit.
I have *disabled* the specialisation on lambdas; it's pretty fragile,
and sometimes generates more and more specialisations. Something to
come back to, perhaps.
I rejigged the flag-handling a bit. Now the specification of passes
in DynFlags is a bit nicer; see
- optLevelFlags top-level data structure
- runWhen function
- CoreDoPasses constructor
There are now command-line flags
-fspec-constr
-fliberate-case
-fspec-threshold=N
which do the obvious thing. -O2 switches on both spec-constr and liberate-case.
You can use -fno-liberate-case, -fno-spec-constr after -O2 to switch them off again.
The spec-threshold applies to both these transformations; default value 200 for now.
|
|
|
|
| |
does no harm
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Roman found cases where it was important to do SpecConstr for
mutually-recursive definitions. Here is one:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just 0) = foo Nothing
foo (Just n) = foo (Just (n-1))
By the time SpecConstr gets to it, it looks like this:
lvl = foo Nothing
foo Nothing = 0
foo (Just 0) = lvl
foo (Just n) = foo (Just (n-1))
Happily, it turns out to be rather straightforward to generalise the
transformation to mutually-recursive functions. Look, ma, only 4
extra lines of ocde!
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
For totally stupid reasons, SpecConstr didn't work for the (particularly
easy) case of nullary constructors like True and False. I just had some
equations in the wrong order, so that a Var case came first, which
matches a nullary constructor, with the constructor-application case
afterwards.
The fix is easy. I did a bit of refactoring at the same time.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
SpecConstr was conservative about avoiding reboxing (see Note [Reboxing])
but that meant it lost useful opportunities. This patch makes it much
more aggressive, but at the risk of doing some reboxing.
Actually, the strictness analyser has the same property (it's possible
for it to generate reboxing code, and thus increase allocation), but we
don't worry so much about that. Maybe we should.
Ideally, one would do some more sophisticated analysis that spotted
the reboxing cases without excluding the useful ones.
But meanwhile, let's try this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This big patch completely overhauls the Simplifier. The simplifier
had grown old and crufty, and was hard to understand and maintain.
This new version is still quite complicated, because the simplifier
does a lot, but it's much easier to understand, for me at least.
It does mean that I have touched almost every line of the simplifier,
so the diff is a large one.
Big changes are these
* When simplifying an Expr we generate a simplified Expr plus a
bunch of "floats", which are bindings that have floated out
of the Expr. Before, this float stuff was returned separately,
but not they are embedded in the SimplEnv, which makes the
plumbing much easier and more robust. In particular, the
SimplEnv already meaintains the "in-scope set", and making
that travel with the floats helps to ensure that we always
use the right in-scope set.
This change has a pervasive effect.
* Rather than simplifying the args of a call before trying rules
and inlining, we now defer simplifying the args until both
rules and inlining have failed, so we're going to leave a
call in the result. This avoids the risk of repeatedly
simplifying an argument, which was handled by funny ad-hoc
flags before.
The downside is that we must apply the substitution to the args before
rule-matching; and if thep rule doesn't match that is wasted work.
But having any rules at all is the exception not the rule, and the
substitution is lazy, so we only substitute until a no-match is found.
The code is much more elegant though.
* A SimplCont is now more zipper-like. It used to have an embedded
function, but that was a bit hard to think about, and now it's
nice and consistent. The relevant constructors are StrictArg
and StrictBind
* Each Rule now has an *arity* (gotten by CoreSyn.ruleArity), which
tells how many arguments it matches against. This entailed adding
a field ru_nargs to a BuiltinRule. And that made me look at
PrelRules; I did quite a bit of refactoring in the end, so the
diff in PrelRules looks much biggger than it really is.
* A little refactoring in OccurAnal. The key change is that in
the RHS of x = y `cast` co
we regard 'y' as "many", so that it doesn't get inlined into
the RHS of x. This allows x to be inlined elsewhere. It's
very like the existing situation for
x = Just y
where we treat 'y' as "many".
|
|
|
|
|
| |
This patch teaches SpecConstr about casts; see Note [SpecConstr for casts]
|
|
|
|
|
|
|
|
|
|
| |
This patch enables argToPat to look through let expressions
e.g. f (let v = rhs in \y -> ...v...)
Here we can specialise for f (\y -> ...) because the rule-matcher will
look through the let.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Fri Aug 4 18:13:56 EDT 2006 Manuel M T Chakravarty <chak@cse.unsw.edu.au>
* Massive patch for the first months work adding System FC to GHC #31
Broken up massive patch -=chak
Original log message:
This is (sadly) all done in one patch to avoid Darcs bugs.
It's not complete work... more FC stuff to come. A compiler
using just this patch will fail dismally.
|
| |
|
|
|
|
|
|
|
| |
argToPat is a crucial function for SpecConstr, because it decides
what patterns are worth specialising. I was being much too gung-ho about
constants. This patch makes it much better.
|
| |
|
|
|
|
|
| |
I was forgetting the non-pattern-matched type args of a constructor.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Roman inspired me to beef up SpecConstr to deal with
a) constant arguments
b) lambda arguments
This is described in elaborate comments in the file:
Note [Specialising for constant parameters]
Note [Specialising for lambda parameters]
I also took the opportunity to fix the usage analysis done by
SpecConstr, which was only handling the top-level correctly.
Now it does nesting too.
|
| |
|
| |
|
|
|
|
|
|
|
|
|
| |
In SpecConstr.scBind, we should pass the optimised body (body') to
specialise, not the un-optimised one. In this way we'll benefit from
specialising any nested functions inside body.
Discovered by Roman.
|
|
|
|
|
|
|
|
|
| |
For some reason, SpecConstr wasn't taking account of let-bound constructors:
let v = Just 4
in ...(f v)...
Now it does. An easy fix fortunately.
|
|
|
|
|
|
|
|
|
|
|
|
| |
Arrange to run the simplifier before SpecConstr, to (almost entirely)
eliminate shadowing.
Reason: otherwise SpecConstr can generate a RULE that never
files; and LiberateCase specifically *does* generate lots of shadowing.
See Note [Shadowing] in SpecConstr.lhs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The constructor-specialisation optimisation was not dealing with the case
of
(letrec ... in f) a1 a2
We need to apply constructor specialisation in the letrec; previously
we were leaving it untouched on the grounds that the function part of
an application is almost always a variable.
But in fact, float-in immediately precedes SpecConstr, so we can get
these odd-looking applications.
|
|
|
|
|
|
|
|
|
|
|
| |
SpecConstr currently uses substExpr for tiresome reasons to do with
GADTs. Unfortunately the substExpr generates some WARNINGS (when DEBUG)
is on, because we aren't adding all the in-scope Ids to the in-scope
set of the substitution.
When we move to FC these substExprs will go away, so I'm not going to
worry about this now.
|
|
Most of the other users of the fptools build system have migrated to
Cabal, and with the move to darcs we can now flatten the source tree
without losing history, so here goes.
The main change is that the ghc/ subdir is gone, and most of what it
contained is now at the top level. The build system now makes no
pretense at being multi-project, it is just the GHC build system.
No doubt this will break many things, and there will be a period of
instability while we fix the dependencies. A straightforward build
should work, but I haven't yet fixed binary/source distributions.
Changes to the Building Guide will follow, too.
|