Changes between Version 5 and Version 6 of Plugins/Phases


Ignore:
Timestamp:
Jul 28, 2008 11:49:01 AM (6 years ago)
Author:
batterseapower
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Plugins/Phases

    v5 v6  
    1111 
    1212I believe the proposed system represents a significant improvement in modularity and usability of phase control within GHC. 
     13 
     14== CURRENT STATUS == 
     15 
     16{{{ 
     17-- $phase_control 
     18-- #phase_control# 
     19-- 
     20-- Compiler /core phases/ represent contiguous intervals of time spent in the core pipeline. They are used 
     21-- to control when core-to-core passes, inlining and rule activation take place. The phases @Foo@ and @Bar@ 
     22-- would be used in @INLINE@ and @RULES@ pragmas like so: 
     23-- 
     24-- > {-# INLINE [Foo] myIdentifier #-} 
     25-- > {-# RULES "myrule" [~Bar] map f (map g xs) = map (f . g) xs #-} 
     26-- 
     27-- Phases, with the constraints on when they can run are introduced by the @PHASE@ pragma syntax. So, a phase 
     28-- called @Foo@ that must run before one called @Bar@, after one called @Baz@ and at the same time as one 
     29-- called @Spqr@ is written like so: 
     30-- 
     31-- > {-# PHASE Foo < Bar, > Baz, = Spqr #-} 
     32-- 
     33-- All the constraints above are so-called /strong/ constraints: there are also /weak/ constraints, which are 
     34-- suggestions but not commands to the compiler as to when to run phases. If, for example, a cycle is formed 
     35-- by including these constraints into the phase partial ordering then the compiler may ignore them, at it's 
     36-- discretion. Weak constraints are indicated by enclosing the constraint in square brackets: 
     37-- 
     38-- > {-# PHASE Foo [< Bar], [> Baz] #-} 
     39-- 
     40-- Note that it is not currently possible for an equality constraint (phase alias) to be weak. 
     41-- 
     42-- Phases may be imported and exported: 
     43-- 
     44-- > import MyModule ({-# PHASE Foo #-} {-# PHASE Bar #-}) 
     45-- 
     46-- There are three built-in phases that are implicitly imported, and these have the special names @0@, @1@ and 
     47-- @2@. These are constrained such that @2@ must run first, then @1@ and finally @0@. The GHC compiler also 
     48-- exports a number of phases from @GHC.Prim@ that correspond to the particular optimizations and analyses 
     49-- that it may run. 
     50-- 
     51-- When constructing the core pipeline, GHC gathers all the phases available to it, and then imposes a total 
     52-- order than respects all the strong constraints of those phases and as many of the weak constraints as it 
     53-- wishes. This linearises the core phase graph, which serves as the scaffolding on which the actual Core 
     54-- transformations are hung. 
     55-- 
     56-- Now we come to /core passes/, which represent a concrete transformation to be applied to GHCs current Core. 
     57-- Passes will typically just do a single action, but it is possible to specify a \"core pass\" that just runs a 
     58-- list of several other core passes. /Core to-dos/ then associates a core pass with a particular core phase. 
     59-- 
     60-- After solving for some linearisation of the available core phases, the compiler takes the core passes associated 
     61-- with each phase in that linearisation by way of a core to-do and concatenates them in order. This yields 
     62-- the final compiler pipeline, which is what is actually run. 
     63 
     64-- The above is actually a somewhat simplified picture. It gives the /user model/ for what we do with core phases 
     65-- and passes, but actually we implement a number of optimizations to this process. What is there to optimize? Well, 
     66-- we want to minimize the number of simplifier passes that we perform. A naive approach would be to just do one 
     67-- simplifier run per core phase, to deal with activating the rules and inlinings in that phase. However, this 
     68-- results in a lot of simplification! So, we optimize in three ways: 
     69-- 
     70-- 1) When solving for a linearisation of the phases, we group phases together into so-called /phase groups/, which 
     71--    have the property that every phase within the group is depedent only on the phases in other groups. Hence the 
     72--    phases within a phase group are independent, and may be treated by a single simplifier run that "acts as though" 
     73--    it were a simplifier run for every pass individually. 
     74-- 
     75-- 2) Before running a simplifier pass introduced for the sole purpose of performing the rules and inlining activations 
     76--    associated with a particular phase, the compiler does a pre-pass to check if there exists any actual uses of that  
     77--    phase in the source code being compiled. If not, it doesn't bother running that simplifier pass. 
     78-- 
     79-- 3) When building up the core pass pipeline, as far as is possible simplifier passes are moved to the end of the part 
     80--    of the core pipeline belonging to their associated phase group. This gives them their maximum effectiveness, while 
     81--    simultaneously allowing us to "coalesce" those simplifier passes that are adjacent into a single simplifier pass 
     82--    that performs the union of the operations of each individual simplifier pass. 
     83}}} 
    1384 
    1485== Solution ==