Blob Blame History Raw
2009-09-30  Alexandre Oliva  <aoliva@redhat.com>

	* tree-dfa.c (referenced_var_p): New.
	(remove_referenced_var): Clear renaming mark.
	* tree-flow.h (referenced_var_p): Declare.
	(sym_marked_for_renaming, clear_mark_for_renaming): Declare.
	* tree-into-ssa.c (clear_mark_for_renaming): New.
	(sym_marked_for_renaming): New.
	* tree-ssa-operands.c (pop_stmt_changes): Reset debug stmts
	that reference otherwise-unreferenced variables.

	* gcc.dg/debug/vta-1.c: New.

--- gcc/tree-dfa.c.orig	2009-09-30 04:00:45.000000000 -0300
+++ gcc/tree-dfa.c	2009-09-30 04:01:21.000000000 -0300
@@ -639,6 +639,23 @@ set_default_def (tree var, tree def)
    SSA_NAME_IS_DEFAULT_DEF (def) = true;
 }
 
+/* Return TRUE if VAR is in the set of referenced variables.  */
+
+bool
+referenced_var_p (tree var)
+{
+  struct tree_decl_minimal in;
+
+  gcc_assert (DECL_P (var));
+
+  if (!gimple_referenced_vars (cfun))
+    return false;
+
+  in.uid = DECL_UID (var);
+  return htab_find_with_hash (gimple_referenced_vars (cfun), &in, in.uid)
+    != NULL;
+}
+
 /* Add VAR to the list of referenced variables if it isn't already there.  */
 
 bool
@@ -686,6 +703,15 @@ remove_referenced_var (tree var)
   void **loc;
   unsigned int uid = DECL_UID (var);
 
+  /* Symbols that decayed from addressable to gimple registers, but
+     that are referenced only in debug stmts, may be marked for
+     renaming, but renaming them would fail once they're no longer
+     referenced.  Let them rest in peace.  */
+  if (TREE_CODE (var) != SSA_NAME
+      && is_gimple_reg (var)
+      && sym_marked_for_renaming (var))
+    clear_mark_for_renaming (var);
+
   clear_call_clobbered (var);
   bitmap_clear_bit (gimple_call_used_vars (cfun), uid);
   if ((v_ann = var_ann (var)))
--- gcc/tree-flow.h.orig	2009-09-30 04:00:46.000000000 -0300
+++ gcc/tree-flow.h	2009-09-30 04:01:21.000000000 -0300
@@ -773,6 +773,7 @@ extern void dump_referenced_vars (FILE *
 extern void dump_variable (FILE *, tree);
 extern void debug_variable (tree);
 extern tree get_virtual_var (tree);
+extern bool referenced_var_p (tree);
 extern bool add_referenced_var (tree);
 extern void remove_referenced_var (tree);
 extern void mark_symbols_for_renaming (gimple);
@@ -889,7 +890,9 @@ bool name_registered_for_update_p (tree)
 bitmap ssa_names_to_replace (void);
 void release_ssa_name_after_update_ssa (tree);
 void compute_global_livein (bitmap, bitmap);
+bool sym_marked_for_renaming (tree);
 void mark_sym_for_renaming (tree);
+void clear_mark_for_renaming (tree);
 void mark_set_for_renaming (bitmap);
 tree get_current_def (tree);
 void set_current_def (tree, tree);
--- gcc/tree-into-ssa.c.orig	2009-09-30 04:00:45.000000000 -0300
+++ gcc/tree-into-ssa.c	2009-09-30 04:01:21.000000000 -0300
@@ -2874,6 +2874,37 @@ mark_sym_for_renaming (tree sym)
     }
 }
 
+/* Unregister symbol SYM to be renamed by update_ssa.  SYM must be a
+   gimple register.  */
+
+void
+clear_mark_for_renaming (tree sym)
+{
+  if (need_to_initialize_update_ssa_p)
+    return;
+
+  gcc_assert (is_gimple_reg (sym));
+
+  bitmap_clear_bit (syms_to_rename, DECL_UID (sym));
+
+  if (bitmap_empty_p (syms_to_rename))
+    BITMAP_FREE (syms_to_rename);
+}
+
+/* Return true if a symbol is marked for renaming.  This is an
+   exported interface for symbol_marked_for_renaming.  */
+
+bool
+sym_marked_for_renaming (tree sym)
+{
+  if (need_to_initialize_update_ssa_p)
+    return false;
+
+  if (!syms_to_rename)
+    return false;
+
+  return symbol_marked_for_renaming (sym);
+}
 
 /* Register all the symbols in SET to be renamed by update_ssa.  */
 
--- gcc/tree-ssa-operands.c.orig	2009-09-30 04:00:45.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-09-30 04:01:21.000000000 -0300
@@ -2716,9 +2716,22 @@ pop_stmt_changes (gimple *stmt_p)
   mark_difference_for_renaming (stores, buf->stores);
 
   /* Mark all the naked GIMPLE register operands for renaming.  */
-  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
-    if (DECL_P (op))
-      mark_sym_for_renaming (op);
+  if (gimple_debug_bind_p (stmt))
+    {
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
+	if (DECL_P (op) && !referenced_var_p (op))
+	  {
+	    gimple_debug_bind_reset_value (stmt);
+	    update_stmt (stmt);
+	    break;
+	  }
+    }
+  else
+    {
+      FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF|SSA_OP_USE)
+	if (DECL_P (op))
+	  mark_sym_for_renaming (op);
+    }
 
   /* FIXME, need to add more finalizers here.  Cleanup EH info,
      recompute invariants for address expressions, add
--- gcc/testsuite/gcc.dg/debug/vta-1.c	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/vta-1.c	2009-09-30 04:01:21.000000000 -0300
@@ -0,0 +1,35 @@
+/* https://bugzilla.redhat.com/show_bug.cgi?id=521991#c5
+
+   Distilled from Linux XFS source code.  foo, inlined into bar, ends
+   up with debug stmts referencing the addressable variable b.
+   Optimization made it non-addressable, and then completely optimized
+   away, before we got a chance to rename (and discard) the occurrence
+   in the debug stmt.  When we did, we crashed, attempting to rename
+   an unreference variable.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -g" } */
+
+static inline int
+foo (void *x, unsigned y)
+{
+  unsigned z = *(unsigned long *) x % y;
+  *(unsigned long *) x = *(unsigned long *) x / y;
+  return z;
+}
+
+struct S
+{
+  unsigned t;
+};
+
+void
+bar (struct S *x, int *y)
+{
+  int a = 0;
+  unsigned long b = x->t;
+  foo (&b, x->t);
+  for (;; a++)
+    if (b)
+      *y = 1;
+}