[PATCH] Fix PR90074

Richard Biener rguenther@suse.de
Mon Apr 15 09:38:00 GMT 2019


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  <rguenther@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;
+}



More information about the Gcc-patches mailing list