[tree-ssa] Aliasing fixes, take 3
Jan Hubicka
hubicka@ucw.cz
Sat Nov 22 14:36:00 GMT 2003
Hi,
Per Jeff's request, I've re-tested my patches with i686-pc-linux-gnu, instead
of i386-linux. This ineed makes clean tree to bootstrap. Additionally I've
also bootstrapped i386-linux and x86-64-linux (without libjava).
The patch is unification of the reverted patch to tree-must-alias fixes and
patch to recompute TREE_ADDRESSABLE instead of relying on frontend to do that.
It is not possible to break this patch further as each bugfix triggers latent
bug fixed by other bugfix.
I do have many direct followups to this patch: re-enabling of tail recursion,
verify_stmts, removal of TREE_ADDRESSABLE code from front-ends, removal of
ADDRESSOF construct, small improvements to aliasing, more proper handling of
matching constraints in asm operands. So I really hope this time everything
will go right.
Head of changelog of tree I tested patch on is:
2003-11-21 Diego Novillo <dnovillo@redhat.com>
* Makefile.in (tree-dfa.o): Add dependency on $(TREE_DUMP_H)
* tree-dfa.c: Include tree-dump.h
(compute_alias_sets): Call dump_function_to_file.
(may_access_global_mem_p): Check if the base address of _REF nodes
may point to global memory.
And the comparsion of testsuites gives:
- FAIL: gcc.c-torture/execute/20010403-1.c execution, -O3 -fomit-frame-pointer
- FAIL: gcc.c-torture/execute/20010403-1.c execution, -O3 -g
- FAIL: gcc.dg/format/ext-3.c bad %_0 (test for warnings, line 213)
- FAIL: gcc.dg/format/ext-3.c bad %^# (test for warnings, line 215)
So two of long standing failures fewer.
Honza
2003-11-22 Jan Hubicka <jh@suse.cz>
* tree-dfa.c (walk_state): Add force_addressable field.
(add_referenced_var): Add new argument in_addr_expr_p; recompute TREE_ADDRESSABLE.
(find_referenced_vars): Update call.
(find_vars_r): Likewise.
(add_referenced_tmp_var): Likewise.
(get_expr_operands): FIx handling of i386.
* tree-must-alias.c (tree_compute_must_alias): Promote pointers.
(find_addressable_vars): Deal with complex references.
(promote_var): Do not clear may_point_to_global_mem
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.187
diff -c -3 -p -r1.1.4.187 tree-dfa.c
*** tree-dfa.c 21 Nov 2003 23:17:17 -0000 1.1.4.187
--- tree-dfa.c 22 Nov 2003 13:03:41 -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)
*** 1982,1988 ****
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);
--- 1985,1991 ----
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
*** 2480,2490 ****
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);
--- 2483,2529 ----
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
*** 2507,2513 ****
if (SSA_VAR_P (t))
{
! add_referenced_var (t, walk_state);
return NULL_TREE;
}
--- 2546,2552 ----
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
*** 2528,2534 ****
&& !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;
}
}
--- 2567,2573 ----
&& !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
*** 2554,2560 ****
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;
--- 2593,2599 ----
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)
{
void **slot;
var_ann_t v_ann;
*************** add_referenced_var (tree var, struct wal
*** 2578,2583 ****
--- 2617,2628 ----
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.
+ Honza will track this next! */
+ 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
*** 2624,2629 ****
--- 2669,2701 ----
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
*** 2670,2676 ****
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. */
--- 2742,2748 ----
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)
*** 2873,2879 ****
void
add_referenced_tmp_var (tree var)
{
! add_referenced_var (var, NULL);
}
/* Return true if VDEFS_AFTER contains fewer entries than VDEFS_BEFORE.
--- 2945,2951 ----
void
add_referenced_tmp_var (tree var)
{
! add_referenced_var (var, NULL, false);
}
/* Return true if VDEFS_AFTER contains fewer entries than VDEFS_BEFORE.
Index: tree-must-alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-must-alias.c,v
retrieving revision 1.1.2.10
diff -c -3 -p -r1.1.2.10 tree-must-alias.c
*** tree-must-alias.c 21 Nov 2003 22:56:00 -0000 1.1.2.10
--- tree-must-alias.c 22 Nov 2003 13:03:42 -0000
*************** tree_compute_must_alias (tree fndecl, sb
*** 93,100 ****
/* We are only interested in disambiguating addressable locals. */
if (TREE_ADDRESSABLE (var)
! /* FIXME Why exactly do we need to ignore pointers and arrays? */
! && !POINTER_TYPE_P (TREE_TYPE (var))
&& TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE
&& decl_function_context (var) == current_function_decl
&& !DECL_NONLOCAL (var)
--- 93,99 ----
/* We are only interested in disambiguating addressable locals. */
if (TREE_ADDRESSABLE (var)
! /* FIXME Why exactly do we need to ignore arrays? */
&& TREE_CODE (TREE_TYPE (var)) != ARRAY_TYPE
&& decl_function_context (var) == current_function_decl
&& !DECL_NONLOCAL (var)
*************** find_addressable_vars (sbitmap addresses
*** 172,180 ****
--- 171,190 ----
{
tree t = PHI_ARG_DEF (phi, i);
+ if (TREE_CODE (t) == NOP_EXPR)
+ t = TREE_OPERAND (t, 0);
+
+ if (TREE_CODE (t) == PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+
if (TREE_CODE (t) != ADDR_EXPR)
continue;
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 (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
continue;
SET_BIT (addresses_needed, var_ann (t)->uid);
*************** promote_var (tree var, sbitmap vars_to_r
*** 217,223 ****
ann->may_aliases = NULL;
ann->is_call_clobbered = 0;
ann->may_alias_global_mem = 0;
- ann->may_point_to_global_mem = 0;
/* If the variable was an alias tag, remove it from every variable that
had it in its may-alias set. */
--- 227,232 ----
More information about the Gcc-patches
mailing list