Skip to content
  • Simon Peyton Jones's avatar
    [project @ 1999-05-18 15:16:33 by simonpj] · c5b15182
    Simon Peyton Jones authored
    SIMON's MASSIVE COMMIT
    
    [The real commit preceded this, but had the stupid message "RULES-NOTES"
     because I used "cvs commit -m" instead of "cvs commit -F"]
    
    Module reorganisation
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    coreSyn/CoreFVs		replaces coreSyn/FreeVars
    coreSyn/CoreTidy	is new (was code in simplCore/SimplCore)
    coreSyn/Subst 		is new (implements substitution incl 
    				dealing with name clashes
    main/CodeOutput		is new (was gruesome code in main/Main)
    parser/rulevar.ugn	Ugen file for rules
    prelude/ThinAir.lhs	is new (defns for "thin air" ids; was in
    				prelude/PrelVals)
    specialise/Rules	is new (implements rewrite rule matching)
    typecheck/TcRules	is new (typechecks rewrite rules)
    types/InstEnv		is new (implements the instance env in Class;
    
    				replaces SpecEnv)
    specialise/SpecEnv	has gone
    simplCore/MagicUFs	has gone (hurrah)
    
    Rewrite rules
    ~~~~~~~~~~~~~
    This major commit adds the ability to specify transformation rules.
    
       E.g. 
       
       {-# RULES
    	   forall f,g,xs. map f (map g xs) = map (f . g) xs
       #-}
    
    The rules are typechecked, and survive across separate compilation.
    
    * specialise/SpecEnv.lhs has gone, replaced by specialise/Rules.lhs.
      Rules.lhs implements transformation-rule matching.
    
    * Info about class instances is no longer held in a SpecEnv in the class;
      instead classes have their own thing, typecheck/InstEnv.lhs
    
    * Specialisations are held in list of rules, held inside an Id.
      So although specialisations arise from SPECIALISE pragmas and
      uses of overloaded functions, they are still expressed as transformation
      rules.  However these rules are held inside the relevant Id, as
      before.  The RULES ones are held globally.
    
    Cloning
    ~~~~~~~
    I've removed -fplease-clone as a simplifier flag.  It complicates the 
    plumbing quite a bit.  The simplifier now simply ensures that there's
    no shadowing in its output.
    
    It's up to other passes to solve their own cloning problems.  It turned
    out to be easy:
    	- SetLevels clones where necessary, so that floating out
    	  doesn't cause a problem.
    
    	- CoreToStg clones so that the code generator can use uniques
    	  for labels
    
    Instead, the simplifier clones by using VarSet.uniqAway to find a unique
    that doesn't conflict with any that are in scope.  If you say -dppr-debug
    you get a trace of how many times uniqAway had to loop before finding a
    suitable unique.  It's too much at present; something to improve.
    
    Flags
    ~~~~~
    * I have stopped -fcase-of-case and friends being 'per-simplfication' 
      flags, and instead made them global 'opt_' things.  This is simpler
      and more efficient, and the extra expressiveness was never used anyway.
    
    * -dsimplifier-stats has been renamed to -ddump-simpl-stats
      and prints much more coherent info than before.
      If you add -dppr-debug you get much more detailed information.
    
    * -ddump-inlinings is more or less as before, but a bit improved.
    
    
    Inlining and inline phase
    ~~~~~~~~~~~~~~~~~~~~~~~~~
    I've moved the crucial inline-control function (now called callSiteInline)
    to CoreUnfold from Simplify, so that all the key inlining decisions are
    made in CoreUnfold.
    
    I've removed IWantToBeINLINEd as an InlinePragInfo on an Id.  Instead, I've
    added a new Note on expressions, InlineMe.  This is much more robust to
    program transformations than the old way.  Essentially, an expression
    wrapped in an InlineMe note looks small to the inliner.
    
    In order to prevent variables on the LHS of transformation rules being inlined
    prematurely, the simplifier maintains a "black list" of variables that should
    not be inlined.  Before each run of the simplifier, it constructs its black
    list based on the "inline phase number", controlled by the per-simplification
    flag -finline-phase1, -finline-phase2 etc.  Details of what happens in the
    different phases are defined by the function CoreUnfold.blackListed.
    
    
    Function and primop arguments
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    I've improved the way that the simplifier deals with strict arguments of functions
    and primops.  These are now both dealt with by Simplify.prepareArgs.  As as result
    strict arguments are no longer case-ifyd in Core.  That happens in the core-to-stg
    transformation. This is important so that transformation rules work easily.
    We want to see		foldr k z (build g)
    	and not		case build g of { x -> foldr k z x }
    
    CoreToStg now takes accouunt of the strictness of functions and primops, to
    ensure that strict arguments are done with case.
    
    
    Cheap primops
    ~~~~~~~~~~~~~
    Primops that are cheap and can't fail (i.e not divide!) reply True to primOpOkForSpeculation.
    Applications of such primops are now allowed to appear in lets (rather than cases),
    so that they are easier to float.  They are honorary lets, in the sense that they can 
    float out or in without damage.  Again core-to-stg turns them into cases.
    
    
    Class op selectors
    ~~~~~~~~~~~~~~~~~~
    Generate bindings for class-op selectors.  The immediate reason for doing this
    is so we can write transformation rules involving them; black-listing won't
    work if they have to be inlined!  The longer-term reason is because Hugs will
    need these bindings. Also there's no point in inling them if the dictionary
    is lambda bound.
    
    
    Simplifier
    ~~~~~~~~~~
    I've made a number of detailed changes to the innards of the simplifier.
    Result is (a bit) less code, and fewer iterations.  Only the biggest modules
    provoke the "more than 4 iterations" complaint.
    
    
    
    ... And tons of other minor stuff ...
    c5b15182