This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] Fix for volatile handling and PR11373 [patch]
- From: Diego Novillo <dnovillo at redhat dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: 15 Jul 2003 12:15:00 -0400
- Subject: [tree-ssa] Fix for volatile handling and PR11373 [patch]
- Organization: Red Hat Canada
Fixes handling of volatile attributes. Jason changed the gimplifier to
promote volatile attributes to the expressions on the LHS and RHS of
expressions. This change allows the compiler to detect if the statement
makes volatile references by simply checking if the LHS or RHS of an
assignment are volatile.
It also partially fixes http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11373
We were not marking pointers modified by __asm__ expressions as pointers
that may be pointing to global memory.
The other test case reported in PR11373 is in my queue. It's basically
this:
foo()
{
int *p = 0xdeadbeef;
*p = 3;
}
We are currently killing '*p = 3;'. I'm no language lawyer, but I've
been told that the above is implementation defined and that a reasonable
default behaviour would be to mark pointer 'p' as 'may point to global
memory'. This will prevent DCE from killing it.
The patch should also fix the problem reported by dberlin. The
propagation of ADDR_EXPR was also being done even when the dominator
optimizations were switched off. This is because we were allowing the
CCP pass from exposing them. Since propagating ADDR_EXPRs break SSA and
GIMPLE, they should be contained and done only when we are ready to
repair the damage.
Finally, a minor optimization. In avail_expr_eq, if both statements are
the same pointer, return true without further checks.
Bootstrapped and tested on x86.
Diego.
2003-07-15 Diego Novillo <dnovillo@redhat.com>
* tree-dfa.c (add_stmt_operand): Move volatile handling...
(find_vars_r): ... here.
Mark when the walker is inside an ASM_EXPR.
(struct walk_state): Add field 'is_asm_expr'.
Change flag fields to bitfields.
(add_referenced_var): If the variable is a pointer being stored by
an ASM_EXPR, mark it as a global memory pointer.
* tree-flow-inline.h (is_optimizable_addr_expr): New function.
* tree-flow.h (is_optimizable_addr_expr): Declare it.
* tree-ssa.c (rewrite_and_optimize_stmt): Use it.
(lookup_avail_expr): Likewise.
(get_eq_expr_value): Likewise.
(avail_expr_eq): Return 'true' when comparing a statement against
itself.
* tree-ssa-dce.c (need_to_preserve_store): Move volatile checking...
(stmt_useful_p): ...here.
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.128
diff -d -u -p -r1.1.4.128 tree-dfa.c
--- tree-dfa.c 14 Jul 2003 22:22:19 -0000 1.1.4.128
+++ tree-dfa.c 15 Jul 2003 16:12:07 -0000
@@ -89,10 +89,13 @@ struct walk_state
htab_t vars_found;
/* Nonzero if the variables found under the current tree are written to. */
- int is_store;
+ int is_store : 1;
/* Nonzero if the walker is inside an INDIRECT_REF node. */
- int is_indirect_ref;
+ int is_indirect_ref : 1;
+
+ /* Nonzero if the walker is inside an ASM_EXPR node. */
+ int is_asm_expr : 1;
};
@@ -609,11 +612,6 @@ add_stmt_operand (tree *var_p, tree stmt
if (v_ann->is_alias_tag)
flags |= opf_force_vop;
- /* If the variable is volatile, inform the statement that it makes
- volatile storage references. */
- if (TREE_THIS_VOLATILE (var))
- s_ann->has_volatile_ops = 1;
-
aliases = v_ann->may_aliases;
if (aliases == NULL)
{
@@ -1682,6 +1680,7 @@ compute_may_aliases (tree fndecl)
walk_state.vars_found = vars_found;
walk_state.is_store = 0;
walk_state.is_indirect_ref = 0;
+ walk_state.is_asm_expr = 0;
/* Find all the variables referenced in the function. */
FOR_EACH_BB (bb)
@@ -2163,16 +2162,23 @@ find_vars_r (tree *tp, int *walk_subtree
&& may_access_global_mem_p (TREE_OPERAND (t, 1)))
set_may_point_to_global_mem (TREE_OPERAND (t, 0));
+ /* If either side makes volatile references, mark the statement. */
+ if (TREE_THIS_VOLATILE (TREE_OPERAND (t, 0))
+ || TREE_THIS_VOLATILE (TREE_OPERAND (t, 1)))
+ get_stmt_ann (t)->has_volatile_ops = 1;
+
return t;
}
else if (TREE_CODE (t) == ASM_EXPR)
{
+ walk_state->is_asm_expr = 1;
walk_state->is_store = 1;
walk_tree (&ASM_OUTPUTS (t), find_vars_r, data, NULL);
walk_tree (&ASM_CLOBBERS (t), find_vars_r, data, NULL);
walk_state->is_store = 0;
walk_tree (&ASM_INPUTS (t), find_vars_r, data, NULL);
walk_state->is_store = saved_is_store;
+ walk_state->is_asm_expr = 0;
return t;
}
else if (TREE_CODE (t) == INDIRECT_REF)
@@ -2296,6 +2302,13 @@ add_referenced_var (tree var, struct wal
stores to keep track of. */
if (walk_state->is_store)
v_ann->is_stored = 1;
+
+ /* If the variable is a pointer being clobbered by an ASM_EXPR, the
+ pointer may end up pointing to global memory. */
+ if (POINTER_TYPE_P (TREE_TYPE (var))
+ && walk_state->is_store
+ && walk_state->is_asm_expr)
+ v_ann->may_point_to_global_mem = 1;
/* If VAR is a pointer referenced in an INDIRECT_REF node, create (or
re-use) a memory tag to represent the location pointed-to by VAR. */
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
retrieving revision 1.1.2.41
diff -d -u -p -r1.1.2.41 tree-flow-inline.h
--- tree-flow-inline.h 15 Jul 2003 03:13:40 -0000 1.1.2.41
+++ tree-flow-inline.h 15 Jul 2003 16:12:07 -0000
@@ -502,14 +502,19 @@ empty_bsi_stack (bsi_list_p list)
static inline bool
is_unchanging_value (tree val)
{
+ return ((TREE_CONSTANT (val) || really_constant_p (val))
+ && is_gimple_val (val));
+}
+
+static inline bool
+is_optimizable_addr_expr (tree val)
+{
/* FIXME: It should be possible to accept type-casted ADDR_EXPRs if we
made sure that the folded INDIRECT_REF kept the type-cast. See for
instance, gcc.c-torture/compile/990203-1.c. */
- return ((TREE_CODE (val) == ADDR_EXPR
- && (TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
- || TREE_CODE (TREE_OPERAND (val, 0)) == PARM_DECL))
- || ((TREE_CONSTANT (val) || really_constant_p (val))
- && is_gimple_val (val)));
+ return (TREE_CODE (val) == ADDR_EXPR
+ && (TREE_CODE (TREE_OPERAND (val, 0)) == VAR_DECL
+ || TREE_CODE (TREE_OPERAND (val, 0)) == PARM_DECL));
}
#endif /* _TREE_FLOW_INLINE_H */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.90
diff -d -u -p -r1.1.4.90 tree-flow.h
--- tree-flow.h 15 Jul 2003 03:13:40 -0000 1.1.4.90
+++ tree-flow.h 15 Jul 2003 16:12:08 -0000
@@ -483,7 +483,8 @@ void propagate_copy (tree *, tree);
/* In tree-flow-inline.h */
static inline int phi_arg_from_edge (tree, edge);
static inline struct phi_arg_d *phi_element_for_edge (tree, edge);
-static inline bool is_unchanging_value (tree val);
+static inline bool is_unchanging_value (tree);
+static inline bool is_optimizable_addr_expr (tree);
/* In tree-must-alias.c */
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.45
diff -d -u -p -r1.1.2.45 tree-ssa-dce.c
--- tree-ssa-dce.c 14 Jul 2003 21:18:48 -0000 1.1.2.45
+++ tree-ssa-dce.c 15 Jul 2003 16:12:08 -0000
@@ -193,10 +193,6 @@ need_to_preserve_store (tree var)
sym = SSA_NAME_VAR (var);
base_symbol = get_base_symbol (var);
- /* Stores to volatiles must be preserved. */
- if (TREE_THIS_VOLATILE (sym))
- return true;
-
/* File scope variables must be preserved. */
if (decl_function_context (base_symbol) == NULL)
return true;
@@ -289,6 +285,10 @@ stmt_useful_p (tree stmt)
if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
return true;
}
+
+ /* If the statement has volatile operands, it needs to be preserved. */
+ if (stmt_ann (stmt)->has_volatile_ops)
+ return true;
/* Examine all the stores in this statement. */
get_stmt_operands (stmt);
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.101
diff -d -u -p -r1.1.4.101 tree-ssa.c
--- tree-ssa.c 14 Jul 2003 21:18:48 -0000 1.1.4.101
+++ tree-ssa.c 15 Jul 2003 16:12:08 -0000
@@ -2193,7 +2193,8 @@ rewrite_and_optimize_stmt (block_stmt_it
if (val)
{
/* Gather statistics. */
- if (is_unchanging_value (val))
+ if (is_unchanging_value (val)
+ || is_optimizable_addr_expr (val))
ssa_stats.num_const_prop++;
else
ssa_stats.num_copy_prop++;
@@ -2204,7 +2205,7 @@ rewrite_and_optimize_stmt (block_stmt_it
fprintf (dump_file, " Replaced '");
print_generic_expr (dump_file, *op_p, 0);
fprintf (dump_file, "' with %s '",
- is_unchanging_value (val) ? "constant" : "variable");
+ TREE_CODE (val) == SSA_NAME ? "variable" : "constant");
print_generic_expr (dump_file, val, 0);
fprintf (dump_file, "'\n");
}
@@ -2292,7 +2293,9 @@ rewrite_and_optimize_stmt (block_stmt_it
rhs = TREE_OPERAND (stmt, 1);
if (may_optimize_p)
{
- if (TREE_CODE (rhs) == SSA_NAME || is_unchanging_value (rhs))
+ if (TREE_CODE (rhs) == SSA_NAME
+ || is_unchanging_value (rhs)
+ || is_optimizable_addr_expr (rhs))
set_value_for (*def_p, rhs, const_and_copies);
}
}
@@ -2762,7 +2765,8 @@ lookup_avail_expr (tree stmt,
in rewrite_and_optimize_stmt. */
rhs = TREE_OPERAND (stmt, 1);
if (TREE_CODE (rhs) == SSA_NAME
- || is_unchanging_value (rhs))
+ || is_unchanging_value (rhs)
+ || is_optimizable_addr_expr (rhs))
return NULL_TREE;
slot = htab_find_slot (avail_exprs, stmt, INSERT);
@@ -2806,6 +2810,7 @@ get_eq_expr_value (tree if_stmt)
else if (TREE_CODE (cond) == EQ_EXPR
&& TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME
&& (is_unchanging_value (TREE_OPERAND (cond, 1))
+ || is_optimizable_addr_expr (TREE_OPERAND (cond, 1))
|| TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME))
value = build (MODIFY_EXPR, TREE_TYPE (cond),
TREE_OPERAND (cond, 0),
@@ -2860,6 +2865,10 @@ avail_expr_eq (const void *p1, const voi
s2 = (tree) p2;
rhs2 = TREE_OPERAND (s2, 1);
+
+ /* If they are the same physical statement, return true. */
+ if (s1 == s2)
+ return true;
/* In case of a collision, both RHS have to be identical and have the
same VUSE operands. */