I am testing the following patch to fix wrong-debug creatd by
loop-distribution simply dropping debug stmts on the floor
making earlier ones with bogus value live.

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

2019-04-15  Richard Biener  <rguent...@suse.de>

        PR debug/90074
        * tree-loop-distribution.c (destroy_loop): Preserve correct
        debug info.

        * gcc.dg/guality/pr90074.c: New testcase.

Index: gcc/tree-loop-distribution.c
===================================================================
--- gcc/tree-loop-distribution.c        (revision 270358)
+++ gcc/tree-loop-distribution.c        (working copy)
@@ -1094,12 +1094,8 @@ destroy_loop (struct loop *loop)
 
   bbs = get_loop_body_in_dom_order (loop);
 
-  redirect_edge_pred (exit, src);
-  exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
-  exit->flags |= EDGE_FALLTHRU;
-  cancel_loop_tree (loop);
-  rescan_loop_exit (exit, false, true);
-
+  gimple_stmt_iterator dst_gsi = gsi_after_labels (exit->dest);
+  bool safe_p = single_pred_p (exit->dest);
   i = nbbs;
   do
     {
@@ -1116,14 +1112,45 @@ destroy_loop (struct loop *loop)
          if (virtual_operand_p (gimple_phi_result (phi)))
            mark_virtual_phi_result_for_renaming (phi);
        }
-      for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);
-          gsi_next (&gsi))
+      for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);)
        {
          gimple *stmt = gsi_stmt (gsi);
          tree vdef = gimple_vdef (stmt);
          if (vdef && TREE_CODE (vdef) == SSA_NAME)
            mark_virtual_operand_for_renaming (vdef);
+         /* Also move and eventually reset debug stmts.  We can leave
+            constant values in place in case the stmt dominates the exit.
+            ???  Non-constant values from the last iteration can be
+            replaced with final values if we can compute them.  */
+         if (gimple_debug_bind_p (stmt))
+           {
+             tree val = gimple_debug_bind_get_value (stmt);
+             gsi_move_before (&gsi, &dst_gsi);
+             if (val
+                 && (!safe_p
+                     || !is_gimple_min_invariant (val)
+                     || !dominated_by_p (CDI_DOMINATORS, exit->src, bbs[i])))
+               {
+                 gimple_debug_bind_reset_value (stmt);
+                 update_stmt (stmt);
+               }
+           }
+         else
+           gsi_next (&gsi);
        }
+    }
+  while (i != 0);
+
+  redirect_edge_pred (exit, src);
+  exit->flags &= ~(EDGE_TRUE_VALUE|EDGE_FALSE_VALUE);
+  exit->flags |= EDGE_FALLTHRU;
+  cancel_loop_tree (loop);
+  rescan_loop_exit (exit, false, true);
+
+  i = nbbs;
+  do
+    {
+      --i;
       delete_basic_block (bbs[i]);
     }
   while (i != 0);
Index: gcc/testsuite/gcc.dg/guality/pr90074.c
===================================================================
--- gcc/testsuite/gcc.dg/guality/pr90074.c      (nonexistent)
+++ gcc/testsuite/gcc.dg/guality/pr90074.c      (working copy)
@@ -0,0 +1,31 @@
+/* { dg-do run } */
+/* { dg-options "-g" } */
+
+void __attribute__((noinline))
+optimize_me_not ()
+{
+  __asm__ volatile ("" : : : "memory");
+}
+char a;
+short b[7][1];
+int main()
+{
+  int i, c;
+  a = 0;
+  i = 0;
+  for (; i < 7; i++) {
+      c = 0;
+      for (; c < 1; c++)
+       b[i][c] = 0;
+  }
+  /* i may very well be optimized out, so we cannot test for i == 7.
+     Instead test i + 1 which will make the test UNSUPPORTED if i
+     is optimized out.  Since the test previously had wrong debug
+     with i == 0 this is acceptable.  Optimally we'd produce a
+     debug stmt for the final value of the loop during loop distribution
+     which would fix the UNSUPPORTED cases.
+     c is optimized out at -Og for no obvious reason.  */
+  optimize_me_not(); /* { dg-final { gdb-test . "i + 1" "8" } } */
+    /* { dg-final { gdb-test .-1 "c + 1" "2" } } */
+  return 0;
+}

Reply via email to