[multiple changes]
authorDiego Novillo <dnovillo@gcc.gnu.org>
Sat, 8 Jan 2005 18:31:39 +0000 (13:31 -0500)
committerDiego Novillo <dnovillo@gcc.gnu.org>
Sat, 8 Jan 2005 18:31:39 +0000 (13:31 -0500)
2005-01-08  Jeff Law  <law@redhat.com>
    Diego Novillo  <dnovillo@redhat.com>

* tree-nrv.c (tree_nrv): Ignore volatile return values.
* tree-ssa-dse.c (dse_optimize_stmt): Do not optimize
statements with volatile operands.
* tree-ssa-operands.c (add_stmt_operand): Do add volatile
operands after marking a statement with has_volatile_ops.

testsuite/ChangeLog:

2005-01-08  Diego Novillo  <dnovillo@redhat.com>

* gcc.dg/pr18241-1.c: New test.
* gcc.dg/pr18241-2.c: New test.
* gcc.dg/pr18241-3.c: New test.
* gcc.dg/pr18241-4.c: New test.
* gcc.dg/pr18241-5.c: New test.

From-SVN: r93088

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr18241-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr18241-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr18241-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr18241-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr18241-5.c [new file with mode: 0644]
gcc/tree-nrv.c
gcc/tree-ssa-dse.c
gcc/tree-ssa-operands.c

index f1133b3..5960c6e 100644 (file)
@@ -1,3 +1,12 @@
+2005-01-08  Jeff Law  <law@redhat.com>
+           Diego Novillo  <dnovillo@redhat.com>
+
+       * tree-nrv.c (tree_nrv): Ignore volatile return values.
+       * tree-ssa-dse.c (dse_optimize_stmt): Do not optimize
+       statements with volatile operands.
+       * tree-ssa-operands.c (add_stmt_operand): Do add volatile
+       operands after marking a statement with has_volatile_ops.
+
 2005-01-08  Roger Sayle  <roger@eyesopen.com>
 
        * tree.c (int_fits_type_p): Always honor integer constant
index 55a54aa..ce3e92a 100644 (file)
@@ -1,3 +1,11 @@
+2005-01-08  Diego Novillo  <dnovillo@redhat.com>
+
+       * gcc.dg/pr18241-1.c: New test.
+       * gcc.dg/pr18241-2.c: New test.
+       * gcc.dg/pr18241-3.c: New test.
+       * gcc.dg/pr18241-4.c: New test.
+       * gcc.dg/pr18241-5.c: New test.
+
 2005-01-08  Steven G. Kargl  <kargls@comcast.net>
 
        * gfortran.dg/select_2.f90, gfortran.dg/select_3.f90,
diff --git a/gcc/testsuite/gcc.dg/pr18241-1.c b/gcc/testsuite/gcc.dg/pr18241-1.c
new file mode 100644 (file)
index 0000000..6f5bd9c
--- /dev/null
@@ -0,0 +1,107 @@
+/* { dg-do execute } */
+/* { dg-options "-std=gnu99 -Wall -Wextra -O1" } */ 
+
+extern void *memset (void*, int, unsigned long);
+extern void abort (void);
+
+struct radix_tree_root {
+       unsigned int height;
+       struct radix_tree_node *rnode;
+};
+
+struct radix_tree_node {
+       unsigned int count;
+       void *slots[64];
+       unsigned long tags[2][2];
+};
+
+struct radix_tree_path {
+       struct radix_tree_node *node, **slot;
+       int offset;
+};
+
+static unsigned long height_to_maxindex[7] =
+{0, 63, 4095, 262143, 16777215, 1073741823, 4294967295};
+
+static inline void tag_clear(struct radix_tree_node *node, int tag, int offset)
+{
+       int nr;
+       volatile unsigned long *addr;
+       int mask;
+       
+       nr = offset;
+       addr = &node->tags[tag][0];
+
+       addr += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+       *addr &= ~mask;
+}
+
+void *radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index, int tag)
+{
+       struct radix_tree_path path[7], *pathp = path;
+       unsigned int height, shift;
+       void *ret = 0;
+       
+       height = root->height;
+       if (index > height_to_maxindex[height])
+               goto out;
+       
+       shift = (height - 1) * 6;
+       pathp->node = 0;
+       pathp->slot = &root->rnode;
+       
+       while (height > 0) {
+               int offset;
+               
+               if (*pathp->slot == 0)
+                       goto out;
+               
+               offset = (index >> shift) & (64-1);
+               pathp[1].offset = offset;
+               pathp[1].node = *pathp[0].slot;
+               pathp[1].slot = (struct radix_tree_node **)
+                       (pathp[1].node->slots + offset);
+               pathp++;
+               shift -= 6;
+               height--;
+       }
+       
+       ret = *pathp[0].slot;
+       if (ret == 0)
+               goto out;
+       
+       do {
+               int idx;
+               
+               tag_clear(pathp[0].node, tag, pathp[0].offset);
+               for (idx = 0; idx < 2; idx++) {
+                       if (pathp[0].node->tags[tag][idx])
+                               goto out;
+               }
+               pathp--;
+       } while (pathp[0].node);
+out:
+       return ret;
+}
+
+int main ()
+{
+       struct radix_tree_root r;
+       struct radix_tree_node node;
+       void *p = (void *) 0xdeadbeef;
+       
+       r.height = 1;
+       r.rnode = &node;
+       
+       memset (&node, 0, sizeof (node));
+       
+       node.count = 1;
+       node.slots [13] = p;
+       
+       radix_tree_tag_clear (&r, 13, 1);
+       
+       if (r.rnode->slots[13] != p)
+               abort ();
+       return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr18241-2.c b/gcc/testsuite/gcc.dg/pr18241-2.c
new file mode 100644 (file)
index 0000000..dce9656
--- /dev/null
@@ -0,0 +1,65 @@
+/* { dg-do execute } */
+/* { dg-options "-std=gnu99 -Wall -Wextra -O1" } */ 
+
+extern void *memset (void*, int, unsigned long);
+extern void abort (void);
+
+struct radix_tree_root {
+       unsigned int height;
+       struct radix_tree_node *rnode;
+};
+
+struct radix_tree_node {
+       unsigned int count;
+       void *slots[64];
+       unsigned long tags[2];
+};
+
+struct radix_tree_path {
+       struct radix_tree_node *node, **slot;
+       int offset;
+};
+
+void radix_tree_tag_clear(struct radix_tree_root *root, unsigned long index)
+{
+       struct radix_tree_path path[7], *pathp = path;
+       unsigned int height, shift;
+       volatile unsigned long *addr;
+       
+       height = root->height;
+       
+       shift = (height - 1) * 6;
+       path[0].slot = &root->rnode;
+       
+       while (height > 0) {
+               int offset;
+               
+               offset = (index >> shift) & (64-1);
+               pathp[1].offset = offset;
+               pathp[1].node = *pathp[0].slot;
+               pathp[1].slot = (struct radix_tree_node **)
+                       (pathp[1].node->slots + offset);
+               pathp++;
+               shift -= 6;
+               height--;
+       }
+       
+       addr = &(pathp->node->tags[0]) + 1;
+       *addr = 574;
+}
+
+struct radix_tree_root r;
+struct radix_tree_node node;
+
+int main ()
+{
+       r.height = 1;
+       r.rnode = &node;
+       
+       memset (&node, 0, sizeof (node));
+       
+       node.count = 1;
+       
+       radix_tree_tag_clear (&r, 13);
+       return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr18241-3.c b/gcc/testsuite/gcc.dg/pr18241-3.c
new file mode 100644 (file)
index 0000000..e2bc3d7
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do execute } */
+/* { dg-options "-O1" } */ 
+
+void abort (void);
+
+void radix_tree_tag_clear (int *node)
+{
+       int *path[2], **pathp = path, height;
+       volatile int *addr;
+       
+       height = 1;
+       pathp[0] = node;
+       
+       while (height > 0) {
+               pathp[1] = pathp[0];
+               pathp++;
+               height--;
+       }
+       
+       addr = pathp[0];
+       *addr = 1;
+}
+
+int main ()
+{
+       int n;
+       radix_tree_tag_clear (&n);
+       if (n != 1)
+               abort ();
+       return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr18241-4.c b/gcc/testsuite/gcc.dg/pr18241-4.c
new file mode 100644 (file)
index 0000000..ba18d6e
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do execute } */
+/* { dg-options "-O1" } */ 
+
+void abort (void);
+
+int f(int i1243)
+{
+  int i[2], *i1 = i;
+  i[0] = 1;
+  volatile int *i2 = i1;
+  i2[1] = 1;
+  i1243 = 0;
+  return i2[1]+i2[0];
+}
+
+
+int main(void)
+{
+  if( f(100) != 2)
+   abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr18241-5.c b/gcc/testsuite/gcc.dg/pr18241-5.c
new file mode 100644 (file)
index 0000000..e462a65
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do execute } */
+/* { dg-options "-O1" } */ 
+
+void abort (void);
+
+int main ()
+{
+  int a;
+  volatile int *b = &a;
+  a = 1;
+  if (*b != 1)
+    abort ();
+  return 0;
+}
index 0df0712..71de0db 100644 (file)
@@ -154,6 +154,7 @@ tree_nrv (void)
          /* The returned value must be a local automatic variable of the
             same type and alignment as the function's result.  */
          if (TREE_CODE (found) != VAR_DECL
+             || TREE_THIS_VOLATILE (found)
              || DECL_CONTEXT (found) != current_function_decl
              || TREE_STATIC (found)
              || TREE_ADDRESSABLE (found)
index 93ceaeb..86622e9 100644 (file)
@@ -259,6 +259,10 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
      not also a function call, then record it into our table.  */
   if (get_call_expr_in (stmt))
     return;
+
+  if (ann->has_volatile_ops)
+    return;
+
   if (TREE_CODE (stmt) == MODIFY_EXPR)
     {
       dataflow_t df = get_immediate_uses (stmt);
index fc43a19..2ca208e 100644 (file)
@@ -1520,13 +1520,10 @@ add_stmt_operand (tree *var_p, stmt_ann_t s_ann, int flags)
   sym = (TREE_CODE (var) == SSA_NAME ? SSA_NAME_VAR (var) : var);
   v_ann = var_ann (sym);
 
-  /* Don't expose volatile variables to the optimizers.  */
-  if (TREE_THIS_VOLATILE (sym))
-    {
-      if (s_ann)
-       s_ann->has_volatile_ops = true;
-      return;
-    }
+  /* Mark statements with volatile operands.  Optimizers should back
+     off from statements having volatile operands.  */
+  if (TREE_THIS_VOLATILE (sym) && s_ann)
+    s_ann->has_volatile_ops = true;
 
   if (is_real_op)
     {