From e79b60a72c50b9d1ba1e196048cb6c4329556cba Mon Sep 17 00:00:00 2001 From: Diego Novillo Date: Sat, 8 Jan 2005 13:31:39 -0500 Subject: [PATCH] [multiple changes] 2005-01-08 Jeff Law Diego Novillo * 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 * 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 | 9 +++ gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/gcc.dg/pr18241-1.c | 107 +++++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/pr18241-2.c | 65 +++++++++++++++++++ gcc/testsuite/gcc.dg/pr18241-3.c | 31 +++++++++ gcc/testsuite/gcc.dg/pr18241-4.c | 22 +++++++ gcc/testsuite/gcc.dg/pr18241-5.c | 14 ++++ gcc/tree-nrv.c | 1 + gcc/tree-ssa-dse.c | 4 ++ gcc/tree-ssa-operands.c | 11 ++-- 10 files changed, 265 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr18241-1.c create mode 100644 gcc/testsuite/gcc.dg/pr18241-2.c create mode 100644 gcc/testsuite/gcc.dg/pr18241-3.c create mode 100644 gcc/testsuite/gcc.dg/pr18241-4.c create mode 100644 gcc/testsuite/gcc.dg/pr18241-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f1133b36da86..5960c6ef9e7b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2005-01-08 Jeff Law + Diego Novillo + + * 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 * tree.c (int_fits_type_p): Always honor integer constant diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 55a54aa192b1..ce3e92af33cf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2005-01-08 Diego Novillo + + * 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 * 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 index 000000000000..6f5bd9c0593f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18241-1.c @@ -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 index 000000000000..dce9656a8332 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18241-2.c @@ -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 index 000000000000..e2bc3d7ff433 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18241-3.c @@ -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 index 000000000000..ba18d6eee341 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18241-4.c @@ -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 index 000000000000..e462a657f4c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr18241-5.c @@ -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; +} diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index 0df0712d19c3..71de0db82c22 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -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) diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 93ceaeb0730a..86622e96bb24 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -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); diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index fc43a196e524..2ca208ef8fc5 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -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) { -- 2.43.5