https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116799

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Actually, seems loop-doloop.cc doesn't look at REG_DEAD notes, but at live out.
  /* Ensure that the new sequence doesn't clobber a register that
     is live at the end of the block.  */
  {
    bitmap modified = BITMAP_ALLOC (NULL);

    for (rtx_insn *i = doloop_seq; i != NULL; i = NEXT_INSN (i))
      note_stores (i, record_reg_sets, modified);

    basic_block loop_end = desc->out_edge->src;
    bool fail = bitmap_intersect_p (df_get_live_out (loop_end), modified);
    BITMAP_FREE (modified);

    if (fail)
      {
        if (dump_file)
          fprintf (dump_file, "Doloop: doloop pattern clobbers live out\n");
        return false;
      }
  }
Now, in loop2_init dump I still see the expected
(jump_insn 38 37 42 5 (set (pc)
        (if_then_else (ltu (reg:CCU 33 %cc)
                (const_int 0 [0]))
            (label_ref 36)
            (pc))) "pr116799.c":15:22 discrim 1 2173 {*cjump_64}
     (int_list:REG_BR_PROB 1014686028 (nil))
 -> 36)
;; lr  out       11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
;; live  out     11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
and
;; basic block 16, loop depth 0, count 55807731 (estimated locally, freq
0.4859), maybe hot
;;  prev block 15, next block 1, flags: (REACHABLE, RTL, MODIFIED)
;;  pred:       5 [5.5% (guessed)]  count:55807731 (estimated locally, freq
0.4859) (FALLTHRU,LOOP_EXIT)
;; bb 16 artificial_defs: { }
;; bb 16 artificial_uses: { u-1(11){ }u-1(15){ }u-1(32){ }u-1(34){ }}
;; lr  in        11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
;; lr  use       11 [%r11] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp]
;; lr  def      
;; live  in      11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
;; live  gen    
;; live  kill   
i.e. 33 [%cc] is live on the edge.
But loop2_invariant dump already doesn't:
(jump_insn 38 37 42 5 (set (pc)
        (if_then_else (ltu (reg:CCU 33 %cc)
                (const_int 0 [0]))
            (label_ref 36)
            (pc))) "pr116799.c":15:22 discrim 1 2173 {*cjump_64}
     (int_list:REG_BR_PROB 1014686028 (nil))
 -> 36)
;;  succ:       3 [94.5% (guessed)]  count:958878294 (estimated locally, freq
8.3480)
;;              16 [5.5% (guessed)]  count:55807731 (estimated locally, freq
0.4859) (FALLTHRU,LOOP_EXIT)
;; lr  out       11 [%r11] 15 [%r15] 32 [%ap] 34 [%fp] 65 68
;; live  out     68
and
;; basic block 16, loop depth 0, count 55807731 (estimated locally, freq
0.4859), maybe hot
;;  prev block 15, next block 1, flags: (REACHABLE, RTL, MODIFIED)
;;  pred:       5 [5.5% (guessed)]  count:55807731 (estimated locally, freq
0.4859) (FALLTHRU,LOOP_EXIT)
;; bb 16 artificial_defs: { }
;; bb 16 artificial_uses: { u-1(11){ }u-1(15){ }u-1(32){ }u-1(34){ }}
;; lr  in        11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
;; lr  use       11 [%r11] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp]
;; lr  def      
;; live  in      11 [%r11] 14 [%r14] 15 [%r15] 32 [%ap] 33 [%cc] 34 [%fp] 65 68
69
;; live  gen    
;; live  kill   
Well, it is in live in of bb16, but not in live out of bb 5.
And one can see the same state in loop-doloop.cc:
Breakpoint 5, doloop_optimize (loop=0x7fffea546260) at
../../gcc/loop-doloop.cc:802
802         bool fail = bitmap_intersect_p (df_get_live_out (loop_end),
modified);
(gdb) p debug (desc->out_edge)
<edge (5 -> 16)>
 5 [5.5% (guessed)]  count:5625631 (estimated locally, freq 0.0490)
(FALLTHRU,LOOP_EXIT)
$2 = void
(gdb) p debug (df_get_live_out (desc->out_edge->src))
68
$3 = void
(gdb) p debug (df_get_live_in (desc->out_edge->dest))
11, 14, 15, 32, 33, 34, 65, 68, 69
$4 = void
(gdb) p debug (modified)
33, 93
$5 = void
I.e. if one would instead check df_get_live_in of the out_edge's destination,
it would punt.
Maybe the bug is caused by the introduction of df_analyze_loop in PR38518?
I mean if a pass itself only cares about df within a loop, it might be fine,
but e.g. looking at the live_out/lr_out whether something is live on the exit
edge is not.
Certainly the change of df_get_live_out from
11, 14, 15, 32, 33, 34, 65, 68, 69
to
68
happens during  df_analyze_1 called from df_analyze_loop on the loop with bb 5
header (i.e. the block whose df_get_live_out changed).
But unfortunately it isn't just loop2_invariant which uses df_analyze_loop, but
also
loop-iv.cc used by most of the loop passes.
If it was just loop2_invariant, perhaps we could just do full df_analyze at the
end of the pass, but as loop-doloop.cc will
  iv_analysis_loop_init (loop);
which does that df_analyze_loop, but then wants to check the live registers in
  /* Ensure that the new sequence doesn't clobber a register that
     is live at the end of the block.  */
  {              
    bitmap modified = BITMAP_ALLOC (NULL);

    for (rtx_insn *i = doloop_seq; i != NULL; i = NEXT_INSN (i))
      note_stores (i, record_reg_sets, modified);

    basic_block loop_end = desc->out_edge->src;
    bool fail = bitmap_intersect_p (df_get_live_out (loop_end), modified);
    BITMAP_FREE (modified);

    if (fail)
      {
        if (dump_file)
          fprintf (dump_file, "Doloop: doloop pattern clobbers live out\n");
        return false;
      }
  }
I'm not sure what can be done.
Perhaps doing that df_get_live_in (desc->out_edge->dest) instead would help a
little
bit (like in this case), but am not sure if it say work also if the exit edge's
destination is in some outer loop and the register use only on the exit edge of
the outer loop.

Reply via email to