aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.dg/guality/loop-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr89892.c34
-rw-r--r--gcc/testsuite/gcc.dg/guality/pr89905.c39
-rw-r--r--gcc/tree-cfgcleanup.c30
6 files changed, 138 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4dbd3a0..53b58ef 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+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.
+
2019-04-05 Martin Liska <mliska@suse.cz>
PR translation/89936
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index af77f02..e19a1b8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2019-04-05 Richard Biener <rguenther@suse.de>
+
+ 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 <richard.sandiford@arm.com>
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 0000000..8da447d
--- /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 0000000..9bb27fd
--- /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 0000000..e718359
--- /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 f7bd565..3c291f5 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));
}