aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDiego Novillo <dnovillo@redhat.com>2005-07-22 13:39:18 +0000
committerDiego Novillo <dnovillo@gcc.gnu.org>2005-07-22 09:39:18 -0400
commit17c7e33e8c288eda8ec9316dad5daea43299f584 (patch)
treea90ff2874706640af3b68570fabd2d4bcd045798 /gcc
parent191e1ff2f56a8b5148ccca1e3c30283af9905cee (diff)
downloadgcc-17c7e33e8c288eda8ec9316dad5daea43299f584.zip
gcc-17c7e33e8c288eda8ec9316dad5daea43299f584.tar.gz
gcc-17c7e33e8c288eda8ec9316dad5daea43299f584.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c37
-rw-r--r--gcc/tree-ssa-alias.c12
-rw-r--r--gcc/tree-ssa-structalias.c39
5 files changed, 95 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index faddc83..e93626f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a71759e..25db24b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
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 0000000..a1c08e3
--- /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 c65fe8d..76d883a 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 867c6a7..2a10a8d 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