| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
| |
|
|
|
|
| |
This has been wrong for a long time. Fixes Trac #4431.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Reason: avoid having to link the entire ghc package in modules
that use compile-time annotations:
import GHC.Exts( SpecConstrAnnotation )
{-# ANN type T ForceSpecConstr #-}
It's a kind of bug that the package exporting SpecConstrAnnotation
is linked even though it is only needed at compile time, but putting
the data type declaration in GHC.Exts is a simple way to sidestep
the problem
See See Note [SpecConstrAnnotation] in SpecConstr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This big-ish patch arranges that if an Id 'f' is
* Type-class overloaded
f :: Ord a => [a] -> [a]
* Defined with an INLINABLE pragma
{-# INLINABLE f #-}
* Exported from its defining module 'D'
then in any module 'U' that imports D
1. Any call of 'f' at a fixed type will generate
(a) a specialised version of f in U
(b) a RULE that rewrites unspecialised calls to the
specialised on
e.g. if the call is (f Int dOrdInt xs) then the
specialiser will generate
$sfInt :: [Int] -> [Int]
$sfInt = <code for f, imported from D, specialised>
{-# RULE forall d. f Int d = $sfInt #-}
2. In addition, you can give an explicit {-# SPECIALISE -#}
pragma for the imported Id
{-# SPECIALISE f :: [Bool] -> [Bool] #-}
This too generates a local specialised definition,
and the corresponding RULE
The new RULES are exported from module 'U', so that any module
importing U will see the specialised versions of 'f', and will
not re-specialise them.
There's a flag -fwarn-auto-orphan that warns you if the auto-generated
RULES are orphan rules. It's not in -Wall, mainly to avoid lots of
error messages with existing packages.
Main implementation changes
- A new flag on a CoreRule to say if it was auto-generated.
This is persisted across interface files, so there's a small
change in interface file format.
- Quite a bit of fiddling with plumbing, to get the
{-# SPECIALISE #-} pragmas for imported Ids. In particular, a
new field tgc_imp_specs in TcGblEnv, to keep the specialise
pragmas for imported Ids between the typechecker and the desugarer.
- Some new code (although surprisingly little) in Specialise,
to deal with calls of imported Ids
|
|
|
|
| |
and adjust imports accordingly
|
|
|
|
|
|
|
|
|
| |
This major patch implements the new OutsideIn constraint solving
algorithm in the typecheker, following our JFP paper "Modular type
inference with local assumptions".
Done with major help from Dimitrios Vytiniotis and Brent Yorgey.
|
|
|
|
|
|
|
|
|
|
| |
Since the RULE from specialising gets the same Activation as
the inlining for the Id itself there's no point in specialising
a NOINLINE thing, because the rule will be permanently switched
off.
See Note [Transfer activation] in SpecConstr
and Note [Auto-specialisation and RULES] in Specialise.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch has zero effect. It includes comments,
a bit of refactoring, and a tiny bit of commment-out
code go implement the "matching cases" idea below.
In the end I've left it disabled because while I think
it does no harm I don't think it'll do any good either.
But I didn't want to lose the idea totally. There's
a thread called "Storable and constant memory" on
the libraries@haskell.org list (Apr 2010) about it.
Note [Matching cases]
~~~~~~~~~~~~~~~~~~~~~
{- NOTE: This idea is currently disabled. It really only works if
the primops involved are OkForSpeculation, and, since
they have side effects readIntOfAddr and touch are not.
Maybe we'll get back to this later . -}
Consider
f (case readIntOffAddr# p# i# realWorld# of { (# s#, n# #) ->
case touch# fp s# of { _ ->
I# n# } } )
This happened in a tight loop generated by stream fusion that
Roman encountered. We'd like to treat this just like the let
case, because the primops concerned are ok-for-speculation.
That is, we'd like to behave as if it had been
case readIntOffAddr# p# i# realWorld# of { (# s#, n# #) ->
case touch# fp s# of { _ ->
f (I# n# } } )
|
| |
|
| |
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It turned out that there were two bugs. First, we were getting an
exponential number of specialisations when we had a deep nest of
join points. See Note [Avoiding exponential blowup]. I fixed this
by dividing sc_count (in ScEnv) by the number of specialisations
when recursing. Crude but effective.
Second, when making specialisations I was looking at the result of
applying specExpr to the RHS of the function, whereas I should have
been looking at the original RHS. See Note [Specialise original
body].
There's a tantalising missed opportunity here, though. In this
example (recorded as a test simplCore/should_compile/T3831), each join
point has *exactly one* call pattern, so we should really just
specialise for that alone, in which case there's zero code-blow-up.
In particular, we don't need the *original* RHS at all. I need to think
more about how to exploit this.
But the blowup is now limited, so compiling terminfo with -O2 works again.
|
|
|
|
|
|
| |
We were printing the wrong value, so getting confusing messages like:
Function `$wa{v s17LO} [lid]'
has 2 call pattterns, but the limit is 3
|
| |
|
|
|
|
|
|
|
|
|
| |
The -fspec-inline-join-point thing was a gross hack intended to help
Roman play around, but he's not using it and it was a terribly blunt
instrument so I've nuked it.
Instead I've re-instated the let-binding specialiser.
See Note [Local let bindings]
|
|
|
|
|
|
|
|
|
|
|
|
| |
It now says something like
SpecConstr
Function `happyDoAction'
has 17 call pattterns, but the limit is 3
Use -fspec-constr-count=n to set the bound
Use -dppr-debug to see specialisations
Previously it just silently did no specialisation
|
|
|
|
|
|
|
|
| |
* I was debugging so I added some call-site info
(that touches a lot of code)
* I used substExpr a bit less in Simplify, hoping to
make the simplifier a little faster and cleaner
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
InlineRules
This patch does two main things:
1. Adjusts the way we set the Activation for
a) The wrappers generated by the strictness analyser
See Note [Wrapper activation] in WorkWrap
b) The RULEs generated by Specialise and SpecConstr
See Note [Auto-specialisation and RULES] in Specialise
Note [Transfer activation] in SpecConstr
2. Refines how we set the phase when simplifying the right
hand side of an InlineRule. See
Note [Simplifying inside InlineRules] in SimplUtils.
Most of the extra lines are comments!
The merit of (2) is that a bit more stuff happens inside InlineRules,
and that in turn allows better dead-code elimination.
|
|
|
|
|
|
|
|
|
|
|
|
| |
The problem was that we collected all annotations we knew about once when the
simplifier started and threaded them through the CoreM monad. If new interface
files were loaded during simplification, their annotations would not be
visible to the simplifier.
Now, we rebuild the annotation list at the start of every simplifier pass that
needs it (which is only SpecConstr at the moment). This ensures that we see
all annotations that have been loaded so far. This is somewhat similar to how
RULES are handled.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Annotating a type with {-# ANN type T ForceSpecConstr #-} makes SpecConstr
ignore -fspec-constr-threshold and -fspec-constr-count for recursive functions
that have arguments of type T. Such functions will be specialised regardless
of their size and there is no upper bound on the number of specialisations
that can be generated. This also works if T is embedded in other types such as
Maybe T (but not T -> T).
T should not be a product type because it could be eliminated by the
worker/wrapper transformation. For instance, in
data T = T Int Int
foo :: T -> Int
foo (T m n) = ... foo (T m' n') ...
SpecConstr will never see the T because w/w will get rid of it. I'm still
thinking about whether fixing this is worthwhile.
|
|
|
|
|
|
|
| |
I finally got tired of the #ifdef OLD_STRICTNESS stuff. I had been
keeping it around in the hope of doing old-to-new comparisions, but
have failed to do so for many years, so I don't think it's going to
happen. This patch deletes the clutter.
|
| |
|
|
|
|
|
|
|
|
|
| |
Annotating a type with NoSpecConstr will prevent SpecConstr from specialising
on arguments of that type. The syntax is
import SpecConstr
{-# ANN type T NoSpecConstr #-}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
'lilac' helpful pin-pointed a space leak that was due to a specialised
function being insufficiently strict. Here's the new comment in SpecConstr:
Note [Transfer strictness]
~~~~~~~~~~~~~~~~~~~~~~~~~~
We must transfer strictness information from the original function to
the specialised one. Suppose, for example
f has strictness SS
and a RULE f (a:as) b = f_spec a as b
Now we want f_spec to have strictess LLS, otherwise we'll use call-by-need
when calling f_spec instead of call-by-value. And that can result in
unbounded worsening in space (cf the classic foldl vs foldl')
See Trac #3437 for a good example.
The function calcSpecStrictness performs the calculation.
|
| |
|
| |
|
|
|
|
|
|
|
| |
This patch fixes a rather obscure bug, whereby it's possible
for (case C a b of <alts>) to have altenatives that do not inclue
(C a b)! See Note [Unreachable code] in CoreUtils.
|
|
|
|
|
|
|
|
|
| |
There is no point in specialising a function that is guaranteed to
diverge, and doing so screwed up arity stuff.
See Note [Do not specialise diverging functions].
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch, written by Max Bolingbroke, does two things
1. It adds a new CoreM monad (defined in simplCore/CoreMonad),
which is used as the top-level monad for all the Core-to-Core
transformations (starting at SimplCore). It supports
* I/O (for debug printing)
* Unique supply
* Statistics gathering
* Access to the HscEnv, RuleBase, Annotations, Module
The patch therefore refactors the top "skin" of every Core-to-Core
pass, but does not change their functionality.
2. It adds a completely new facility to GHC: Core "annotations".
The idea is that you can say
{#- ANN foo (Just "Hello") #-}
which adds the annotation (Just "Hello") to the top level function
foo. These annotations can be looked up in any Core-to-Core pass,
and are persisted into interface files. (Hence a Core-to-Core pass
can also query the annotations of imported things.) Furthermore,
a Core-to-Core pass can add new annotations (eg strictness info)
of its own, which can be queried by importing modules.
The design of the annotation system is somewhat in flux. It's
designed to work with the (upcoming) dynamic plug-ins mechanism,
but is meanwhile independently useful.
Do not merge to 6.10!
|
|
|
|
|
|
|
|
| |
SpecConstr can make pattern binders come alive, so we must remember
to zap their dead-variable annotation. See extendCaseBndrs.
(This was triggering a Core Lint failure in DPH.)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
a) When generating specialisations, include the types in the name
of the rule, to avoid having rules with duplicate names.
(The rule name is used to put rules in canonical order for
fingerprinting.)
b) In Specialise and SpecConstr use a new function Rules.pprRulesForUser
to print rules in canonical order. This reduces unnecessary wobbling
in test output, notably in T2486
|
|
|
|
|
|
|
| |
The uniques that come out in dumpStyle make it harder to compare
output in the testsuite. And the rules are tidied, so uniques
are not necessary. If you want the uniques, use -dppr-debug.
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In SpecConstr.isValue, we recorded a ConVal for a big-lambda,
which seems wrong. I came across this when implementing System IF.
The code now reads:
isValue env (Lam b e)
| isTyVar b = case isValue env e of
Just _ -> Just LambdaVal -- NB!
Nothing -> Nothing
| otherwise = Just LambdaVal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch makes a significant improvement to SpecConstr, based on
Roman's experience with using it for stream fusion. The main change is
this:
* For local (not-top-level) declarations, seed the specialisation
loop from the calls in the body of the 'let'.
See Note [Local recursive groups] for discussion and example. Top-level
declarations are treated just as before.
Other changes in this patch:
* New flag -fspec-constr-count=N sets the maximum number of specialisations
for any single function to N. -fno-spec-constr-count removes the limit.
* Refactoring in specLoop and friends; new algebraic data types
OneSpec and SpecInfo instead of the tuples that were there before
* Be less keen to specialise on variables that are simply in scope.
Example
f p q = letrec g a y = ...g.... in g q p
We probably do not want to specialise 'g' for calls with exactly
the arguments 'q' and 'p', since we know nothing about them.
|
|
|
|
|
| |
Work around various problems caused by some of the monadification patches
not being applied.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This patch addresses a problem that Roman found in SpecConstr. Consider:
foo :: Maybe Int -> Maybe Int -> Int
foo a b = let j b = foo a b
in
case b of
Nothing -> ...
Just n -> case a of
Just m -> ... j (Just (n+1)) ...
Nothing -> ... j (Just (n-1)) ...
We want to make specialised versions for 'foo' for the patterns
Nothing (Just v)
(Just a) (Just b)
Two problems, caused by the join point j. First, j does not
scrutinise b, so j won't be specialised f for the (Just v) pattern.
Second, j is defined where the free var 'a' is not evaluated.
Both are solved by brutally inlining j at its call sites. This risks
major code bloat, but it's relatively quick to implement. The flag
-fspec-inline-join-points
causes brutal inlining for a
non-recursive binding
of a function
whose RHS contains calls
of a recursive function
The (experimental) flag is static for now, and I have not even
documented it properly.
|
|
|
|
|
|
| |
This patch replaces -fspec-threshold by -fspec-constr-threshold and
-fliberate-case-threshold. The thresholds can be disabled by
-fno-spec-constr-threshold and -fno-liberate-case-threshold.
|
|
|
|
|
|
|
|
|
|
|
| |
The Cast case of the rule-matcher was simply wrong.
This patch fixes it; see Trac #1746.
I also fixed the rule generation in SpecConstr to generate a wild-card
for the cast expression, which we don't want to match on. This makes
the rule more widely applicable; it wasn't the cause of the bug.
|
| |
|
| |
|
|
|
|
|
|
|
| |
Older GHCs can't parse OPTIONS_GHC.
This also changes the URL referenced for the -w options from
WorkingConventions#Warnings to CodingStyle#Warnings for the compiler
modules.
|
| |
|