[project @ 2000-03-23 17:45:17 by simonpj]
authorsimonpj <unknown>
Thu, 23 Mar 2000 17:45:33 +0000 (17:45 +0000)
committersimonpj <unknown>
Thu, 23 Mar 2000 17:45:33 +0000 (17:45 +0000)
commit111cee3f1ad93816cb828e38b38521d85c3bcebb
tree65f0517386e1855a8bd7198eff92b2e12b07b923
parent290e7896a6785ba5dcfbc7045438f382afd447ff
[project @ 2000-03-23 17:45:17 by simonpj]
This utterly gigantic commit is what I've been up to in background
mode in the last couple of months.  Originally the main goal
was to get rid of Con (staturated constant applications)
in the CoreExpr type, but one thing led to another, and I kept
postponing actually committing.   Sorry.

Simon, 23 March 2000

I've tested it pretty thoroughly, but doubtless things will break.

Here are the highlights

* Con is gone; the CoreExpr type is simpler
* NoRepLits have gone
* Better usage info in interface files => less recompilation
* Result type signatures work
* CCall primop is tidied up
* Constant folding now done by Rules
* Lots of hackery in the simplifier
* Improvements in CPR and strictness analysis

Many bug fixes including

* Sergey's DoCon compiles OK; no loop in the strictness analyser
* Volker Wysk's programs don't crash the CPR analyser

I have not done much on measuring compilation times and binary sizes;
they could have got worse.  I think performance has got significantly
better, though, in most cases.

Removing the Con form of Core expressions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The big thing is that

  For every constructor C there are now *two* Ids:

C is the constructor's *wrapper*. It evaluates and unboxes arguments
before calling $wC.  It has a perfectly ordinary top-level defn
in the module defining the data type.

$wC is the constructor's *worker*.  It is like a primop that simply
allocates and builds the constructor value.  Its arguments are the
actual representation arguments of the constructor.
Its type may be different to C, because:
- useless dict args are dropped
- strict args may be flattened

  For every primop P there is *one* Id, its (curried) Id

  Neither contructor worker Id nor the primop Id have a defminition anywhere.
  Instead they are saturated during the core-to-STG pass, and the code generator
  generates code for them directly. The STG language still has saturated
  primops and constructor applications.

* The Const type disappears, along with Const.lhs.  The literal part
  of Const.lhs reappears as Literal.lhs.  Much tidying up in here,
  to bring all the range checking into this one module.

* I got rid of NoRep literals entirely.  They just seem to be too much trouble.

* Because Con's don't exist any more, the funny C { args } syntax
  disappears from inteface files.

Parsing
~~~~~~~
* Result type signatures now work
f :: Int -> Int = \x -> x
-- The Int->Int is the type of f

g x y :: Int = x+y
-- The Int is the type of the result of (g x y)

Recompilation checking and make
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* The .hi file for a modules is not touched if it doesn't change.  (It used to
  be touched regardless, forcing a chain of recompilations.)  The penalty for this
  is that we record exported things just as if they were mentioned in the body of
  the module.  And the penalty for that is that we may recompile a module when
  the only things that have changed are the things it is passing on without using.
  But it seems like a good trade.

* -recomp is on by default

Foreign declarations
~~~~~~~~~~~~~~~~~~~~
* If you say
foreign export zoo :: Int -> IO Int
  then you get a C produre called 'zoo', not 'zzoo' as before.
  I've also added a check that complains if you export (or import) a C
  procedure whose name isn't legal C.

Code generation and labels
~~~~~~~~~~~~~~~~~~~~~~~~~~
* Now that constructor workers and wrappers have distinct names, there's
  no need to have a Foo_static_closure and a Foo_closure for constructor Foo.
  I nuked the entire StaticClosure story.  This has effects in some of
  the RTS headers (i.e. s/static_closure/closure/g)

Rules, constant folding
~~~~~~~~~~~~~~~~~~~~~~~
* Constant folding becomes just another rewrite rule, attached to the Id for the
  PrimOp.   To achieve this, there's a new form of Rule, a BuiltinRule (see CoreSyn.lhs).
  The prelude rules are in prelude/PrelRules.lhs, while simplCore/ConFold.lhs has gone.

* Appending of constant strings now works, using fold/build fusion, plus
  the rewrite rule
unpack "foo" c (unpack "baz" c n)  =  unpack "foobaz" c n
  Implemented in PrelRules.lhs

* The CCall primop is tidied up quite a bit.  There is now a data type CCall,
  defined in PrimOp, that packages up the info needed for a particular CCall.
  There is a new Id for each new ccall, with an big "occurrence name"
{__ccall "foo" gc Int# -> Int#}
  In interface files, this is parsed as a single Id, which is what it is, really.

Miscellaneous
~~~~~~~~~~~~~
* There were numerous places where the host compiler's
  minInt/maxInt was being used as the target machine's minInt/maxInt.
  I nuked all of these; everything is localised to inIntRange and inWordRange,
  in Literal.lhs

* Desugaring record updates was broken: it didn't generate correct matches when
  used withe records with fancy unboxing etc.  It now uses matchWrapper.

* Significant tidying up in codeGen/SMRep.lhs

* Add __word, __word64, __int64 terminals to signal the obvious types
  in interface files.  Add the ability to print word values in hex into
  C code.

* PrimOp.lhs is no longer part of a loop.  Remove PrimOp.hi-boot*

Types
~~~~~
* isProductTyCon no longer returns False for recursive products, nor
  for unboxed products; you have to test for these separately.
  There's no reason not to do CPR for recursive product types, for example.
  Ditto splitProductType_maybe.

Simplification
~~~~~~~~~~~~~~~
* New -fno-case-of-case flag for the simplifier.  We use this in the first run
  of the simplifier, where it helps to stop messing up expressions that
  the (subsequent) full laziness pass would otherwise find float out.
  It's much more effective than previous half-baked hacks in inlining.

  Actually, it turned out that there were three places in Simplify.lhs that
  needed to know use this flag.

* Make the float-in pass push duplicatable bindings into the branches of
  a case expression, in the hope that we never have to allocate them.
  (see FloatIn.sepBindsByDropPoint)

* Arrange that top-level bottoming Ids get a NOINLINE pragma
  This reduced gratuitous inlining of error messages.
  But arrange that such things still get w/w'd.

* Arrange that a strict argument position is regarded as an 'interesting'
  context, so that if we see
foldr k z (g x)
  then we'll be inclined to inline g; this can expose a build.

* There was a missing case in CoreUtils.exprEtaExpandArity that meant
  we were missing some obvious cases for eta expansion
  Also improve the code when handling applications.

* Make record selectors (identifiable by their IdFlavour) into "cheap" operations.
  [The change is a 2-liner in CoreUtils.exprIsCheap]
  This means that record selection may be inlined into function bodies, which
  greatly improves the arities of overloaded functions.

* Make a cleaner job of inlining "lone variables".  There was some distributed
  cunning, but I've centralised it all now in SimplUtils.analyseCont, which
  analyses the context of a call to decide whether it is "interesting".

* Don't specialise very small functions in Specialise.specDefn
  It's better to inline it.  Rather like the worker/wrapper case.

* Be just a little more aggressive when floating out of let rhss.
  See comments with Simplify.wantToExpose
  A small change with an occasional big effect.

* Make the inline-size computation think that
case x of I# x -> ...
  is *free*.

CPR analysis
~~~~~~~~~~~~
* Fix what was essentially a bug in CPR analysis.  Consider

letrec f x = let g y = let ... in f e1
     in
     if ... then (a,b) else g x

  g has the CPR property if f does; so when generating the final annotated
  RHS for f, we must use an envt in which f is bound to its final abstract
  value.  This wasn't happening.  Instead, f was given the CPR tag but g
  wasn't; but of course the w/w pass gives rotten results in that case!!
  (Because f's CPR-ness relied on g's.)

  On they way I tidied up the code in CprAnalyse.  It's quite a bit shorter.

  The fact that some data constructors return a constructed product shows
  up in their CPR info (MkId.mkDataConId) not in CprAnalyse.lhs

Strictness analysis and worker/wrapper
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* BIG THING: pass in the demand to StrictAnal.saExpr.  This affects situations
  like
f (let x = e1 in (x,x))
  where f turns out to have strictness u(SS), say.  In this case we can
  mark x as demanded, and use a case expression for it.

  The situation before is that we didn't "know" that there is the u(SS)
  demand on the argument, so we simply computed that the body of the let
  expression is lazy in x, and marked x as lazily-demanded.  Then even after
  f was w/w'd we got

let x = e1 in case (x,x) of (a,b) -> $wf a b

  and hence

let x = e1 in $wf a b

  I found a much more complicated situation in spectral/sphere/Main.shade,
  which improved quite a bit with this change.

* Moved the StrictnessInfo type from IdInfo to Demand.  It's the logical
  place for it, and helps avoid module loops

* Do worker/wrapper for coerces even if the arity is zero.  Thus:
stdout = coerce Handle (..blurg..)
  ==>
wibble = (...blurg...)
stdout = coerce Handle wibble
  This is good because I found places where we were saying
case coerce t stdout of { MVar a ->
...
case coerce t stdout of { MVar b ->
...
  and the redundant case wasn't getting eliminated because of the coerce.
177 files changed:
ghc/compiler/DEPEND-NOTES
ghc/compiler/Makefile
ghc/compiler/absCSyn/AbsCSyn.lhs
ghc/compiler/absCSyn/AbsCUtils.lhs
ghc/compiler/absCSyn/CLabel.lhs
ghc/compiler/absCSyn/CStrings.lhs
ghc/compiler/absCSyn/Costs.lhs
ghc/compiler/absCSyn/PprAbsC.lhs
ghc/compiler/basicTypes/BasicTypes.lhs
ghc/compiler/basicTypes/Const.hi-boot [deleted file]
ghc/compiler/basicTypes/Const.hi-boot-5 [deleted file]
ghc/compiler/basicTypes/Const.lhs [deleted file]
ghc/compiler/basicTypes/DataCon.hi-boot
ghc/compiler/basicTypes/DataCon.hi-boot-5
ghc/compiler/basicTypes/DataCon.lhs
ghc/compiler/basicTypes/Demand.lhs
ghc/compiler/basicTypes/FieldLabel.lhs
ghc/compiler/basicTypes/Id.lhs
ghc/compiler/basicTypes/IdInfo.lhs
ghc/compiler/basicTypes/MkId.hi-boot
ghc/compiler/basicTypes/MkId.hi-boot-5
ghc/compiler/basicTypes/MkId.lhs
ghc/compiler/basicTypes/Name.lhs
ghc/compiler/basicTypes/OccName.lhs
ghc/compiler/basicTypes/PprEnv.lhs
ghc/compiler/basicTypes/RdrName.lhs
ghc/compiler/basicTypes/Unique.lhs
ghc/compiler/basicTypes/Var.lhs
ghc/compiler/basicTypes/VarEnv.lhs
ghc/compiler/basicTypes/VarSet.lhs
ghc/compiler/codeGen/CgBindery.lhs
ghc/compiler/codeGen/CgCase.lhs
ghc/compiler/codeGen/CgCon.lhs
ghc/compiler/codeGen/CgConTbls.lhs
ghc/compiler/codeGen/CgExpr.lhs
ghc/compiler/codeGen/CgRetConv.lhs
ghc/compiler/codeGen/CgTailCall.lhs
ghc/compiler/codeGen/ClosureInfo.lhs
ghc/compiler/codeGen/CodeGen.lhs
ghc/compiler/codeGen/SMRep.lhs
ghc/compiler/coreSyn/CoreFVs.lhs
ghc/compiler/coreSyn/CoreLint.lhs
ghc/compiler/coreSyn/CoreSyn.hi-boot
ghc/compiler/coreSyn/CoreSyn.hi-boot-5
ghc/compiler/coreSyn/CoreSyn.lhs
ghc/compiler/coreSyn/CoreTidy.lhs
ghc/compiler/coreSyn/CoreUnfold.lhs
ghc/compiler/coreSyn/CoreUtils.lhs
ghc/compiler/coreSyn/PprCore.lhs
ghc/compiler/coreSyn/Subst.lhs
ghc/compiler/cprAnalysis/CprAnalyse.lhs
ghc/compiler/deSugar/DsBinds.lhs
ghc/compiler/deSugar/DsCCall.lhs
ghc/compiler/deSugar/DsExpr.lhs
ghc/compiler/deSugar/DsForeign.lhs
ghc/compiler/deSugar/DsHsSyn.lhs
ghc/compiler/deSugar/DsListComp.lhs
ghc/compiler/deSugar/DsMonad.lhs
ghc/compiler/deSugar/DsUtils.lhs
ghc/compiler/deSugar/Match.lhs
ghc/compiler/deSugar/MatchLit.lhs
ghc/compiler/hsSyn/HsBinds.lhs
ghc/compiler/hsSyn/HsCore.lhs
ghc/compiler/hsSyn/HsDecls.lhs
ghc/compiler/hsSyn/HsExpr.lhs
ghc/compiler/main/CmdLineOpts.lhs
ghc/compiler/main/CodeOutput.lhs
ghc/compiler/main/Constants.lhs
ghc/compiler/main/Main.lhs
ghc/compiler/main/MkIface.lhs
ghc/compiler/nativeGen/AbsCStixGen.lhs
ghc/compiler/nativeGen/MachMisc.lhs
ghc/compiler/nativeGen/StixInteger.lhs
ghc/compiler/nativeGen/StixPrim.lhs
ghc/compiler/parser/Lex.lhs
ghc/compiler/parser/ParseUtil.lhs
ghc/compiler/parser/Parser.y
ghc/compiler/parser/RdrHsSyn.lhs
ghc/compiler/prelude/PrelInfo.lhs
ghc/compiler/prelude/PrelRules.lhs
ghc/compiler/prelude/PrimOp.lhs
ghc/compiler/prelude/TysWiredIn.lhs
ghc/compiler/profiling/SCCfinal.lhs
ghc/compiler/rename/ParseIface.y
ghc/compiler/rename/Rename.lhs
ghc/compiler/rename/RnBinds.lhs
ghc/compiler/rename/RnExpr.lhs
ghc/compiler/rename/RnIfaces.lhs
ghc/compiler/rename/RnNames.lhs
ghc/compiler/rename/RnSource.lhs
ghc/compiler/simplCore/CSE.lhs
ghc/compiler/simplCore/ConFold.lhs [deleted file]
ghc/compiler/simplCore/FloatIn.lhs
ghc/compiler/simplCore/FloatOut.lhs
ghc/compiler/simplCore/LiberateCase.lhs
ghc/compiler/simplCore/OccurAnal.lhs
ghc/compiler/simplCore/SAT.lhs
ghc/compiler/simplCore/SetLevels.lhs
ghc/compiler/simplCore/SimplCore.lhs
ghc/compiler/simplCore/SimplMonad.lhs
ghc/compiler/simplCore/SimplUtils.lhs
ghc/compiler/simplCore/Simplify.lhs
ghc/compiler/simplStg/LambdaLift.lhs
ghc/compiler/simplStg/SRT.lhs
ghc/compiler/simplStg/StgStats.lhs
ghc/compiler/simplStg/StgVarInfo.lhs
ghc/compiler/simplStg/UpdAnal.lhs
ghc/compiler/specialise/Rules.lhs
ghc/compiler/specialise/SpecEnv.hi-boot-5
ghc/compiler/specialise/Specialise.lhs
ghc/compiler/stgSyn/CoreToStg.lhs
ghc/compiler/stgSyn/StgLint.lhs
ghc/compiler/stgSyn/StgSyn.lhs
ghc/compiler/stranal/SaAbsInt.lhs
ghc/compiler/stranal/SaLib.lhs
ghc/compiler/stranal/StrictAnal.lhs
ghc/compiler/stranal/WorkWrap.lhs
ghc/compiler/stranal/WwLib.lhs
ghc/compiler/typecheck/Inst.lhs
ghc/compiler/typecheck/TcClassDcl.lhs
ghc/compiler/typecheck/TcEnv.lhs
ghc/compiler/typecheck/TcExpr.lhs
ghc/compiler/typecheck/TcForeign.lhs
ghc/compiler/typecheck/TcHsSyn.lhs
ghc/compiler/typecheck/TcIfaceSig.lhs
ghc/compiler/typecheck/TcInstDcls.lhs
ghc/compiler/typecheck/TcModule.lhs
ghc/compiler/typecheck/TcPat.lhs
ghc/compiler/typecheck/TcRules.lhs
ghc/compiler/typecheck/TcSimplify.lhs
ghc/compiler/typecheck/TcTyClsDecls.lhs
ghc/compiler/typecheck/TcTyDecls.lhs
ghc/compiler/types/PprType.lhs
ghc/compiler/types/TyCon.lhs
ghc/compiler/types/Type.lhs
ghc/compiler/types/Variance.lhs
ghc/compiler/usageSP/UsageSPInf.lhs
ghc/compiler/usageSP/UsageSPLint.lhs
ghc/compiler/usageSP/UsageSPUtils.lhs
ghc/compiler/utils/Maybes.lhs
ghc/compiler/utils/Outputable.lhs
ghc/compiler/utils/Util.lhs
ghc/driver/ghc.lprl
ghc/includes/Prelude.h
ghc/includes/Regs.h
ghc/lib/std/PrelBase.lhs
ghc/lib/std/PrelByteArr.lhs
ghc/lib/std/PrelEnum.lhs
ghc/lib/std/PrelException.lhs
ghc/lib/std/PrelFloat.lhs
ghc/lib/std/PrelGHC.hi-boot
ghc/lib/std/PrelHandle.lhs
ghc/lib/std/PrelList.lhs
ghc/lib/std/PrelNum.lhs
ghc/rts/HSprel.def
ghc/rts/Prelude.h
ghc/tests/codeGen/should_run/cg045.hs
ghc/tests/codeGen/should_run/cg047.hs [new file with mode: 0644]
ghc/tests/codeGen/should_run/cg047.stdout [new file with mode: 0644]
ghc/tests/io/should_run/io013.hs
ghc/tests/reader/should_fail/read001.stderr
ghc/tests/rename/should_compile/rn033.hs
ghc/tests/typecheck/should_compile/tc038.stderr
ghc/tests/typecheck/should_compile/tc049.stderr
ghc/tests/typecheck/should_compile/tc050.stderr
ghc/tests/typecheck/should_compile/tc053.stderr
ghc/tests/typecheck/should_compile/tc054.stderr
ghc/tests/typecheck/should_compile/tc056.stderr
ghc/tests/typecheck/should_compile/tc058.stderr
ghc/tests/typecheck/should_compile/tc059.stderr
ghc/tests/typecheck/should_compile/tc087.stderr
ghc/tests/typecheck/should_compile/tc095.stderr
ghc/tests/typecheck/should_fail/tcfail007.stderr
ghc/tests/typecheck/should_fail/tcfail010.stderr
ghc/tests/typecheck/should_fail/tcfail036.stderr
ghc/tests/typecheck/should_fail/tcfail043.stderr
ghc/tests/typecheck/should_fail/tcfail080.stderr