Changes between Version 5 and Version 6 of Plugins/Phases

Jul 28, 2008 11:49:01 AM (7 years ago)



  • Plugins/Phases

    v5 v6  
    1212I believe the proposed system represents a significant improvement in modularity and usability of phase control within GHC.
     14== CURRENT STATUS ==
     17-- $phase_control
     18-- #phase_control#
     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:
     24-- > {-# INLINE [Foo] myIdentifier #-}
     25-- > {-# RULES "myrule" [~Bar] map f (map g xs) = map (f . g) xs #-}
     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:
     31-- > {-# PHASE Foo < Bar, > Baz, = Spqr #-}
     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:
     38-- > {-# PHASE Foo [< Bar], [> Baz] #-}
     40-- Note that it is not currently possible for an equality constraint (phase alias) to be weak.
     42-- Phases may be imported and exported:
     44-- > import MyModule ({-# PHASE Foo #-} {-# PHASE Bar #-})
     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.
     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.
     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.
     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.
     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:
     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.
     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.
     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.
    1485== Solution ==