From e911adadf279416c4acaa4479b60c0ad020159db Mon Sep 17 00:00:00 2001 From: dnovillo Date: Fri, 22 Jul 2005 13:39:18 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@102283 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 7 ++++++ gcc/testsuite/ChangeLog | 4 +++ gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c | 37 ++++++++++++++++++++++++++++ gcc/tree-ssa-alias.c | 12 +++++++-- gcc/tree-ssa-structalias.c | 39 ++++++++++++++++++++++++++++-- 5 files changed, 95 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index faddc8357e1..e93626f4008 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-07-22 Diego Novillo + + * 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 PR rtl-optimization/20370 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a71759e1f93..25db24b931a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-07-22 Diego Novillo + + * gcc.dg/tree-ssa/20050719-1.c: New test. + 2005-07-22 Bernd Schmidt * gcc.dg/bfin-longcall-1.c: New file. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c new file mode 100644 index 00000000000..a1c08e34d29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c @@ -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); +} diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index c65fe8d043f..76d883ab64c 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -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; diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 867c6a76364..2a10a8d3d11 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -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 -- 2.11.4.GIT