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

Commits:

7 changed files:

Changes:

  • changelog.d/T27368-ppr-unreachable-cmm-blocks.md
    1
    +section: cmm
    
    2
    +issues: #27368
    
    3
    +synopsis:
    
    4
    +  Cmm dumps now show unreachable blocks under ``-dppr-debug``
    
    5
    +description:
    
    6
    +  Unreachable blocks stay in a Cmm graph's block map for most of the Cmm
    
    7
    +  pipeline, but ``-ddump-cmm-*`` only ever printed the blocks reachable from
    
    8
    +  the graph's entry. Adding ``-dppr-debug`` now appends the stored but
    
    9
    +  unreachable blocks, which makes bugs like #27368 visible in the dumps.

  • compiler/GHC/Cmm.hs
    ... ... @@ -151,15 +151,24 @@ instance OutputableP Platform CmmGraph where
    151 151
     toBlockMap :: CmmGraph -> LabelMap CmmBlock
    
    152 152
     toBlockMap (CmmGraph {g_graph=GMany NothingO body NothingO}) = body
    
    153 153
     
    
    154
    +-- | Print the blocks reachable from the entry, in reverse postorder.  Under
    
    155
    +-- @-dppr-debug@ the blocks that are stored in the graph but unreachable are
    
    156
    +-- appended too; see Note [unreachable blocks] in "GHC.Cmm.Pipeline".
    
    154 157
     pprCmmGraph :: Platform -> CmmGraph -> SDoc
    
    155 158
     pprCmmGraph platform g
    
    156 159
        = text "{" <> text "offset"
    
    157
    -  $$ nest 2 (vcat $ map (pdoc platform) blocks)
    
    160
    +  $$ nest 2 (vcat (map (pdoc platform) blocks) $$ unreachable)
    
    158 161
       $$ text "}"
    
    159
    -  where blocks = revPostorder g
    
    160
    -    -- revPostorder has the side-effect of discarding unreachable code,
    
    161
    -    -- so pretty-printed Cmm will omit any unreachable blocks.  This can
    
    162
    -    -- sometimes be confusing.
    
    162
    +  where
    
    163
    +    blocks = revPostorder g
    
    164
    +
    
    165
    +    unreachable = getPprDebug $ \debug ->
    
    166
    +      if not debug || mapNull dead_blocks
    
    167
    +        then empty
    
    168
    +        else text "// unreachable blocks:"
    
    169
    +          $$ nest 2 (vcat $ map (pdoc platform) (mapElems dead_blocks))
    
    170
    +
    
    171
    +    dead_blocks = foldr (mapDelete . entryLabel) (toBlockMap g) blocks
    
    163 172
     
    
    164 173
     revPostorder :: CmmGraph -> [CmmBlock]
    
    165 174
     revPostorder g = {-# SCC "revPostorder" #-}
    

  • compiler/GHC/Cmm/Pipeline.hs
    ... ... @@ -350,13 +350,15 @@ _GLOBAL_OFFSET_TABLE_, regardless of which entry point we arrived via.
    350 350
     
    
    351 351
     -}
    
    352 352
     
    
    353
    -{- Note [unreachable blocks]
    
    354
    -   ~~~~~~~~~~~~~~~~~~~~~~~~~
    
    353
    +{-
    
    354
    +Note [unreachable blocks]
    
    355
    +~~~~~~~~~~~~~~~~~~~~~~~~~
    
    355 356
     The control-flow optimiser sometimes leaves unreachable blocks behind
    
    356 357
     containing junk code.  These aren't necessarily a problem, but
    
    357 358
     removing them is good because it might save time in the native code
    
    358 359
     generator later.
    
    359 360
     
    
    361
    +To make unreachable blocks visible in -ddump-cmm-* output, add -dppr-debug.
    
    360 362
     -}
    
    361 363
     
    
    362 364
     dumpGraph :: Logger -> Platform -> Bool -> DumpFlag -> String -> CmmGraph -> IO ()
    

  • docs/users_guide/debugging.rst
    ... ... @@ -564,6 +564,11 @@ C-\- representation
    564 564
     
    
    565 565
     These flags dump various phases of GHC's C-\- pipeline.
    
    566 566
     
    
    567
    +Cmm dumps print the blocks reachable from a graph's entry, in reverse
    
    568
    +post-order. Blocks can linger in a graph without being reachable; adding
    
    569
    +:ghc-flag:`-dppr-debug` to any of these dump flags additionally prints those,
    
    570
    +under a ``// unreachable blocks:`` heading.
    
    571
    +
    
    567 572
     .. ghc-flag:: -ddump-cmm-verbose-by-proc
    
    568 573
         :shortdesc: Show output from main C-\- pipeline passes (grouped by proc)
    
    569 574
         :type: dynamic
    
    ... ... @@ -574,9 +579,6 @@ These flags dump various phases of GHC's C-\- pipeline.
    574 579
         the chosen backend. Currently only the NCG backends runs
    
    575 580
         additional passes ( :ghc-flag:`-ddump-opt-cmm` ).
    
    576 581
     
    
    577
    -    Cmm dumps don't include unreachable blocks since we print
    
    578
    -    blocks in reverse post-order.
    
    579
    -
    
    580 582
     .. ghc-flag:: -ddump-cmm-verbose
    
    581 583
         :shortdesc: Write output from main C-\- pipeline passes to files
    
    582 584
         :type: dynamic
    

  • testsuite/tests/cmm/should_compile/T27368-ppr-debug.cmm
    1
    +#include "Cmm.h"
    
    2
    +
    
    3
    +// The block "dead" is stored in the graph but no block branches to it, so it
    
    4
    +// only shows up in Cmm dumps under -dppr-debug.
    
    5
    +testUnreachable (W_ x)
    
    6
    +{
    
    7
    +  if (x > 0) {
    
    8
    +    goto live;
    
    9
    +  }
    
    10
    +  return (x);
    
    11
    +
    
    12
    +dead:
    
    13
    +  x = x + 42;
    
    14
    +  return (x);
    
    15
    +
    
    16
    +live:
    
    17
    +  x = x - 1;
    
    18
    +  return (x);
    
    19
    +}

  • testsuite/tests/cmm/should_compile/T27368-ppr-debug.stderr
    1
    +// unreachable blocks:

  • testsuite/tests/cmm/should_compile/all.T
    ... ... @@ -13,6 +13,9 @@ test('T20725', normal, compile, ['-package ghc'])
    13 13
     test('T23610', normal, makefile_test, ['T23610'])
    
    14 14
     test('T24224', [cmm_src, grep_errmsg(r'(F64.*);', [1]), only_ways(['normal'])], compile, ['-no-hs-main -ddump-cmm -dsuppress-all -dsuppress-uniques'])
    
    15 15
     test('T24474', cmm_src, compile, ['-optc-g3'])
    
    16
    +# -dppr-debug makes stored-but-unreachable blocks visible in Cmm dumps (#27368)
    
    17
    +test('T27368-ppr-debug', [cmm_src, grep_errmsg(r'(// unreachable blocks:)', [1]), only_ways(['normal'])],
    
    18
    +     compile, ['-no-hs-main -ddump-cmm-verbose-by-proc -dppr-debug -dsuppress-uniques'])
    
    16 19
     test('T24474-cmm-gets-c-opts', cmm_src, compile, ['-optc-DFOO'])
    
    17 20
     test('T24474-cmm-opt-order', cmm_src, compile, ['-optc-DFOO '
    
    18 21
                                                     '-optCmmP-UFOO '