Bug 89892 - gcc generates wrong debug information at -O2
Summary: gcc generates wrong debug information at -O2
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: debug (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Richard Biener
URL: https://gcc.gnu.org/ml/gcc-patches/20...
Keywords: wrong-debug
: 88882 89454 89905 (view as bug list)
Depends on:
Blocks: 88882 89905
  Show dependency treegraph
 
Reported: 2019-03-30 16:30 UTC by Qirun Zhang
Modified: 2019-04-11 23:41 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 9.0
Known to fail: 8.3.0
Last reconfirmed: 2019-04-01 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Qirun Zhang 2019-03-30 16:30:28 UTC
It seems to be a recent regression. Bisect points to r260357.

It affects "-O2" only. 

The correct output is "i=0". At "-O2", it prints "i=2".


$ gcc-trunk -v
gcc version 9.0.1 20190330 (experimental) [trunk revision 270031] (GCC)
$ gdb -v
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1


#Correct output#
$ gcc-trunk -g abc.c outer.c
$ gdb -x cmds -batch a.out
Breakpoint 1 at 0x400519: file abc.c, line 19.

Breakpoint 1, main () at abc.c:19
19	  optimize_me_not();
$1 = 0


#Incorrect output at -O2#
$ gcc-trunk -g abc.c outer.c -O2
$ gdb -x cmds -batch a.out
Breakpoint 1 at 0x40047d: file abc.c, line 19.

Breakpoint 1, main () at abc.c:19
19	  optimize_me_not();
$1 = 2


$ cat abc.c
volatile int a;
static short b[3][9][1] = {5};
int c;
int main() {
  int i, d;
  i = 0;
  for (; i < 3; i++) {
    c = 0;
    for (; c < 9; c++) {
      d = 0;
      for (; d < 1; d++)
        a = b[i][c][d];
    }
  }
  i = c = 0;
  for (; c < 7; c++)
    for (; d < 6; d++)
      a;
  optimize_me_not();
}

$ cat cmds
b 19
r
p i
kill
q
Comment 1 Richard Biener 2019-04-01 07:48:25 UTC
Confirmed.  The issue is we end up with

<bb 6> [local count: 14598062]:
# DEBUG BEGIN_STMT
# DEBUG i => 0
# DEBUG BEGIN_STMT
# DEBUG d => 1
goto <bb 9>; [100.00%]

as a forwarder block which CFG cleanup is about to remove.  But both
single predecessor and successor edges are critical so we cannot move
the debug stmts.  Instead we removed them...

Conservatively we'd have to still move them but instead of inserting
i => 0 we'd have to insert i => NULL, possibly trading debug info
quality in the predecessor/successor for debug info correctness.

As said elsewhere having debug stmts on edges might be a solution to this...

We could also in general avoid removing forwarders connecting two blocks
we could not move debug stmts to (but we'd have to do this irrespective
of their presence).  The same issue likely exists on RTL where not
eliminating such forwarder might become costly (unless we can convince us BB
reorder can fixup things so no extra jump will occur with/without such
forwarder).

In this particular case liveness analysis could tell us moving the i => 0
to the successor is OK and moving the d association to the predecessor
is as well (because it already exists there).  But that's something we
generally do not want to do (in CFG cleanup anyways).

IIRC I've seen this forwarder-removal in a duplicate bug.

tree_forwarder_block_p explicitely spells out the issue:

          /* ??? For now, hope there's a corresponding debug
             assignment at the destination.  */
        case GIMPLE_DEBUG:
          break;
Comment 2 Richard Biener 2019-04-03 10:00:31 UTC
Testing patch.
Comment 3 Richard Biener 2019-04-03 10:35:08 UTC
*** Bug 89905 has been marked as a duplicate of this bug. ***
Comment 4 Richard Biener 2019-04-03 10:35:24 UTC
*** Bug 88882 has been marked as a duplicate of this bug. ***
Comment 5 Richard Biener 2019-04-03 10:36:10 UTC
Patch in testing / eventual discussion.
Comment 6 Richard Biener 2019-04-05 11:56:17 UTC
Author: rguenth
Date: Fri Apr  5 11:55:45 2019
New Revision: 270165

URL: https://gcc.gnu.org/viewcvs?rev=270165&root=gcc&view=rev
Log:
2019-04-05  Richard Biener  <rguenther@suse.de>

	PR debug/89892
	PR debug/89905
	* tree-cfgcleanup.c (remove_forwarder_block): Always move
	debug bind stmts but reset them if they are not valid at the
	destination.

	* gcc.dg/guality/pr89892.c: New testcase.
	* gcc.dg/guality/pr89905.c: Likewise.
	* gcc.dg/guality/loop-1.c: Likewise.

Added:
    trunk/gcc/testsuite/gcc.dg/guality/loop-1.c
    trunk/gcc/testsuite/gcc.dg/guality/pr89892.c
    trunk/gcc/testsuite/gcc.dg/guality/pr89905.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-cfgcleanup.c
Comment 7 Richard Biener 2019-04-08 07:34:48 UTC
Fixed.
Comment 8 Alexandre Oliva 2019-04-11 23:41:21 UTC
*** Bug 89454 has been marked as a duplicate of this bug. ***