Simon Jakobi pushed to branch wip/sjakobi/T27368-cbe-compress at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/Cmm/CommonBlockElim.hs
    ... ... @@ -59,18 +59,25 @@ import qualified Data.List.NonEmpty as NE
    59 59
     -- hashes, and at most once otherwise. Previously, we were slower, and people
    
    60 60
     -- rightfully complained: #10397
    
    61 61
     
    
    62
    +-- The input graph may contain unreachable blocks (see
    
    63
    +-- Note [unreachable blocks] in GHC.Cmm.Pipeline). They take part in
    
    64
    +-- deduplication like any other block, and stay in the graph unless
    
    65
    +-- eliminated by a merge (deleteLosers removes those).
    
    66
    +
    
    62 67
     -- TODO: Use optimization fuel
    
    63 68
     elimCommonBlocks :: CmmGraph -> CmmGraph
    
    64 69
     elimCommonBlocks g =
    
    65 70
         assert (g_entry g == g_entry g') g'
    
    66 71
       where
    
    67
    -     g' = replaceLabels env $ copyTicks env g
    
    72
    +     g' = replaceLabels env $ deleteLosers $ copyTicks env g
    
    73
    +     deleteLosers g0
    
    74
    +       | mapNull env = g0
    
    75
    +       | otherwise   = ofBlockMap (g_entry g0)
    
    76
    +                                  (toBlockMap g0 `mapDifference` env)
    
    68 77
          env = resolveSubst (iterate mapEmpty blocks_with_key)
    
    69
    -     -- The order of blocks doesn't matter here. While we could use
    
    70
    -     -- revPostorder which drops unreachable blocks this is done in
    
    71
    -     -- ContFlowOpt already which runs before this pass. So we use
    
    72
    -     -- toBlockList since it is faster.
    
    73
    -     -- One exception: The entry block most come first or we risk eliminating it
    
    78
    +     -- The order of blocks doesn't matter here, so we use toBlockList,
    
    79
    +     -- which is faster than revPostorder.
    
    80
    +     -- One exception: The entry block must come first or we risk eliminating it
    
    74 81
          -- in favour of another block. See Note [Retain entry block during common block elimination.]
    
    75 82
          groups = groupByInt hash_block (toBlockListEntryFirst g) :: [[CmmBlock]]
    
    76 83
          blocks_with_key = [ [ (successors b, [b]) | b <- bs] | bs <- groups]
    

  • compiler/GHC/Cmm/ContFlowOpt.hs
    ... ... @@ -42,9 +42,10 @@ import Control.Monad
    42 42
     -- L2: goto L3;
    
    43 43
     -- L3: ...
    
    44 44
     --
    
    45
    --- In this situation we say that we shortcut L2 to L3. One of
    
    45
    +-- In this situation we say that we shortcut L2 to L3. One of the
    
    46 46
     -- consequences of shortcutting is that some blocks of code may become
    
    47
    --- unreachable (in the example above this is true for L2).
    
    47
    +-- unreachable (in the example above this is true for L2). See
    
    48
    +-- Note [unreachable blocks] in GHC.Cmm.Pipeline.
    
    48 49
     
    
    49 50
     
    
    50 51
     -- Note [Control-flow optimisations]
    
    ... ... @@ -66,7 +67,7 @@ import Control.Monad
    66 67
     --
    
    67 68
     -- Blocks are processed using postorder DFS traversal. A side effect
    
    68 69
     -- of determining traversal order with a graph search is elimination
    
    69
    --- of any blocks that are unreachable.
    
    70
    +-- of any blocks that are unreachable in the input.
    
    70 71
     --
    
    71 72
     -- Transformations are improved by working from the end of the graph
    
    72 73
     -- towards the beginning, because we may be able to perform many
    
    ... ... @@ -341,8 +342,7 @@ blockConcat splitting_procs g@CmmGraph { g_entry = entry_id }
    341 342
     -- Invariant: if a block has no predecessors it should be dropped from the
    
    342 343
     -- graph because it is unreachable. maybe_concat is constructed to maintain
    
    343 344
     -- that invariant, but calling replaceLabels may introduce unreachable blocks.
    
    344
    --- We rely on subsequent passes in the Cmm pipeline to remove unreachable
    
    345
    --- blocks.
    
    345
    +-- See Note [unreachable blocks] in GHC.Cmm.Pipeline.
    
    346 346
     incPreds, decPreds :: BlockId -> LabelMap Int -> LabelMap Int
    
    347 347
     incPreds bid edges = mapInsertWith (+) bid 1 edges
    
    348 348
     decPreds bid edges = case mapLookup bid edges of
    

  • compiler/GHC/Cmm/Pipeline.hs
    ... ... @@ -358,6 +358,20 @@ containing junk code. These aren't necessarily a problem, but
    358 358
     removing them is good because it might save time in the native code
    
    359 359
     generator later.
    
    360 360
     
    
    361
    +Who removes them, and when?  Any pass that rebuilds the graph from
    
    362
    +revPostorder drops them as a side effect.  Normally the first pass to
    
    363
    +do so is stack layout.  In addition, removeUnreachableBlocksProc at the
    
    364
    +very end of cpsTop removes the blocks that the second round of
    
    365
    +control-flow optimisation orphans, and prunes their info tables.  No
    
    366
    +pass between the first control-flow optimisation and stack layout
    
    367
    +removes unreachable blocks (common block elimination deletes the losing
    
    368
    +blocks of its merges, but leaves other unreachable code alone), so every
    
    369
    +pass in that window may encounter them.
    
    370
    +
    
    371
    +Note that unreachable blocks are not entirely harmless, though: some later
    
    372
    +passes read them. callProcPoints, for example, folds over the whole block map,
    
    373
    +so a stale edge in an unreachable block caused the panic in #27368.
    
    374
    +
    
    361 375
     To make unreachable blocks visible in -ddump-cmm-* output, add -dppr-debug.
    
    362 376
     -}
    
    363 377