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

Manuel López-Ibáñez <manu at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |manu at gcc dot gnu.org
         Depends on|                            |24639
            Summary|[4.9/5 Regression] may be   |[4.9/5 Regression] wrong
                   |used uninitialized warning  |may be used uninitialized
                   |on variable definition with |warning (abnormal edges)
                   |initializer                 |

--- Comment #5 from Manuel López-Ibáñez <manu at gcc dot gnu.org> ---
(In reply to Ulrich Weigand from comment #4)
> Huh?  No matter what, "buf" is in fact never used uninitialized in this
> function, and that should be trivial to see; the only use of "buf" occurs in
> line 17 immediately after the definition of "buf" in line 16, whether any
> longjmp is ever called or not.
> 
> Also, if any of the gotos in this function is removed, the warning
> disappears.  The problem seems to be related to some call-graph
> optimizations (note that the if (noside) check is partially redundant).

The problem arises because we create PHI nodes with default definitions of buf
for the basic block created by the gotos. For example:

;;   basic block 6, loop depth 0, count 0, freq 0, maybe hot
;;    prev block 5, next block 7, flags: (NEW, REACHABLE)
;;    pred:       3 (ABNORMAL)
;;                8 (ABNORMAL)
;;   starting at line -1
  # argvec_2(ab) = PHI <[test.c:9:9] argvec_13(ab)(3), argvec_3(ab)(8)>
  # buf_5(ab) = PHI <buf_18(D)(ab)(3), buf_6(ab)(8)>
  # .MEM_9(ab) = PHI <.MEM_16(ab)(3), .MEM_25(ab)(8)>
  # .MEM_20(ab) = VDEF <.MEM_9(ab)>
  # USE = anything
  # CLB = anything
  ABNORMAL_DISPATCHER (0);
;;    succ:       5 (ABNORMAL)

and no subsequent optimization is able to realize that those PHI nodes are
never used or to remove the edges as unreachable.

I think this is some issue with how the call-graph is built. A simplified
version of 015t.ssa:

test (intD.6 opD.1753, intD.6 nosideD.1754)
{
;;   basic block 2, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       ENTRY (FALLTHRU)
;;   starting at line 9
  [test.c:11:6] if (op_14(D) != 0)
    goto <bb 3>;
  else
    goto <bb 10>;

;;   basic block 3, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       2 (TRUE_VALUE)
;;   starting at line 13
  [test.c:13:16] # .MEM_16(ab) = VDEF <.MEM_15(D)>
  _17 = alloc_jmp_bufD.1750 ();
;;    succ:       4 (FALLTHRU)
;;                6 (ABNORMAL)

;;   basic block 4, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       3 (FALLTHRU)
;;   starting at line 13, discriminator 1
  [test.c:13:16] buf_19 = _17;
;;    succ:       5 (FALLTHRU)

;;   basic block 5, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       4 (FALLTHRU)
;;                6 (ABNORMAL)
;;   starting at line 14
  # buf_4(ab) = PHI <[test.c:13:16] buf_19(4), buf_5(ab)(6)>
  setjmpD.1749 (buf_4(ab));
  [test.c:16:10] if (noside_22(D) != 0)
    goto <bb 11> (nosideret);
  else
    goto <bb 7> (do_call_it);
;;    succ:       11 (TRUE_VALUE)
;;                7 (FALSE_VALUE)

;;   basic block 6, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       3 (ABNORMAL)
;;                8 (ABNORMAL)
;;   starting at line -1
  # buf_5(ab) = PHI <buf_18(D)(ab)(3), buf_6(ab)(8)>
  ABNORMAL_DISPATCHER (0);
;;    succ:       5 (ABNORMAL)

;;   basic block 7, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       5 (FALSE_VALUE)
;;                10 (FALLTHRU)
;;   starting at line 21
  # buf_6(ab) = PHI <buf_4(ab)(5), buf_18(D)(ab)(10)>
do_call_itL.2:
  [test.c:21:10] if (noside_22(D) != 0)
    goto <bb 11> (nosideret);
  else
    goto <bb 8>;
;;    succ:       11 (TRUE_VALUE)
;;                8 (FALSE_VALUE)

;;   basic block 8, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       7 (FALSE_VALUE)
;;   starting at line 24
  _26 = fooD.1752 (argvec_3(ab));
;;    succ:       9 (FALLTHRU)
;;                6 (ABNORMAL)

;;   basic block 9, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       8 (FALLTHRU)
;;   starting at line 24, discriminator 1
  [test.c:24:14] _27 = _26;
  [test.c:24:14] goto <bb 12>;
;;    succ:       12 (FALLTHRU)

;;   basic block 10, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       2 (FALSE_VALUE)
;;   starting at line 27
  argvec_24 = allocaD.858 (1);
  [test.c:28:3] goto <bb 7> (do_call_it);
;;    succ:       7 (FALLTHRU)

;;   basic block 11, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       5 (TRUE_VALUE)
;;                7 (TRUE_VALUE)
;;   starting at line 31
nosideretL.5:
  [test.c:31:10] _28 = 1;
;;    succ:       12 (FALLTHRU)

;;   basic block 12, loop depth 0, count 0, freq 0, maybe hot
;;    pred:       9 (FALLTHRU)
;;                11 (FALLTHRU)
;;   starting at line -1
  # _7 = PHI <[test.c:24:14] _27(9), [test.c:31:10] _28(11)>
  return _7;
;;    succ:       EXIT

}

which is more or less:


test (intD.6 opD.1753, intD.6 nosideD.1754)
{
bb1:
 if (op_14(D) != 0)
 {
     try {
         _17 = alloc_jmp_bufD.1750 (); 
         [test.c:13:16] buf_19 = _17;
         goto bb5;
     } catch {
         goto bb6;
     }
 } else {
      argvec_24 = allocaD.858 (1);
      [test.c:28:3] goto do_call_it;
  }

bb5:
  # buf_4(ab) = PHI <[test.c:13:16] buf_19(bb1), buf_5(ab)(6)>
  setjmpD.1749 (buf_4(ab));
  [test.c:16:10] if (noside_22(D) != 0)
    goto nosideret;
  else
    goto do_call_it;

bb6:
  # buf_5(ab) = PHI <buf_18(D)(ab)(bb1), buf_6(ab)(bb8)>
  ABNORMAL_DISPATCHER (0);
  goto bb5:

do_call_it:
  # buf_6(ab) = PHI <buf_4(ab)(5), buf_18(D)(ab)(10)>
  [test.c:21:10] if (noside_22(D) != 0)
    goto nosideret;
  else
    goto bb8;

bb8:
  try {
        [test.c:24:14] _7 = fooD.1752 (argvec_3(ab));
        [test.c:24:14] goto bb12;
  } catch { 
    goto bb6; 
  }

nosideret:
  [test.c:31:10] _7 = 1;
bb12:
  return _7;

}

Thus, it is clear that buf can be used uninitialized if the abnormal edge is
taken (represented by the first try-catch). Now, I don't have any idea why
there is an abnormal edge there. I guess this is what Andrew was explaining
about alloc_jmp_buf.

If it is indeed needed, then there may be a missing optimization later (someone
else would need to compare the -fdump-tree-all-all files when removing one of
the gotos).

Perhaps, as a work-around, the uninit pass could ignore default definitions
that come from abnormal edges, but I'm not sure if this will cause some false
negatives.

Reply via email to