This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa-branch] Fix call site clobbers [patch]


This patch fixes a reaching definition bug found by Jeff Law that
would make a DCE pass kill statements that it shouldn't.  In
gcc.c-torture/execute/20000217-1.c we have:

	unsigned short int x = 0;
	unsigned short int y = 10;

	if (showbug (&x, &y) != 0)
	  abort ();

We were clobbering x and y at the call site, but we were not
creating a may-use for them.  This tricks a DCE pass into killing
both assignments for x and y.

Along the same lines.  When the DFA pass finds a non-simplified
tree node, it should also create a may-use for the variable.

Bootstrapped and tested on x86.


Diego.

	* tree-dfa.c (find_refs_in_stmt): Call clobber_vars_r to clobber
	CLEANUP_STMT nodes.
	(create_ref): Only add _DECL nodes to the list of referenced
	variables.
	(clobber_vars_r): Create a may-use reference prior to clobbering
	the variable.
	(add_call_site_clobbers): Ditto.
	(add_ptr_may_refs): Move call to find_list_node where it's actually
	needed.
	* tree-flow.h: Update documentation on M_CLOBBER.

Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.14
diff -d -u -p -r1.1.4.14 tree-dfa.c
--- tree-dfa.c	11 Sep 2002 01:13:35 -0000	1.1.4.14
+++ tree-dfa.c	12 Sep 2002 03:31:24 -0000
@@ -234,15 +234,10 @@ find_refs_in_stmt (t, bb)
 	}
       break;
 
-    /* FIXME: CLEANUP_STMTs are not simplified.  Clobber everything.  */
+    /* FIXME  CLEANUP_STMTs are not simplified.  Clobber everything.  */
     case CLEANUP_STMT:
-      if (TREE_CODE (CLEANUP_DECL (t)) == VAR_DECL
-	  && DECL_INITIAL (TREE_OPERAND (t, 0)))
-	find_refs_in_expr (&TREE_OPERAND (t, 0), V_DEF | M_CLOBBER, bb, t,
-			   TREE_OPERAND (t, 0));
-
-      find_refs_in_expr (&CLEANUP_EXPR (t), V_DEF | M_CLOBBER, bb, t,
-	                 CLEANUP_EXPR (t));
+      walk_tree (&CLEANUP_DECL (t), clobber_vars_r, NULL, NULL);
+      walk_tree (&CLEANUP_EXPR (t), clobber_vars_r, NULL, NULL);
       break;
 
     case LABEL_STMT:
@@ -754,12 +749,13 @@ create_ref (var, ref_type, bb, parent_st
     {
       /* Add the variable to the list of variables referenced in this
 	 function.  But only for actual variable defs or uses in the code.  */
-      if (ref_type & (V_DEF | V_USE))
+      if ((ref_type & (V_DEF | V_USE))
+	  && TREE_CODE_CLASS (TREE_CODE (var)) == 'd')
 	add_referenced_var (var);
-      
+
       /* Add this reference to the list of references for the variable.  */
       add_tree_ref (var, ref);
-      
+
       /* Add this reference to the list of references for the containing
 	 statement.  */
       if (parent_stmt)
@@ -1369,7 +1365,7 @@ validate_ref_type (type)
   return false;
 }
 
-/* Callback for walk_tree.  Create a clobbering definition for every _DECL
+/* Callback for walk_tree.  Create a may-def/may-use reference for every _DECL
    and compound reference found under *TP.  */
 
 static tree
@@ -1381,10 +1377,14 @@ clobber_vars_r (tp, walk_subtrees, data)
   enum tree_code code = TREE_CODE (*tp);
   struct clobber_data_d *clobber = (struct clobber_data_d *)data;
 
-  /* Clobber every VAR_DECL in sight.  */
-  if (code == VAR_DECL)
-    create_ref (*tp, V_DEF | M_CLOBBER, clobber->bb, clobber->parent_stmt,
-	        clobber->parent_expr, NULL, true);
+  /* Create may-use and clobber references for every *_DECL in sight.  */
+  if (code == VAR_DECL || code == PARM_DECL || code == FUNCTION_DECL)
+    {
+      create_ref (*tp, V_USE | M_MAY, clobber->bb, clobber->parent_stmt,
+		  clobber->parent_expr, NULL, true);
+      create_ref (*tp, V_DEF | M_CLOBBER, clobber->bb, clobber->parent_stmt,
+		  clobber->parent_expr, NULL, true);
+    }
 
   return NULL;
 }
@@ -1411,7 +1411,8 @@ add_default_defs ()
 }
 
 
-/* Insert clobbering definitions at every call site.  */
+/* Insert may-use/clobber references at every call site for every variable
+   that the called function might have access to.  */
 
 static void
 add_call_site_clobbers ()
@@ -1428,7 +1429,6 @@ add_call_site_clobbers ()
       tree expr = ref_expr (ref);
       tree fcall = ref_var (ref);
       ref_list refs = bb_refs (bb);
-      struct ref_list_node *call_ref_node = find_list_node (refs, ref);
 
       /* Skip pure and built-in functions.  */
       if (is_pure_fcall (fcall))
@@ -1451,9 +1451,21 @@ add_call_site_clobbers ()
 	  if ((add_addressable && TREE_ADDRESSABLE (sym))
 	      || DECL_CONTEXT (sym) == NULL)
 	    {
-	      tree_ref ref = create_ref (sym, V_DEF | M_CLOBBER, bb, stmt, expr,
-		                         NULL, false);
-	      add_ref_to_list_after (refs, call_ref_node, ref);
+	      struct ref_list_node *call_ref_node;
+	      tree_ref clobber, may_use;
+	      
+	      clobber = create_ref (sym, V_DEF | M_CLOBBER, bb, stmt, expr,
+				    NULL, false);
+	      may_use = create_ref (sym, V_USE | M_MAY, bb, stmt, expr, NULL,
+		                    false);
+
+	      /* Notice that we first add the clobber and then the may-use
+		 reference so that the may-use appears first.  This is so
+		 that any prior definitions of SYM may reach the call site
+		 and any subsequent uses of SYM are reached by the clobber.  */
+	      call_ref_node = find_list_node (refs, ref);
+	      add_ref_to_list_after (refs, call_ref_node, clobber);
+	      add_ref_to_list_after (refs, call_ref_node, may_use);
 	    }
 	}
     }
@@ -1478,7 +1490,7 @@ add_ptr_may_refs ()
       tree stmt = ref_stmt (ref);
       tree expr = ref_expr (ref);
       ref_list refs = bb_refs (bb);
-      struct ref_list_node *ptr_ref_node = find_list_node (refs, ref);
+      struct ref_list_node *ptr_ref_node;
       HOST_WIDE_INT sym_alias_set, ptr_sym_alias_set;
 
       /* The may-refs we are going to introduce are not indirect.  */
@@ -1501,9 +1513,12 @@ add_ptr_may_refs ()
 	  if (TREE_ADDRESSABLE (sym)
 	      && alias_sets_conflict_p (sym_alias_set, ptr_sym_alias_set))
 	    {
-	      tree_ref ref = create_ref (sym, type | M_MAY, bb, stmt, expr,
-					 NULL, false);
-	      add_ref_to_list_after (refs, ptr_ref_node, ref);
+	      tree_ref may_ref;
+	      
+	      may_ref = create_ref (sym, type | M_MAY, bb, stmt, expr, NULL,
+		                    false);
+	      ptr_ref_node = find_list_node (refs, ref);
+	      add_ref_to_list_after (refs, ptr_ref_node, may_ref);
 	    }
 	}
     }
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.12
diff -d -u -p -r1.1.4.12 tree-flow.h
--- tree-flow.h	11 Sep 2002 01:13:35 -0000	1.1.4.12
+++ tree-flow.h	12 Sep 2002 03:31:24 -0000
@@ -92,15 +92,11 @@ extern const HOST_WIDE_INT E_INJ;
 extern const HOST_WIDE_INT M_DEFAULT;
 
 /* M_CLOBBER is used to modify V_DEF references to represent an unknown
-   access to the associated variable (ie, the operation may read and/or
-   write to the variable).  Since the compiler does not know what the
-   statement may be doing to the variable, it assumes that the statement
-   might write a new value to it.
-
-   For instance, __asm__ statements, function calls and tree nodes that
-   have not been simplified use V_DEF|M_CLOBBERs to represent references.
-   V_DEF|M_CLOBBER references are safety devices used when the compiler
-   knows that the variable is being accessed, but it doesn't know how.  */
+   modification to the associated variable.  This is used for instructions
+   like __asm__ statements where we know that the variable is being
+   modified but not how.  Another case is at function call sites.
+   Variables that may be accessed by the called function are assumed read
+   and clobbered by the call.  */
 extern const HOST_WIDE_INT M_CLOBBER;
 
 /* M_MAY is used to represent references that may or may not occur at


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]