[Bug middle-end/90191] [9/10 regression] incorrect -Wformat-overflow with --param max-jump-thread-duplication-stmts=17

2019-04-26 Thread law at redhat dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90191

--- Comment #6 from Jeffrey A. Law  ---
NP.  It happens to all of us at some point :-)

[Bug middle-end/90191] [9/10 regression] incorrect -Wformat-overflow with --param max-jump-thread-duplication-stmts=17

2019-04-26 Thread dimhen at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90191

--- Comment #5 from Dmitry G. Dyachenko  ---
(In reply to Jeffrey A. Law from comment #4)
> Actually I think the warning is valid.  Ramping up the aggressiveness of the
> threader is what ultimately exposes it.
[...]
> 
> But AFAICT the warning is 100% totally valid.  You just have to turn up the
> optimizer thresholds to expose it.

Jeff, thank you for clarification.
You are absolutely right -- my test is invalid.

Sorry for over-reducing

[Bug middle-end/90191] [9/10 regression] incorrect -Wformat-overflow with --param max-jump-thread-duplication-stmts=17

2019-04-25 Thread law at redhat dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90191

Jeffrey A. Law  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 CC||law at redhat dot com
 Resolution|--- |INVALID

--- Comment #4 from Jeffrey A. Law  ---
Actually I think the warning is valid.  Ramping up the aggressiveness of the
threader is what ultimately exposes it.

This code...

m = a ? t::u() : 0;
n.l = m;

Note how we can store 0 into "m" and we then store that into n.l.  Which is
then read by these statements:

char  = d[0];
printf("%s = %s\n", , );

And thus we have a path where e can potentially be NULL.

This can be seen in the IPA inlining pass:

  [local count: 1073741824]:
  MEM[(struct  &)] ={v} {CLOBBER};
  _6 = x::y ();
  MEM[(struct  &)] ={v} {CLOBBER};
  if (_6 != 0)
goto ; [33.00%]
  else
goto ; [67.00%]

   [local count: 354334802]:
  _7 = t::u ();

   [local count: 1073741824]:
  # iftmp.1_8 = PHI <0B(2), _7(3)>
  m = iftmp.1_8;
  MEM[(struct v *)].n.l = iftmp.1_8;
  s.0_9 = s;
  ad (0, 0, s.0_9, D.2603);
  goto ; [100.00%]

   [count: 0]:
:
  c_10 = MEM[(struct v *)].n.l;
  if (c_10 != 0B)
goto ; [0.00%]
  else
goto ; [0.00%]

   [count: 0]:
  *c_10 ={v} {CLOBBER};
  operator delete (c_10, 1);

   [count: 0]:
  MEM[(struct  &)] ={v} {CLOBBER};
  resx 2

   [local count: 1073741824]:
  _3 = MEM[(char * *)];
  printf ("%s = %s\n", , _3);

See how bb4 stores iftmp.1_8 into d.n.l.  iftmp.1_8 when reached from block 2
has the value NULL.

Then in bb8 we read that value and pass it to printf.

Of course in the form above, the warning isn't going to fire.

In .mergephi2 we have (unnecessary stuff skipped):

;;   basic block 2, loop depth 0
;;pred:   ENTRY
  MEM[(struct  &)] ={v} {CLOBBER};
  _6 = x::y ();
  MEM[(struct  &)] ={v} {CLOBBER};
  if (_6 != 0)
goto ; [33.00%]
  else
goto ; [67.00%]
;;succ:   3
;;4

;;   basic block 3, loop depth 0
;;pred:   2
  _7 = t::u ();
;;succ:   4

;;   basic block 4, loop depth 0
;;pred:   2
;;3
  # iftmp.1_8 = PHI <0B(2), _7(3)>
  m = iftmp.1_8;
  MEM[(struct v *)].n.l = iftmp.1_8;
  s.0_9 = s;
  ad (0, 0, s.0_9, D.2603);
  goto ; [100.00%]
;;succ:   8
;;5

;;   basic block 5, loop depth 0
;;pred:   4
:
  if (iftmp.1_8 != 0B)
goto ; [0.00%]
  else
goto ; [0.00%]
;;succ:   6
;;7

;;   basic block 6, loop depth 0
;;pred:   5
  *iftmp.1_8 ={v} {CLOBBER};
  operator delete (iftmp.1_8, 1);
;;succ:   7

;;   basic block 7, loop depth 0
;;pred:   5
;;6
  MEM[(struct  &)] ={v} {CLOBBER};
  resx 2

Note carefully we have an EH edge (4,5).

The threader sees that the path 2->4->5 will always transfer control to bb7. 
So it's going to isolate path that by copying bb4.

THe block #s change a lot, but after ethread1 the relevant blocks:

;;   basic block 2, loop depth 0
;;pred:   ENTRY
  MEM[(struct  &)] ={v} {CLOBBER};
  _6 = x::y ();
  MEM[(struct  &)] ={v} {CLOBBER};
  if (_6 != 0)
goto ; [33.00%]
  else
goto ; [67.00%]
;;succ:   5
;;3

;;   basic block 3, loop depth 0
;;pred:   2 
  # iftmp.1_10 = PHI <0B(2)>
  m = iftmp.1_10;
  MEM[(struct v *)].n.l = iftmp.1_10;
  s.0_30 = s; 
  ad (0, 0, s.0_30, D.2603);
  goto ; [100.00%] 
;;succ:   9
;;4

;;   basic block 4, loop depth 0
;;pred:   3
: 
  goto ; [100.00%]
;;succ:   8

;;   basic block 5, loop depth 0
;;pred:   2
  _7 = t::u ();
  m = _7;
  MEM[(struct v *)].n.l = _7;
  s.0_9 = s;
  ad (0, 0, s.0_9, D.2603);
  goto ; [100.00%]
;;succ:   9
;;6
[ ... ]

;;   basic block 9, loop depth 0
;;pred:   5
;;3
  # iftmp.1_31 = PHI <_7(5), iftmp.1_10(3)>
  printf ("%s = %s\n", , iftmp.1_31);

Note how bb3 and bb5 have the same tail statements.  But they feed values into
the printf in bb9, in particular a NULL value for the path 2->3->9.  It becomes
more obvious after the VRP constant propagation:

;;   basic block 2, loop depth 0
;;pred:   ENTRY
  MEM[(struct  &)] ={v} {CLOBBER};
  _6 = x::y ();   
  MEM[(struct  &)] ={v} {CLOBBER};
  if (_6 != 0)
goto ; [33.00%]
  else
goto ; [67.00%]
;;succ:   5
;;3

;;   basic block 3, loop depth 0
;;pred:   2 
  m = 0B;
  MEM[(struct v *)].n.l = 0B;
  s.0_30 = s;
  ad (0, 0, s.0_30, D.2603);
  goto ; [100.00%]
;;succ:   9
;;4

;;   basic block 4, loop depth 0
;;pred:   3 
:
  goto ; [100.00%]
;;succ:   8

;;   basic block 5, loop depth 0
;;pred:   2
  _7 = t::u ();
  m = _7;
  MEM[(struct v *)].n.l = _7;
  s.0_9 = s;
  ad (0, 0, s.0_9,