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

--- Comment #4 from prathamesh3492 at gcc dot gnu.org ---
Hi,
I think this seems to be an issue with uninit pass.
The same behavior can be observed for following test-case on
x86_64-unknown-linux-gnu regardless of r241915.
(test-case is a slight modification of foo() defined in uninit-pred-8_a.c to
generate same CFG on x86_64 as on cortex-m7):

int f(int n, int m, int l, int r)
{
  int t1, t2, t3, t4, v;
  extern int g;
  void bar();
  void blah(int);

  if ((n || m) || (r || l))
    v = r;

  if (m != 0)
    g++;
  else
    bar (); 

  if ((n || m) || (r || l))
    blah (v);

  if (n != 0)
    blah (v);

  if (l != 0)
    blah (v);

  return 0;
}

-O2 -Wuninitialized gives:
foo2.c: In function ā€˜f’:
foo2.c:17:5: warning: ā€˜v’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
     blah (v);
     ^~~~~~~~

Input to uninit pass (dump of crited2 pass):
http://pastebin.com/wJBak3tS

v is assigned the value of r if either _1 is true or _2 is true in above cfg.

The warning at uninitialized use of v is for:
if ((n || m) || (r || l))
  blah(v);

IIUC, the above call to blah(v) is duplicated in two blocks: bb10 and bb16.

bb10 has only one predecessor bb7.
Looking at:
  <bb 6>:
  # v_32 = PHI <r_13(D)(18), v_15(D)(17), r_13(D)(15)>
  bar ();

  <bb 7>:
  # v_33 = PHI <r_13(D)(5), v_32(6)>
  if (_1 != 0)
    goto <bb 10>;
  else
    goto <bb 8>;

v is uninitialized if the control reaches to bb6 from bb17, ie 
the following path is taken: bb2 -> bb3 -> bb17 -> bb6 -> bb7
This path would be taken only if both _1 and _2 are 0.
Since control goes from bb7 to bb10 only if _1 is nonzero, we can never reach
bb10 if v is uninitialized.

Similarly bb16 has only one predecessor bb8 and bb8 has only one predecessor
bb7.
We reach bb8 from "false edge" of bb7, ie, if _1 is 0.

<bb 8>:
_5 = r_13(D) | l_14(D);
if (_5 != 0)
  goto <bb 16>;
else
  goto <bb 19>;

_5 is same as _2. I wonder why r_13(D) | l_14(D) is re-computed here instead of
using _2, which is assigned the same value ?
So if _5 is false, we should never reach bb16 and hence I think the warning is
a false positive.
Does this sound reasonable ?

Btw the warning isn't given if vrp is disabled.
Input to uninit pass after disabling vrp:
http://pastebin.com/index.php

IIC after disabling vrp, the cfg has only one block bb10 representing
the blah(v) call unlike in the first case of enabled vrp, which duplicated
bb10 and bb16 both containing calls to blah(v).

There's another strange issue I noticed about folding:
Consider following test-case:

int f(int n, int m, int l, int r)
{
  if (n || m || r || l)
    return 1;
  else
    return 0;
}

On x86_64,
ssa pass dump shows:
http://pastebin.com/Fuy6dGX1

truth_orif_expr's are converted to sequence of bit_ior_exprs:
  <bb 2>:
  _1 = n_5(D) | m_6(D);
  _2 = l_7(D) | _1;
  _3 = r_8(D) | _2;
  if (_3 != 0)
    goto <bb 3>;
  else
    goto <bb 4>;


However if the expression is parenthesized as:
if ((n || m) || (r || l)) then truth_orif_expr is not converted to sequence of
bit_ior_exprs as above.

x86_64 ssa dump for parenthesized expression:
http://pastebin.com/AsQ5qLFu

<bb 2>:
  _1 = n_4(D) | m_5(D);
  if (_1 != 0)
    goto <bb 4>;
  else
    goto <bb 3>;

  <bb 3>:
  _2 = l_6(D) | r_7(D);
  if (_2 != 0)
    goto <bb 4>;
  else
    goto <bb 5>;

Why should parenthesizing the sub-expressions make a difference ?

Thanks,
Prathamesh

Reply via email to