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

Commits:

8 changed files:

Changes:

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

  • compiler/GHC/Cmm.hs
    ... ... @@ -151,15 +151,28 @@ 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.
    
    155
    +--
    
    156
    +-- Under @-dppr-debug@ the unreachable blocks stored in the graph are appended
    
    157
    +-- too. See Note [unreachable blocks] in "GHC.Cmm.Pipeline".
    
    154 158
     pprCmmGraph :: Platform -> CmmGraph -> SDoc
    
    155 159
     pprCmmGraph platform g
    
    156 160
        = text "{" <> text "offset"
    
    157
    -  $$ nest 2 (vcat $ map (pdoc platform) blocks)
    
    161
    +  $$ nest 2 (ppr_blocks blocks $$ unreachable)
    
    158 162
       $$ 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.
    
    163
    +  where
    
    164
    +    ppr_blocks :: [CmmBlock] -> SDoc
    
    165
    +    ppr_blocks = vcat . map (pdoc platform)
    
    166
    +
    
    167
    +    blocks = revPostorder g
    
    168
    +
    
    169
    +    unreachable = getPprDebug $ \debug ->
    
    170
    +      if not debug || mapNull dead_blocks
    
    171
    +        then empty
    
    172
    +        else text "// unreachable blocks:"
    
    173
    +          $$ nest 2 (ppr_blocks (mapElems dead_blocks))
    
    174
    +
    
    175
    +    dead_blocks = foldl' (\bs b -> mapDelete (entryLabel b) bs) (toBlockMap g) blocks
    
    163 176
     
    
    164 177
     revPostorder :: CmmGraph -> [CmmBlock]
    
    165 178
     revPostorder g = {-# SCC "revPostorder" #-}
    

  • compiler/GHC/Cmm/Pipeline.hs
    ... ... @@ -357,6 +357,7 @@ containing junk code. These aren't necessarily a problem, but
    357 357
     removing them is good because it might save time in the native code
    
    358 358
     generator later.
    
    359 359
     
    
    360
    +To make unreachable blocks visible in -ddump-cmm-* output, add -dppr-debug.
    
    360 361
     -}
    
    361 362
     
    
    362 363
     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
    +Dumps of Cmm graphs print the blocks reachable from the entry, in reverse
    
    568
    +post-order. To also show unreachable blocks, which can linger in the graph,
    
    569
    +add :ghc-flag:`-dppr-debug`. These blocks are then listed under a
    
    570
    +``// 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/Makefile
    ... ... @@ -16,3 +16,16 @@ T16930:
    16 16
     
    
    17 17
     T23610:
    
    18 18
     	'$(TEST_HC)' $(TEST_HC_OPTS) T23610.cmm -S
    
    19
    +
    
    20
    +# The three seds below, in order:
    
    21
    +#  1. Keep only the "Parsed Cmm" dump, since that is the one stage where the
    
    22
    +#     unreachable block still exists.
    
    23
    +#  2. Rewrite goto targets: their label uniques survive -dsuppress-uniques
    
    24
    +#     (#21310).
    
    25
    +#  3. Drop the "// CmmAssign"-style node annotations, which pprNode emits
    
    26
    +#     only on DEBUG compilers.
    
    27
    +T27368-ppr-debug:
    
    28
    +	'$(TEST_HC)' $(TEST_HC_OPTS) -c -no-hs-main -ddump-cmm-verbose-by-proc -dppr-debug -dsuppress-uniques -dsuppress-ticks T27368-ppr-debug.cmm 2>&1 \
    
    29
    +	| sed -n '/^==* Parsed Cmm/,/^ \}\]/p' \
    
    30
    +	| sed 's/goto c[0-9A-Za-z]*/goto _lbl_/g' \
    
    31
    +	| sed 's| *// Cmm[A-Za-z]*$$||'

  • 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.stdout
    1
    +==================== Parsed Cmm ====================
    
    2
    +[testUnreachable() { //  [R1]
    
    3
    +         { info_tbls: []
    
    4
    +           stack_info: arg_space: 8
    
    5
    +         }
    
    6
    +     {offset
    
    7
    +       _lbl_:
    
    8
    +           __locVar_::I64 = R1;
    
    9
    +           if (__locVar_::I64 > 0) goto _lbl_; else goto _lbl_;
    
    10
    +       _lbl_:
    
    11
    +           goto _lbl_;
    
    12
    +       _lbl_:
    
    13
    +           __locVar_::I64 = __locVar_::I64 - 1;
    
    14
    +           R1 = __locVar_::I64;
    
    15
    +           call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8;
    
    16
    +       _lbl_:
    
    17
    +           goto _lbl_;
    
    18
    +       _lbl_:
    
    19
    +           R1 = __locVar_::I64;
    
    20
    +           call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8;
    
    21
    +       // unreachable blocks:
    
    22
    +         _lbl_:
    
    23
    +             __locVar_::I64 = __locVar_::I64 + 42;
    
    24
    +             R1 = __locVar_::I64;
    
    25
    +             call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8;
    
    26
    +     }
    
    27
    + }]

  • 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
    +# Skipped on wordsize(32) targets, where the dump would say I32/P32.
    
    18
    +test('T27368-ppr-debug', [when(wordsize(32), skip)], makefile_test, ['T27368-ppr-debug'])
    
    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 '