Drop proc-points that don't exist in the graph (#8205)
authorJan Stolarek <jan.stolarek@p.lodz.pl>
Wed, 11 Sep 2013 11:17:10 +0000 (12:17 +0100)
committerJan Stolarek <jan.stolarek@p.lodz.pl>
Wed, 11 Sep 2013 13:33:29 +0000 (14:33 +0100)
On some architectures it might happen that stack layout pass will
invalidate the list of calculated procpoints by dropping some of
them. We fix this by checking whether a proc-point is in a graph
at the beginning of proc-point analysis. This is a speculative
fix for #8205.

compiler/cmm/CmmPipeline.hs
compiler/cmm/CmmProcPoint.hs

index 50d02de..dfcdce0 100644 (file)
@@ -122,12 +122,12 @@ cpsTop hsc_env proc =
                   splitAtProcPoints dflags l call_pps proc_points pp_map
                                     (CmmProc h l v g)
             dumps Opt_D_dump_cmm_split "Post splitting" gs
-     
+
             ------------- Populate info tables with stack info -----------------
             gs <- {-# SCC "setInfoTableStackMap" #-}
                   return $ map (setInfoTableStackMap dflags stackmaps) gs
             dumps Opt_D_dump_cmm_info "after setInfoTableStackMap" gs
-     
+
             ----------- Control-flow optimisations -----------------------------
             gs <- {-# SCC "cmmCfgOpts(2)" #-}
                   return $ if optLevel dflags >= 1
@@ -147,7 +147,7 @@ cpsTop hsc_env proc =
             g <- {-# SCC "setInfoTableStackMap" #-}
                   return $ setInfoTableStackMap dflags stackmaps g
             dump' Opt_D_dump_cmm_info "after setInfoTableStackMap" g
-     
+
             ----------- Control-flow optimisations -----------------------------
             g <- {-# SCC "cmmCfgOpts(2)" #-}
                  return $ if optLevel dflags >= 1
index c0dd0e1..5f9c27f 100644 (file)
@@ -30,7 +30,7 @@ import Hoopl
 -- Compute a minimal set of proc points for a control-flow graph.
 
 -- Determine a protocol for each proc point (which live variables will
--- be passed as arguments and which will be on the stack). 
+-- be passed as arguments and which will be on the stack).
 
 {-
 A proc point is a basic block that, after CPS transformation, will
@@ -83,6 +83,33 @@ most once per iteration, then recompute the reachability information.
 arbitrary, and I don't know if the choice affects the final solution,
 so I don't know if the number of proc points chosen is the
 minimum---but the set will be minimal.
+
+
+
+Note [Proc-point analysis]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Given a specified set of proc-points (a set of block-ids), "proc-point
+analysis" figures out, for every block, which proc-point it belongs to.
+All the blocks belonging to proc-point P will constitute a single
+top-level C procedure.
+
+A non-proc-point block B "belongs to" a proc-point P iff B is
+reachable from P without going through another proc-point.
+
+Invariant: a block B should belong to at most one proc-point; if it
+belongs to two, that's a bug.
+
+Note [Non-existing proc-points]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+On some architectures it might happen that the list of proc-points
+computed before stack layout pass will be invalidated by the stack
+layout. This will happen if stack layout removes from the graph
+blocks that were determined to be proc-points. Later on in the pipeline
+we use list of proc-points to perform [Proc-point analysis], but
+if a proc-point does not exist anymore then we will get compiler panic.
+See #8205.
 -}
 
 type ProcPointSet = BlockSet
@@ -104,11 +131,14 @@ instance Outputable Status where
 procPointAnalysis :: ProcPointSet -> CmmGraph -> UniqSM (BlockEnv Status)
 -- Once you know what the proc-points are, figure out
 -- what proc-points each block is reachable from
-procPointAnalysis procPoints g =
+-- See Note [Proc-point analysis]
+procPointAnalysis procPoints g@(CmmGraph {g_graph = graph}) =
   -- pprTrace "procPointAnalysis" (ppr procPoints) $
   dataflowAnalFwdBlocks g initProcPoints $ analFwd lattice forward
-  where initProcPoints = [(id, ProcPoint) | id <- setElems procPoints]
-
+  where initProcPoints = [(id, ProcPoint) | id <- setElems procPoints,
+                                            id `setMember` labelsInGraph ]
+                                    -- See Note [Non-existing proc-points]
+        labelsInGraph  = labelsDefined graph
 -- transfer equations
 
 forward :: FwdTransfer CmmNode Status
@@ -218,7 +248,7 @@ splitAtProcPoints dflags entry_label callPPs procPoints procMap
              Just (ReachedBy set) ->
                case setElems set of
                  []   -> graphEnv
-                 [id] -> add graphEnv id bid b 
+                 [id] -> add graphEnv id bid b
                  _    -> panic "Each block should be reachable from only one ProcPoint"
              Nothing -> graphEnv
            where bid = entryLabel b
@@ -396,9 +426,9 @@ dataflow pass.  One might attempt to use this simple lattice:
 
   data Location = Unknown
                 | InProc BlockId -- node is in procedure headed by the named proc point
-                | ProcPoint      -- node is itself a proc point   
+                | ProcPoint      -- node is itself a proc point
 
-At a join, a node in two different blocks becomes a proc point.  
+At a join, a node in two different blocks becomes a proc point.
 The difficulty is that the change of information during iterative
 computation may promote a node prematurely.  Here's a program that
 illustrates the difficulty:
@@ -432,19 +462,19 @@ are no other proc points that directly reach L2.
 It may be worthwhile to attempt the Adams optimization by rewriting
 the graph before the assignment of proc-point protocols.  Here are a
 couple of rules:
-                                                                  
-  g() returns to k;                    g() returns to L;          
-  k: CopyIn c ress; goto L:             
-   ...                        ==>        ...                       
-  L: // no CopyIn node here            L: CopyIn c ress; 
 
-                                                                  
+  g() returns to k;                    g() returns to L;
+  k: CopyIn c ress; goto L:
+   ...                        ==>        ...
+  L: // no CopyIn node here            L: CopyIn c ress;
+
+
 And when c == c' and ress == ress', this also:
 
-  g() returns to k;                    g() returns to L;          
-  k: CopyIn c ress; goto L:             
-   ...                        ==>        ...                       
-  L: CopyIn c' ress'                   L: CopyIn c' ress' ; 
+  g() returns to k;                    g() returns to L;
+  k: CopyIn c ress; goto L:
+   ...                        ==>        ...
+  L: CopyIn c' ress'                   L: CopyIn c' ress' ;
 
 In both cases the goal is to eliminate k.
 -}