This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa] re-compute TREE_ADDRESSABLE during find_referenced_vars
- From: Jan Hubicka <jh at suse dot cz>
- To: gcc-patches at gcc dot gnu dot org, rth at redhat dot com, dnovillo at redhat dot com
- Date: Wed, 26 Nov 2003 13:57:16 +0100
- Subject: [tree-ssa] re-compute TREE_ADDRESSABLE during find_referenced_vars
Hi,
I wrote this code orignally as an attempt to avoid need to compute
TREE_ADDRESSABLE in the frontend. This is not possible right now as
gimplification and several other bits depends on different definitions
of TREE_ADDRESABLE value.
However it is very natural to recompute the value there as we already
cleaned up the propgram somewhat (removed useless and unreachable stuff
and so on). It results in slight compile time speedup as more of
optimizations are performed in dom1 instead of dom2 and very small code
quality improvements in portion of GCC source files (120 instructions
out of 400000)
OK?
Honza
* tree-dfa.c (walk_state): Add force_addressable field.
(find_vars_r): Collect information about addressability.
(add_referenced_vars): New operand in_addr_expr; recompute
TREE_ADDRESSABLE
(create_global_var): New.
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.188
diff -c -3 -p -r1.1.4.188 tree-dfa.c
*** tree-dfa.c 25 Nov 2003 18:26:15 -0000 1.1.4.188
--- tree-dfa.c 25 Nov 2003 22:04:10 -0000
*************** struct walk_state
*** 89,94 ****
--- 89,97 ----
/* Nonzero if the walker is inside an ASM_EXPR node. */
int is_asm_expr : 1;
+ /* Nonzero if the walker should force all references to be addressable. */
+ int force_addressable : 1;
+
/* Nonzero if the walker is inside a non-GIMPLE expression. */
int is_not_gimple : 1;
*************** static void add_call_read_ops (tree, vop
*** 134,140 ****
static void add_stmt_operand (tree *, tree, int, voperands_t);
static void add_immediate_use (tree, tree);
static tree find_vars_r (tree *, int *, void *);
! static void add_referenced_var (tree, struct walk_state *);
static tree get_memory_tag_for (tree);
static void compute_immediate_uses_for_phi (tree, bool (*)(tree));
static void compute_immediate_uses_for_stmt (tree, int, bool (*)(tree));
--- 137,143 ----
static void add_stmt_operand (tree *, tree, int, voperands_t);
static void add_immediate_use (tree, tree);
static tree find_vars_r (tree *, int *, void *);
! static void add_referenced_var (tree, struct walk_state *, bool);
static tree get_memory_tag_for (tree);
static void compute_immediate_uses_for_phi (tree, bool (*)(tree));
static void compute_immediate_uses_for_stmt (tree, int, bool (*)(tree));
*************** find_referenced_vars (tree fndecl)
*** 1751,1757 ****
if (walk_state.num_calls * num_call_clobbered_vars < n_calls * n_clobbers)
global_var = NULL_TREE;
else if (global_var)
! add_referenced_var (global_var, &walk_state);
}
htab_delete (vars_found);
--- 1754,1760 ----
if (walk_state.num_calls * num_call_clobbered_vars < n_calls * n_clobbers)
global_var = NULL_TREE;
else if (global_var)
! add_referenced_var (global_var, &walk_state, true);
}
htab_delete (vars_found);
*************** find_vars_r (tree *tp, int *walk_subtree
*** 2249,2259 ****
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, walk_state, NULL);
walk_tree (&ASM_CLOBBERS (t), find_vars_r, walk_state, NULL);
walk_state->is_store = 0;
walk_tree (&ASM_INPUTS (t), find_vars_r, walk_state, NULL);
--- 2252,2298 ----
return t;
}
+ else if (TREE_CODE (t) == ADDR_EXPR)
+ {
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ARRAY_REF
+ || TREE_CODE (t) == COMPONENT_REF
+ || TREE_CODE (t) == REALPART_EXPR
+ || TREE_CODE (t) == IMAGPART_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (SSA_VAR_P (t))
+ {
+ add_referenced_var (t, walk_state, true);
+ }
+ return NULL_TREE;
+ }
else if (TREE_CODE (t) == ASM_EXPR)
{
+ int noutputs = list_length (ASM_OUTPUTS (t));
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ int i;
+ tree link;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+
walk_state->is_asm_expr = 1;
walk_state->is_store = 1;
! for (i=0, link = ASM_OUTPUTS (t); 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)
! walk_state->force_addressable = true;
! walk_tree (&TREE_VALUE (link), find_vars_r, walk_state, NULL);
! walk_state->force_addressable = false;
! }
walk_tree (&ASM_CLOBBERS (t), find_vars_r, walk_state, NULL);
walk_state->is_store = 0;
walk_tree (&ASM_INPUTS (t), find_vars_r, walk_state, NULL);
*************** find_vars_r (tree *tp, int *walk_subtree
*** 2276,2282 ****
if (SSA_VAR_P (t))
{
! add_referenced_var (t, walk_state);
return NULL_TREE;
}
--- 2315,2321 ----
if (SSA_VAR_P (t))
{
! add_referenced_var (t, walk_state, walk_state->force_addressable);
return NULL_TREE;
}
*************** find_vars_r (tree *tp, int *walk_subtree
*** 2297,2303 ****
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
{
walk_state->is_indirect_ref = 1;
! add_referenced_var (arg, walk_state);
walk_state->is_indirect_ref = 0;
}
}
--- 2336,2342 ----
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (arg))))
{
walk_state->is_indirect_ref = 1;
! add_referenced_var (arg, walk_state, false);
walk_state->is_indirect_ref = 0;
}
}
*************** find_vars_r (tree *tp, int *walk_subtree
*** 2323,2329 ****
assumes that VAR is a valid SSA variable. */
static void
! add_referenced_var (tree var, struct walk_state *walk_state)
{
void **slot;
var_ann_t v_ann;
--- 2362,2368 ----
assumes that VAR is a valid SSA variable. */
static void
! add_referenced_var (tree var, struct walk_state *walk_state, bool in_addr_expr_p ATTRIBUTE_UNUSED)
{
void **slot;
var_ann_t v_ann;
*************** add_referenced_var (tree var, struct wal
*** 2347,2352 ****
--- 2386,2397 ----
v_ann->uid = num_referenced_vars;
VARRAY_PUSH_TREE (referenced_vars, var);
+ /* FIXME: For aggregates we must keep addresable bit set to keep front-end happy.
+ Diego is working on proper sollution */
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (var))
+ && decl_function_context (var) == current_function_decl)
+ TREE_ADDRESSABLE (var) = 0;
+
/* Arguments or global variable pointers may point to memory outside
the current function. */
if (POINTER_TYPE_P (TREE_TYPE (var))
*************** add_referenced_var (tree var, struct wal
*** 2393,2398 ****
--- 2438,2470 ----
if (DECL_NONLOCAL (var))
set_is_used (var);
}
+ if (in_addr_expr_p && !TREE_ADDRESSABLE (var)
+ && decl_function_context (var) == current_function_decl)
+ {
+ struct alias_map_d *alias_map;
+
+ /* In our simplistics view taking address makes variable call clobbered. */
+ if (!is_gimple_call_clobbered (var))
+ {
+ add_call_clobbered_var (var);
+ v_ann->is_call_clobbered = 1;
+ if (POINTER_TYPE_P (TREE_TYPE (var)))
+ v_ann->may_point_to_global_mem = 1;
+ }
+ TREE_ADDRESSABLE (var) = 1;
+ /* Verify that we are still stupid this way. */
+ if (!is_gimple_call_clobbered (var))
+ abort ();
+ /* Create a new alias set entry for VAR. */
+ alias_map = ggc_alloc (sizeof (*alias_map));
+ alias_map->var = var;
+
+ if (TREE_CODE (TREE_TYPE (var)) == ARRAY_TYPE)
+ alias_map->set = get_alias_set (TREE_TYPE (TREE_TYPE (var)));
+ else
+ alias_map->set = get_alias_set (var);
+ VARRAY_PUSH_GENERIC_PTR (addressable_vars, alias_map);
+ }
/* Now, set attributes that depend on WALK_STATE. */
if (walk_state == NULL)
*************** add_referenced_var (tree var, struct wal
*** 2439,2445 ****
the memory tag that depend on WALK_STATE (e.g., whether this
variable is being stored-to). */
walk_state->is_indirect_ref = 0;
! add_referenced_var (tag, walk_state);
/* If pointer VAR may point to global mem, then TAG may alias
global memory. */
--- 2511,2517 ----
the memory tag that depend on WALK_STATE (e.g., whether this
variable is being stored-to). */
walk_state->is_indirect_ref = 0;
! add_referenced_var (tag, walk_state, false);
/* If pointer VAR may point to global mem, then TAG may alias
global memory. */
*************** create_global_var (void)
*** 2642,2648 ****
void
add_referenced_tmp_var (tree var)
{
! add_referenced_var (var, NULL);
}
/* Return true if VDEFS_AFTER contains fewer entries than VDEFS_BEFORE.
--- 2714,2720 ----
void
add_referenced_tmp_var (tree var)
{
! add_referenced_var (var, NULL, false);
}
/* Return true if VDEFS_AFTER contains fewer entries than VDEFS_BEFORE.