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
5 changed files with 95 additions and 4 deletions
|
@ -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>
|
2005-07-22 J"orn Rennecke <joern.rennecke@st.com>
|
||||||
|
|
||||||
PR rtl-optimization/20370
|
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>
|
2005-07-22 Bernd Schmidt <bernd.schmidt@analog.com>
|
||||||
|
|
||||||
* gcc.dg/bfin-longcall-1.c: New file.
|
* 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. */
|
(ALIGN/MISALIGNED_)INDIRECT_REF nodes for the pointer passed in DATA. */
|
||||||
|
|
||||||
static tree
|
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;
|
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)
|
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++;
|
count_p->count++;
|
||||||
|
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
|
@ -2555,7 +2555,7 @@ update_alias_info (tree stmt, struct alias_info *ai)
|
||||||
tree op, var;
|
tree op, var;
|
||||||
var_ann_t v_ann;
|
var_ann_t v_ann;
|
||||||
struct ptr_info_def *pi;
|
struct ptr_info_def *pi;
|
||||||
bool is_store;
|
bool is_store, is_potential_deref;
|
||||||
unsigned num_uses, num_derefs;
|
unsigned num_uses, num_derefs;
|
||||||
|
|
||||||
op = USE_FROM_PTR (use_p);
|
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. */
|
is an escape point, whether OP escapes. */
|
||||||
count_uses_and_derefs (op, stmt, &num_uses, &num_derefs, &is_store);
|
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,
|
/* Mark OP as dereferenced. In a subsequent pass,
|
||||||
dereferenced pointers that point to a set of
|
dereferenced pointers that point to a set of
|
||||||
|
|
Loading…
Add table
Reference in a new issue