From 25eafae67f186cfa4c0fd0f89f743d7707d5bf21 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Fri, 5 Apr 2019 11:55:45 +0000 Subject: [PATCH] re PR debug/89892 (gcc generates wrong debug information at -O2) 2019-04-05 Richard Biener 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. From-SVN: r270165 --- gcc/ChangeLog | 8 ++++++ gcc/testsuite/ChangeLog | 8 ++++++ gcc/testsuite/gcc.dg/guality/loop-1.c | 22 +++++++++++++++ gcc/testsuite/gcc.dg/guality/pr89892.c | 34 ++++++++++++++++++++++ gcc/testsuite/gcc.dg/guality/pr89905.c | 39 ++++++++++++++++++++++++++ gcc/tree-cfgcleanup.c | 30 ++++++++++++++++++-- 6 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/guality/loop-1.c create mode 100644 gcc/testsuite/gcc.dg/guality/pr89892.c create mode 100644 gcc/testsuite/gcc.dg/guality/pr89905.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4dbd3a085c2..53b58ef3df0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2019-04-05 Richard Biener + + 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. + 2019-04-05 Martin Liska PR translation/89936 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index af77f0252ae..e19a1b824e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-04-05 Richard Biener + + PR debug/89892 + PR debug/89905 + * gcc.dg/guality/pr89892.c: New testcase. + * gcc.dg/guality/pr89905.c: Likewise. + * gcc.dg/guality/loop-1.c: Likewise. + 2019-04-05 Richard Sandiford PR tree-optimization/89956 diff --git a/gcc/testsuite/gcc.dg/guality/loop-1.c b/gcc/testsuite/gcc.dg/guality/loop-1.c new file mode 100644 index 00000000000..8da447d5379 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/loop-1.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-fno-tree-scev-cprop -fno-tree-vectorize -g" } */ + +#include "../nop.h" + +void __attribute__((noipa,noinline)) +foo (int n) +{ + if (n == 0) + return; + int i = 0; + do + { + ++i; /* { dg-final { gdb-test . "i" "0" } } */ + } + while (i < n); + /* The following works only with final value replacement or with the NOP + but not without (which means -Og). Vectorization breaks it, so disable + that. At -O3 it currently fails, PR89983. */ + __asm__ volatile (NOP : : "g" (i) : "memory"); /* { dg-final { gdb-test . "i" "1" } } */ +} +int main() { foo(1); } diff --git a/gcc/testsuite/gcc.dg/guality/pr89892.c b/gcc/testsuite/gcc.dg/guality/pr89892.c new file mode 100644 index 00000000000..9bb27fde436 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr89892.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +void __attribute__((noinline)) +optimize_me_not () +{ + __asm__ volatile ("" : : : "memory"); +} +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; + /* i may very well be optimized out, so we cannot test for i == 0. + Instead test i + 1 which will make the test UNSUPPORTED if i + is optimized out. Since the test previously had wrong debug + with i == 2 this is acceptable. Optimally we'd produce a + debug stmt for the final value of the loop which would fix + the UNSUPPORTED cases. */ + optimize_me_not(); /* { dg-final { gdb-test . "i + 1" "1" } } */ +} diff --git a/gcc/testsuite/gcc.dg/guality/pr89905.c b/gcc/testsuite/gcc.dg/guality/pr89905.c new file mode 100644 index 00000000000..e718359c9e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr89905.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +void __attribute__((noinline)) +optimize_me_not () +{ + __asm__ volatile ("" : : : "memory"); +} +char c, d = 22, f; +short e, g; +int h; +char(a)() {} +char(b)() { return 0; } +void i() { + char j; + for (; h < 1;) { + short k[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; + int l, i = 5; + short m[3] = {0, 0, 0}; + for (; h < 7; h++) + for (; d >= 33;) { + ++k[8]; + f = (c || a()) && g; + } + i++; + j = b() || m[2]; + l = 0; + for (; l <= 6; l = d) + e = k[8]; + /* i may very well be optimized out, so we cannot test for i == 6. + Instead test i + 1 which will make the test UNSUPPORTED if i + is optimized out. Since the test previously had wrong debug + with i == 5 this is acceptable. Optimally we'd produce a + debug stmt for the final value of the loop which would fix + the UNSUPPORTED cases. */ + optimize_me_not(); /* { dg-final { gdb-test . "i + 1" "7" } } */ + } +} +int main() { i(); } diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index f7bd5651a90..3c291f5473b 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -564,15 +564,39 @@ remove_forwarder_block (basic_block bb) gsi_next (&gsi); } - /* Move debug statements if the destination has a single predecessor. */ - if (can_move_debug_stmts && !gsi_end_p (gsi)) + /* Move debug statements. Reset them if the destination does not + have a single predecessor. */ + if (!gsi_end_p (gsi)) { gsi_to = gsi_after_labels (dest); do { gimple *debug = gsi_stmt (gsi); gcc_assert (is_gimple_debug (debug)); - gsi_move_before (&gsi, &gsi_to); + /* Move debug binds anyway, but not anything else + like begin-stmt markers unless they are always + valid at the destination. */ + if (can_move_debug_stmts + || gimple_debug_bind_p (debug)) + { + gsi_move_before (&gsi, &gsi_to); + /* Reset debug-binds that are not always valid at the + destination. Simply dropping them can cause earlier + values to become live, generating wrong debug information. + ??? There are several things we could improve here. For + one we might be able to move stmts to the predecessor. + For anther, if the debug stmt is immediately followed + by a (debug) definition in the destination (on a + post-dominated path?) we can elide it without any bad + effects. */ + if (!can_move_debug_stmts) + { + gimple_debug_bind_reset_value (debug); + update_stmt (debug); + } + } + else + gsi_next (&gsi); } while (!gsi_end_p (gsi)); } -- 2.30.2