This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa-branch] Fix call site clobbers [patch]
- From: Diego Novillo <dnovillo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Thu, 12 Sep 2002 09:29:40 -0400
- Subject: [tree-ssa-branch] Fix call site clobbers [patch]
- Organization: Red Hat Canada
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