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:
parent
191e1ff2f5
commit
17c7e33e8c
@ -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
|
||||
|
@ -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.
|
||||
|
37
gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c
Normal file
37
gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c
Normal 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);
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user