aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/tree-flow.h4
-rw-r--r--gcc/tree-ssa-alias.c12
-rw-r--r--gcc/tree-ssa-operands.c157
-rw-r--r--gcc/tree-ssa.c3
5 files changed, 137 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 66b7075..8e5f519 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+2004-07-08 Diego Novillo <dnovillo@redhat.com>
+
+ * tree-flow.h (addressable_vars): Declare.
+ * tree-ssa-alias.c (addressable_vars): Define.
+ (setup_pointers_and_addressables): Add addressable variables
+ to addressable_vars.
+ * tree-ssa-operands.c (get_stmt_operands): Move
+ handling of ASM_EXPRs ...
+ (get_asm_expr_operands): ... here.
+ When the ASM_EXPR clobbers memory, also clobber addressable
+ variables.
+ * tree-ssa.c (init_tree_ssa): Initialize addressable_vars.
+ (delete_tree_ssa): Reset addressable_vars.
+
2004-07-07 Jan Beulich <jbeulich@novell.com>
Richard Henderson <rth@redhat.com>
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index dc4ddb2..f9f8115 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -395,6 +395,10 @@ extern GTY(()) tree global_var;
REFERENCED_VARS (I) is call-clobbered. */
extern bitmap call_clobbered_vars;
+/* Addressable variables in the function. If bit I is set, then
+ REFERENCED_VARS (I) has had its address taken. */
+extern bitmap addressable_vars;
+
/* 'true' after aliases have been computed (see compute_may_aliases). */
extern bool aliases_computed_p;
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 75c98e1..3cf27ae 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -163,6 +163,10 @@ static struct ptr_info_def *get_ptr_info (tree t);
REFERENCED_VARS (I) is call-clobbered. */
bitmap call_clobbered_vars;
+/* Addressable variables in the function. If bit I is set, then
+ REFERENCED_VARS (I) has had its address taken. */
+bitmap addressable_vars;
+
/* 'true' after aliases have been computed (see compute_may_aliases). This
is used by get_stmt_operands and its helpers to determine what to do
when scanning an operand for a variable that may be aliased. If
@@ -1196,6 +1200,14 @@ setup_pointers_and_addressables (struct alias_info *ai)
to rename VAR into SSA afterwards. */
bitmap_set_bit (vars_to_rename, v_ann->uid);
}
+ else
+ {
+ /* Add the variable to the set of addressables. Mostly
+ used when scanning operands for ASM_EXPRs that
+ clobber memory. In those cases, we need to clobber
+ all call-clobbered variables and all addressables. */
+ bitmap_set_bit (addressable_vars, v_ann->uid);
+ }
}
/* Global variables and addressable locals may be aliased. Create an
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index c44189f..46f9f59 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -80,6 +80,7 @@ typedef struct voperands_d
static void note_addressable (tree, stmt_ann_t);
static void get_expr_operands (tree, tree *, int, voperands_t);
+static void get_asm_expr_operands (tree, voperands_t);
static inline void append_def (tree *, tree);
static inline void append_use (tree *, tree);
static void append_v_may_def (tree, tree, voperands_t);
@@ -777,59 +778,7 @@ get_stmt_operands (tree stmt)
break;
case ASM_EXPR:
- {
- int noutputs = list_length (ASM_OUTPUTS (stmt));
- const char **oconstraints
- = (const char **) alloca ((noutputs) * sizeof (const char *));
- int i;
- tree link;
- const char *constraint;
- bool allows_mem, allows_reg, is_inout;
-
- for (i=0, link = ASM_OUTPUTS (stmt); link;
- ++i, link = TREE_CHAIN (link))
- {
- oconstraints[i] = constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_output_constraint (&constraint, i, 0, 0,
- &allows_mem, &allows_reg, &is_inout);
- if (allows_reg && is_inout)
- /* This should have been split in gimplify_asm_expr. */
- abort ();
-
- if (!allows_reg && allows_mem)
- {
- tree t = get_base_address (TREE_VALUE (link));
- if (t && DECL_P (t))
- mark_call_clobbered (t);
- }
-
- get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def,
- &prev_vops);
- }
-
- for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
- {
- constraint
- = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
- parse_input_constraint (&constraint, 0, 0, noutputs, 0,
- oconstraints, &allows_mem, &allows_reg);
-
- if (!allows_reg && allows_mem)
- {
- tree t = get_base_address (TREE_VALUE (link));
- if (t && DECL_P (t))
- mark_call_clobbered (t);
- }
-
- get_expr_operands (stmt, &TREE_VALUE (link), 0, &prev_vops);
- }
-
- /* Clobber memory for asm ("" : : : "memory"); */
- for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
- if (!strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory"))
- add_call_clobber_ops (stmt, &prev_vops);
- }
+ get_asm_expr_operands (stmt, &prev_vops);
break;
case RETURN_EXPR:
@@ -1215,6 +1164,108 @@ get_expr_operands (tree stmt, tree *expr_p, int flags, voperands_t prev_vops)
abort ();
}
+/* Scan operands in ASM_EXPR STMT. PREV_VOPS is as in
+ append_v_may_def and append_vuse. */
+
+static void
+get_asm_expr_operands (tree stmt, voperands_t prev_vops)
+{
+ int noutputs = list_length (ASM_OUTPUTS (stmt));
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ int i;
+ tree link;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+ stmt_ann_t s_ann = stmt_ann (stmt);
+
+ for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+ {
+ oconstraints[i] = constraint
+ = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_output_constraint (&constraint, i, 0, 0,
+ &allows_mem, &allows_reg, &is_inout);
+
+#if defined ENABLE_CHECKING
+ /* This should have been split in gimplify_asm_expr. */
+ if (allows_reg && is_inout)
+ abort ();
+#endif
+
+ /* Memory operands are addressable. Note that STMT needs the
+ address of this operand. */
+ if (!allows_reg && allows_mem)
+ {
+ tree t = get_base_address (TREE_VALUE (link));
+ if (t && DECL_P (t))
+ note_addressable (t, s_ann);
+ }
+
+ get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def, prev_vops);
+ }
+
+ for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+ {
+ constraint
+ = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+
+ /* Memory operands are addressable. Note that STMT needs the
+ address of this operand. */
+ if (!allows_reg && allows_mem)
+ {
+ tree t = get_base_address (TREE_VALUE (link));
+ if (t && DECL_P (t))
+ note_addressable (t, s_ann);
+ }
+
+ get_expr_operands (stmt, &TREE_VALUE (link), 0, prev_vops);
+ }
+
+ /* Clobber memory for asm ("" : : : "memory"); */
+ if (!aliases_computed_p)
+ {
+ /* If we still have not computed aliasing information,
+ mark the statement as having volatile operands to avoid
+ optimizations from messing around with it. */
+ stmt_ann (stmt)->has_volatile_ops = true;
+ }
+ else
+ {
+ /* Otherwise, if this ASM_EXPR clobbers memory, clobber
+ all the call-clobbered variables and the addressable
+ variables found by the alias analyzer. */
+ for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
+ if (!strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory"))
+ {
+ /* If we had created .GLOBAL_VAR earlier, use it.
+ Otherwise, add a V_MAY_DEF operand for every
+ call-clobbered and addressable variable. See
+ compute_may_aliases for the heuristic used to decide
+ whether to create .GLOBAL_VAR or not. */
+ if (global_var)
+ add_stmt_operand (&global_var, stmt, opf_is_def, prev_vops);
+ else
+ {
+ size_t i;
+
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i,
+ {
+ tree var = referenced_var (i);
+ add_stmt_operand (&var, stmt, opf_is_def, prev_vops);
+ });
+
+ EXECUTE_IF_SET_IN_BITMAP (addressable_vars, 0, i,
+ {
+ tree var = referenced_var (i);
+ add_stmt_operand (&var, stmt, opf_is_def, prev_vops);
+ });
+ }
+ }
+ }
+}
+
/* Add *VAR_P to the appropriate operand array of STMT. FLAGS is as in
get_expr_operands. If *VAR_P is a GIMPLE register, it will be added to
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 4cdfd3d..3ab7ac2 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -494,6 +494,7 @@ init_tree_ssa (void)
{
VARRAY_TREE_INIT (referenced_vars, 20, "referenced_vars");
call_clobbered_vars = BITMAP_XMALLOC ();
+ addressable_vars = BITMAP_XMALLOC ();
init_ssa_operands ();
init_ssanames ();
init_phinodes ();
@@ -532,6 +533,8 @@ delete_tree_ssa (void)
BITMAP_XFREE (call_clobbered_vars);
call_clobbered_vars = NULL;
aliases_computed_p = false;
+ BITMAP_XFREE (addressable_vars);
+ addressable_vars = NULL;
}