This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix TBAA-pruning of points-to sets
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 3 Jun 2008 15:39:32 +0200 (CEST)
- Subject: [PATCH] Fix TBAA-pruning of points-to sets
We can TBAA-prune the points-to set if the pointer was dereferenced
and use may_alias_p to get better TBAA disambiguation.
This patch renames the pi->is_dereferenced flag to pi->memory_tag_needed,
as this is what it really means - we also set is_dereferenced for call
arguments, which is not a dereference site as far as TBAA is concerned.
Thus the patch adds back a pi->is_dereferenced flag and properly
initializes it. It removes the code that tried to track the
dereferenced property throughout the PTA solver via looking at the
constraints.
It "breaks" the tree-ssa-alias-warnings code some more (it uses the
TBAA-pruned points-to sets to search for aliases the pointer cannot
alias ...). I tried to fix it somewhat, but I would suggest to
remove that code and instead implement it as part of the alias
computation before the sets are pruned. But I have no time for that
now.
Bootstrapped and tested on x86_64-unknown-linux-gnu with the alias.c
fix applied. Ok for trunk?
Thanks,
Richard.
2008-05-29 Richard Guenther <rguenther@suse.de>
PR tree-optimization/36345
* tree-flow.h (struct ptr_info_def): Align escape_mask,
add memory_tag_needed flag.
(may_alias_p): Declare.
* tree-ssa-alias.c (may_alias_p): Export.
(set_initial_properties): Use memory_tag_needed flag.
(update_reference_counts): Likewise.
(reset_alias_info): Reset memory_tag_needed flag.
(create_name_tags): Check memory_tag_needed flag.
(dump_points_to_info_for): Dump it.
* tree-ssa-structalias.c (struct variable_info): Remove
directly_dereferenced flag.
(new_var_info): Do not initialize it.
(process_constraint_1): Do not set it.
(update_alias_info): Set is_dereferenced flag.
(set_uids_in_ptset): Use may_alias_p.
(set_used_smts): Check memory_tag_needed flag.
(find_what_p_points_to): Likewise. Pass is_dereferenced flag.
* tree-ssa-alias.c (verify_flow_sensitive_alias_info): Check
memory_tag_needed flag.
* tree-ssa-alias-warnings.c (dsa_named_for): Try to recover
from broken design.
* gcc.c-torture/execute/20020619-1.c: Remove broken testcase.
Index: trunk/gcc/tree-flow.h
===================================================================
*** trunk.orig/gcc/tree-flow.h 2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-flow.h 2008-06-03 15:14:31.000000000 +0200
*************** typedef struct
*** 227,232 ****
--- 227,235 ----
/* Aliasing information for SSA_NAMEs representing pointer variables. */
struct ptr_info_def GTY(())
{
+ /* Mask of reasons this pointer's value escapes the function. */
+ ENUM_BITFIELD (escape_type) escape_mask : 9;
+
/* Nonzero if points-to analysis couldn't determine where this pointer
is pointing to. */
unsigned int pt_anything : 1;
*************** struct ptr_info_def GTY(())
*** 234,240 ****
/* Nonzero if the value of this pointer escapes the current function. */
unsigned int value_escapes_p : 1;
! /* Nonzero if this pointer is dereferenced. */
unsigned int is_dereferenced : 1;
/* Nonzero if this pointer points to a global variable. */
--- 237,247 ----
/* Nonzero if the value of this pointer escapes the current function. */
unsigned int value_escapes_p : 1;
! /* Nonzero if a memory tag is needed for this pointer. This is
! true if this pointer is eventually dereferenced. */
! unsigned int memory_tag_needed : 1;
!
! /* Nonzero if this pointer is really dereferenced. */
unsigned int is_dereferenced : 1;
/* Nonzero if this pointer points to a global variable. */
*************** struct ptr_info_def GTY(())
*** 243,251 ****
/* Nonzero if this pointer points to NULL. */
unsigned int pt_null : 1;
- /* Mask of reasons this pointer's value escapes the function */
- ENUM_BITFIELD (escape_type) escape_mask : 9;
-
/* Set of variables that this pointer may point to. */
bitmap pt_vars;
--- 250,255 ----
*************** extern void debug_points_to_info (void);
*** 852,857 ****
--- 856,862 ----
extern void dump_points_to_info_for (FILE *, tree);
extern void debug_points_to_info_for (tree);
extern bool may_be_aliased (tree);
+ extern bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
extern struct ptr_info_def *get_ptr_info (tree);
extern void new_type_alias (tree, tree, tree);
extern void count_uses_and_derefs (tree, tree, unsigned *, unsigned *,
Index: trunk/gcc/tree-ssa-alias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias.c 2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa-alias.c 2008-06-03 15:14:31.000000000 +0200
*************** static bitmap_obstack alias_bitmap_obsta
*** 197,203 ****
/* Local functions. */
static void compute_flow_insensitive_aliasing (struct alias_info *);
static void dump_alias_stats (FILE *);
- static bool may_alias_p (tree, alias_set_type, tree, alias_set_type, bool);
static tree create_memory_tag (tree type, bool is_type_tag);
static tree get_smt_for (tree, struct alias_info *);
static tree get_nmt_for (tree);
--- 197,202 ----
*************** set_initial_properties (struct alias_inf
*** 591,604 ****
So removing this code and fixing all the bugs would be nice.
It is the cause of a bunch of clobbering. */
if ((pi->pt_global_mem || pi->pt_anything)
! && pi->is_dereferenced && pi->name_mem_tag)
{
mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
MTAG_GLOBAL (pi->name_mem_tag) = true;
}
if ((pi->pt_global_mem || pi->pt_anything)
! && pi->is_dereferenced
&& tag)
{
mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
--- 590,603 ----
So removing this code and fixing all the bugs would be nice.
It is the cause of a bunch of clobbering. */
if ((pi->pt_global_mem || pi->pt_anything)
! && pi->memory_tag_needed && pi->name_mem_tag)
{
mark_call_clobbered (pi->name_mem_tag, ESCAPE_IS_GLOBAL);
MTAG_GLOBAL (pi->name_mem_tag) = true;
}
if ((pi->pt_global_mem || pi->pt_anything)
! && pi->memory_tag_needed
&& tag)
{
mark_call_clobbered (tag, ESCAPE_IS_GLOBAL);
*************** update_reference_counts (struct mem_ref_
*** 1281,1287 ****
if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr))
&& (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
! && pi->is_dereferenced)
{
unsigned j;
bitmap_iterator bj;
--- 1280,1286 ----
if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr))
&& (pi = SSA_NAME_PTR_INFO (ptr)) != NULL
! && pi->memory_tag_needed)
{
unsigned j;
bitmap_iterator bj;
*************** reset_alias_info (void)
*** 2039,2044 ****
--- 2038,2044 ----
pi->pt_anything = 0;
pi->pt_null = 0;
pi->value_escapes_p = 0;
+ pi->memory_tag_needed = 0;
pi->is_dereferenced = 0;
if (pi->pt_vars)
bitmap_clear (pi->pt_vars);
*************** create_name_tags (void)
*** 2182,2188 ****
pi = SSA_NAME_PTR_INFO (ptr);
! if (pi->pt_anything || !pi->is_dereferenced)
{
/* No name tags for pointers that have not been
dereferenced or point to an arbitrary location. */
--- 2182,2188 ----
pi = SSA_NAME_PTR_INFO (ptr);
! if (pi->pt_anything || !pi->memory_tag_needed)
{
/* No name tags for pointers that have not been
dereferenced or point to an arbitrary location. */
*************** maybe_create_global_var (void)
*** 2661,2667 ****
VAR_ALIAS_SET is the alias set for VAR. */
! static bool
may_alias_p (tree ptr, alias_set_type mem_alias_set,
tree var, alias_set_type var_alias_set,
bool alias_set_only)
--- 2661,2667 ----
VAR_ALIAS_SET is the alias set for VAR. */
! bool
may_alias_p (tree ptr, alias_set_type mem_alias_set,
tree var, alias_set_type var_alias_set,
bool alias_set_only)
*************** dump_points_to_info_for (FILE *file, tre
*** 3224,3229 ****
--- 3224,3231 ----
if (pi->is_dereferenced)
fprintf (file, ", is dereferenced");
+ else if (pi->memory_tag_needed)
+ fprintf (file, ", is dereferenced in call");
if (pi->value_escapes_p)
fprintf (file, ", its value escapes");
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c 2008-06-03 15:14:13.000000000 +0200
--- trunk/gcc/tree-ssa-structalias.c 2008-06-03 15:15:12.000000000 +0200
*************** struct variable_info
*** 227,237 ****
/* A link to the variable for the next field in this structure. */
struct variable_info *next;
- /* True if the variable is directly the target of a dereference.
- This is used to track which variables are *actually* dereferenced
- so we can prune their points to listed. */
- unsigned int directly_dereferenced:1;
-
/* True if this is a variable created by the constraint analysis, such as
heap variables and constraints we had to break up. */
unsigned int is_artificial_var:1;
--- 227,232 ----
*************** new_var_info (tree t, unsigned int id, c
*** 364,370 ****
ret->id = id;
ret->name = name;
ret->decl = t;
- ret->directly_dereferenced = false;
ret->is_artificial_var = false;
ret->is_heap_var = false;
ret->is_special_var = false;
--- 359,364 ----
*************** process_constraint_1 (constraint_t t, bo
*** 2520,2533 ****
gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
- if (!from_call)
- {
- if (lhs.type == DEREF)
- get_varinfo (lhs.var)->directly_dereferenced = true;
- if (rhs.type == DEREF)
- get_varinfo (rhs.var)->directly_dereferenced = true;
- }
-
if (!use_field_sensitive)
{
t->rhs.offset = 0;
--- 2514,2519 ----
*************** update_alias_info (tree stmt, struct ali
*** 3369,3374 ****
--- 3355,3366 ----
is an escape point, whether OP escapes. */
count_uses_and_derefs (op, stmt, &num_uses, &num_loads, &num_stores);
+ /* For directly dereferenced pointers we can apply
+ TBAA-pruning to their points-to set. We may not count the
+ implicit dereferences &PTR->FLD here. */
+ if (num_loads + num_stores > 0)
+ pi->is_dereferenced = 1;
+
/* Handle a corner case involving address expressions of the
form '&PTR->FLD'. The problem with these expressions is that
they do not represent a dereference of PTR. However, if some
*************** update_alias_info (tree stmt, struct ali
*** 3409,3415 ****
dereferenced pointers that point to a set of
variables will be assigned a name tag to alias
all the variables OP points to. */
! pi->is_dereferenced = 1;
/* If this is a store operation, mark OP as being
dereferenced to store, otherwise mark it as being
--- 3401,3410 ----
dereferenced pointers that point to a set of
variables will be assigned a name tag to alias
all the variables OP points to. */
! pi->memory_tag_needed = 1;
!
! /* ??? For always executed direct dereferences we can
! apply TBAA-pruning to their escape set. */
/* If this is a store operation, mark OP as being
dereferenced to store, otherwise mark it as being
*************** update_alias_info (tree stmt, struct ali
*** 3443,3449 ****
|| stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
{
pointer_set_insert (ai->dereferenced_ptrs_store, var);
! pi->is_dereferenced = 1;
}
}
}
--- 3438,3444 ----
|| stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
{
pointer_set_insert (ai->dereferenced_ptrs_store, var);
! pi->memory_tag_needed = 1;
}
}
}
*************** set_uids_in_ptset (tree ptr, bitmap into
*** 4653,4662 ****
bitmap_set_bit (into, DECL_UID (vi->decl));
else
{
! alias_set_type var_alias_set, ptr_alias_set;
var_alias_set = get_alias_set (vi->decl);
! ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! if (alias_sets_conflict_p (ptr_alias_set, var_alias_set))
bitmap_set_bit (into, DECL_UID (vi->decl));
}
}
--- 4648,4658 ----
bitmap_set_bit (into, DECL_UID (vi->decl));
else
{
! alias_set_type var_alias_set, mem_alias_set;
var_alias_set = get_alias_set (vi->decl);
! mem_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr)));
! if (may_alias_p (SSA_NAME_VAR (ptr), mem_alias_set,
! vi->decl, var_alias_set, true))
bitmap_set_bit (into, DECL_UID (vi->decl));
}
}
*************** set_used_smts (void)
*** 4703,4709 ****
/* Skip the special variables and those that can't be aliased. */
if (vi->is_special_var
|| !SSA_VAR_P (var)
! || (pi && !pi->is_dereferenced)
|| (TREE_CODE (var) == VAR_DECL && !may_be_aliased (var))
|| !POINTER_TYPE_P (TREE_TYPE (var)))
continue;
--- 4699,4705 ----
/* Skip the special variables and those that can't be aliased. */
if (vi->is_special_var
|| !SSA_VAR_P (var)
! || (pi && !pi->memory_tag_needed)
|| (TREE_CODE (var) == VAR_DECL && !may_be_aliased (var))
|| !POINTER_TYPE_P (TREE_TYPE (var)))
continue;
*************** find_what_p_points_to (tree p)
*** 4797,4803 ****
bitmap finished_solution;
bitmap result;
! if (!pi->is_dereferenced)
return false;
/* This variable may have been collapsed, let's get the real
--- 4793,4799 ----
bitmap finished_solution;
bitmap result;
! if (!pi->memory_tag_needed)
return false;
/* This variable may have been collapsed, let's get the real
*************** find_what_p_points_to (tree p)
*** 4842,4848 ****
}
set_uids_in_ptset (p, finished_solution, vi->solution,
! vi->directly_dereferenced,
vi->no_tbaa_pruning);
result = shared_bitmap_lookup (finished_solution);
--- 4838,4844 ----
}
set_uids_in_ptset (p, finished_solution, vi->solution,
! pi->is_dereferenced,
vi->no_tbaa_pruning);
result = shared_bitmap_lookup (finished_solution);
Index: trunk/gcc/testsuite/gcc.c-torture/execute/20020619-1.c
===================================================================
*** trunk.orig/gcc/testsuite/gcc.c-torture/execute/20020619-1.c 2008-06-03 15:14:08.000000000 +0200
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
***************
*** 1,32 ****
- static int ref(void)
- {
- union {
- char c[5];
- int i;
- } u;
-
- __builtin_memset (&u, 0, sizeof(u));
- u.c[0] = 1;
- u.c[1] = 2;
- u.c[2] = 3;
- u.c[3] = 4;
-
- return u.i;
- }
-
- #define MAX(a,b) (a < b ? b : a)
-
- static int test(void)
- {
- char c[MAX(5, sizeof(int))] __attribute__((aligned)) = { 1, 2, 3, 4 };
- return *(int *)c;
- }
-
- int main()
- {
- int a = test();
- int b = ref();
- if (a != b)
- abort ();
- return 0;
- }
--- 0 ----
Index: trunk/gcc/tree-ssa-alias-warnings.c
===================================================================
*** trunk.orig/gcc/tree-ssa-alias-warnings.c 2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa-alias-warnings.c 2008-06-03 15:14:31.000000000 +0200
*************** dsa_named_for (tree ptr)
*** 914,919 ****
--- 914,920 ----
{
unsigned ix;
bitmap_iterator bi;
+ bool any = false;
EXECUTE_IF_SET_IN_BITMAP (pi->pt_vars, 0, ix, bi)
{
*************** dsa_named_for (tree ptr)
*** 922,928 ****
--- 923,938 ----
if (nonstandard_alias_p (ptr, alias, false))
strict_aliasing_warn (SSA_NAME_DEF_STMT (ptr),
ptr, true, alias, false, true);
+ else
+ any = true;
}
+
+ /* If there was no object in the points-to set that the pointer
+ may alias, unconditionally warn. */
+ if (!any)
+ warning (OPT_Wstrict_aliasing,
+ "dereferencing type-punned pointer %D will "
+ "break strict-aliasing rules", SSA_NAME_VAR (ptr));
}
}
}
Index: trunk/gcc/tree-ssa.c
===================================================================
*** trunk.orig/gcc/tree-ssa.c 2008-06-03 15:14:08.000000000 +0200
--- trunk/gcc/tree-ssa.c 2008-06-03 15:14:31.000000000 +0200
*************** verify_flow_sensitive_alias_info (void)
*** 558,564 ****
continue;
ann = var_ann (var);
! if (pi->is_dereferenced && !pi->name_mem_tag && !ann->symbol_mem_tag)
{
error ("dereferenced pointers should have a name or a symbol tag");
goto err;
--- 558,564 ----
continue;
ann = var_ann (var);
! if (pi->memory_tag_needed && !pi->name_mem_tag && !ann->symbol_mem_tag)
{
error ("dereferenced pointers should have a name or a symbol tag");
goto err;