tree-ssa-alias.c (count_ptr_derefs): Do not consider &PTR->FLD a dereference of PTR.

* tree-ssa-alias.c (count_ptr_derefs): Do not consider
        &PTR->FLD a dereference of PTR.
        * tree-ssa-structalias.c (update_alias_info): Consider &PTR->FLD
        a potential dereference of PTR.

testsuite/ChangeLog

        * gcc.dg/tree-ssa/20050719-1.c: New test.

From-SVN: r102283
This commit is contained in:
Diego Novillo 2005-07-22 13:39:18 +00:00 committed by Diego Novillo
parent 191e1ff2f5
commit 17c7e33e8c
5 changed files with 95 additions and 4 deletions

View File

@ -1,3 +1,10 @@
2005-07-22 Diego Novillo <dnovillo@redhat.com>
* tree-ssa-alias.c (count_ptr_derefs): Do not consider
&PTR->FLD a dereference of PTR.
* tree-ssa-structalias.c (update_alias_info): Consider &PTR->FLD
a potential dereference of PTR.
2005-07-22 J"orn Rennecke <joern.rennecke@st.com>
PR rtl-optimization/20370

View File

@ -1,3 +1,7 @@
2005-07-22 Diego Novillo <dnovillo@redhat.com>
* gcc.dg/tree-ssa/20050719-1.c: New test.
2005-07-22 Bernd Schmidt <bernd.schmidt@analog.com>
* gcc.dg/bfin-longcall-1.c: New file.

View File

@ -0,0 +1,37 @@
/* { dg-do run } */
/* { dg-options "-O2" } */
extern void abort (void) __attribute__ ((__nothrow__)) __attribute__
((__noreturn__));
extern void exit (int __status) __attribute__ ((__nothrow__))
__attribute__ ((__noreturn__));
struct bootLoader {
int x;
};
void
zap(struct bootLoader *bootLoader)
{
/* The expression on the RHS of the assignment is *not* a
dereference of pointer 'bootLoader'. It is merely used as an
offset calculation. VRP was erroneously removing the if()
because it thought that 'bootLoader' was always dereferenced. */
int *boot = &bootLoader->x;
if (bootLoader)
{
useboot (boot);
}
}
int
useboot (void *boot)
{
abort ();
}
main()
{
zap (0);
}

View File

@ -344,12 +344,20 @@ struct count_ptr_d
(ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */
static tree
count_ptr_derefs (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, void *data)
count_ptr_derefs (tree *tp, int *walk_subtrees, void *data)
{
struct count_ptr_d *count_p = (struct count_ptr_d *) data;
/* Do not walk inside ADDR_EXPR nodes. In the expression &ptr->fld,
pointer 'ptr' is *not* dereferenced, it is simply used to compute
the address of 'fld' as 'ptr + offsetof(fld)'. */
if (TREE_CODE (*tp) == ADDR_EXPR)
{
*walk_subtrees = 0;
return NULL_TREE;
}
if (INDIRECT_REF_P (*tp) && TREE_OPERAND (*tp, 0) == count_p->ptr)
/* || (TREE_CODE (*tp) == MEM_REF && MEM_REF_SYMBOL (*tp) == count_p->ptr)) */
count_p->count++;
return NULL_TREE;

View File

@ -2555,7 +2555,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
tree op, var;
var_ann_t v_ann;
struct ptr_info_def *pi;
bool is_store;
bool is_store, is_potential_deref;
unsigned num_uses, num_derefs;
op = USE_FROM_PTR (use_p);
@ -2612,7 +2612,42 @@ update_alias_info (tree stmt, struct alias_info *ai)
is an escape point, whether OP escapes. */
count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
if (num_derefs > 0)
/* 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
other transformation propagates them into an INDIRECT_REF
expression, we end up with '*(&PTR->FLD)' which is folded
into 'PTR->FLD'.
So, if the original code had no other dereferences of PTR,
the aliaser will not create memory tags for it, and when
&PTR->FLD gets propagated to INDIRECT_REF expressions, the
memory operations will receive no V_MAY_DEF/VUSE operands.
One solution would be to have count_uses_and_derefs consider
&PTR->FLD a dereference of PTR. But that is wrong, since it
is not really a dereference but an offset calculation.
What we do here is to recognize these special ADDR_EXPR
nodes. Since these expressions are never GIMPLE values (they
are not GIMPLE invariants), they can only appear on the RHS
of an assignment and their base address is always an
INDIRECT_REF expression. */
is_potential_deref = false;
if (TREE_CODE (stmt) == MODIFY_EXPR
&& TREE_CODE (TREE_OPERAND (stmt, 1)) == ADDR_EXPR
&& !is_gimple_val (TREE_OPERAND (stmt, 1)))
{
/* If the RHS if of the form &PTR->FLD and PTR == OP, then
this represents a potential dereference of PTR. */
tree rhs = TREE_OPERAND (stmt, 1);
tree base = get_base_address (TREE_OPERAND (rhs, 0));
if (TREE_CODE (base) == INDIRECT_REF
&& TREE_OPERAND (base, 0) == op)
is_potential_deref = true;
}
if (num_derefs > 0 || is_potential_deref)
{
/* Mark OP as dereferenced. In a subsequent pass,
dereferenced pointers that point to a set of