From c554294001d28360a26956e7508231fca94f3074 Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Wed, 11 May 2005 08:14:44 +0000 Subject: [PATCH] re PR middle-end/19807 (fold does not fold &a[4]-1) 2005-05-11 Richard Guenther PR middle-end/19807 PR tree-optimization/19639 * fold-const.c (try_move_mult_to_index): Handle INTEGER_CST and generic summands for char* as s * delta, too, folding &a[i] CODE x to &a[i CODE x/s]. Use tree_int_cst_equal for comparison of steps. Convert types for index addition. (fold_binary): Adjust the callers to always dispatch to try_move_mult_to_index. * tree-ssa-propagate.c (set_rhs): Avoid setting rhs to expr with non-gimple ARRAY_REF offset. * g++.dg/tree-ssa/pr19807.C: New testcase. From-SVN: r99568 --- gcc/ChangeLog | 13 ++++++ gcc/fold-const.c | 82 +++++++++++++++++++++------------ gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/tree-ssa/pr19807.C | 24 ++++++++++ gcc/tree-ssa-propagate.c | 6 +++ 5 files changed, 102 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/g++.dg/tree-ssa/pr19807.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1621f15..d6dd1b7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,18 @@ 2005-05-11 Richard Guenther + PR middle-end/19807 + PR tree-optimization/19639 + * fold-const.c (try_move_mult_to_index): Handle INTEGER_CST + and generic summands for char* as s * delta, too, folding &a[i] + CODE x to &a[i CODE x/s]. Use tree_int_cst_equal + for comparison of steps. Convert types for index addition. + (fold_binary): Adjust the callers to always dispatch to + try_move_mult_to_index. + * tree-ssa-propagate.c (set_rhs): Avoid setting rhs to + expr with non-gimple ARRAY_REF offset. + +2005-05-11 Richard Guenther + * fold-const.c (fold_indirect_ref_1): Avoid removing NOP_EXPRs with type qualifiers like const. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index dc8d417..21250f6 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6259,55 +6259,81 @@ fold_sign_changed_comparison (enum tree_code code, tree type, } /* Tries to replace &a[idx] CODE s * delta with &a[idx CODE delta], if s is - step of the array. ADDR is the address. MULT is the multiplicative expression. + step of the array. Reconstructs s and delta in the case of s * delta + being an integer constant (and thus already folded). + ADDR is the address. MULT is the multiplicative expression. If the function succeeds, the new address expression is returned. Otherwise NULL_TREE is returned. */ static tree -try_move_mult_to_index (enum tree_code code, tree addr, tree mult) +try_move_mult_to_index (enum tree_code code, tree addr, tree op1) { tree s, delta, step; - tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1); tree ref = TREE_OPERAND (addr, 0), pref; tree ret, pos; tree itype; - STRIP_NOPS (arg0); - STRIP_NOPS (arg1); - - if (TREE_CODE (arg0) == INTEGER_CST) + /* Canonicalize op1 into a possibly non-constant delta + and an INTEGER_CST s. */ + if (TREE_CODE (op1) == MULT_EXPR) { - s = arg0; - delta = arg1; + tree arg0 = TREE_OPERAND (op1, 0), arg1 = TREE_OPERAND (op1, 1); + + STRIP_NOPS (arg0); + STRIP_NOPS (arg1); + + if (TREE_CODE (arg0) == INTEGER_CST) + { + s = arg0; + delta = arg1; + } + else if (TREE_CODE (arg1) == INTEGER_CST) + { + s = arg1; + delta = arg0; + } + else + return NULL_TREE; } - else if (TREE_CODE (arg1) == INTEGER_CST) + else if (TREE_CODE (op1) == INTEGER_CST) { - s = arg1; - delta = arg0; + delta = op1; + s = NULL_TREE; } else - return NULL_TREE; + { + /* Simulate we are delta * 1. */ + delta = op1; + s = integer_one_node; + } for (;; ref = TREE_OPERAND (ref, 0)) { if (TREE_CODE (ref) == ARRAY_REF) { step = array_ref_element_size (ref); - if (TREE_CODE (step) != INTEGER_CST) continue; - itype = TREE_TYPE (step); + if (s) + { + if (! tree_int_cst_equal (step, s)) + continue; + } + else + { + /* Try if delta is a multiple of step. */ + tree mod = int_const_binop (TRUNC_MOD_EXPR, delta, step, 0); + if (!integer_zerop (mod)) + continue; - /* If the type sizes do not match, we might run into problems - when one of them would overflow. */ - if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s))) - continue; + delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0); + } - if (!operand_equal_p (step, fold_convert (itype, s), 0)) + itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0))); + if (! itype) continue; - delta = fold_convert (itype, delta); break; } @@ -6330,8 +6356,9 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree mult) } TREE_OPERAND (pos, 1) = fold_build2 (code, itype, - TREE_OPERAND (pos, 1), - delta); + fold_convert (itype, + TREE_OPERAND (pos, 1)), + fold_convert (itype, delta)); return build1 (ADDR_EXPR, TREE_TYPE (addr), ret); } @@ -7441,15 +7468,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step of the array. Loop optimizer sometimes produce this type of expressions. */ - if (TREE_CODE (arg0) == ADDR_EXPR - && TREE_CODE (arg1) == MULT_EXPR) + if (TREE_CODE (arg0) == ADDR_EXPR) { tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1); if (tem) return fold_convert (type, fold (tem)); } - else if (TREE_CODE (arg1) == ADDR_EXPR - && TREE_CODE (arg0) == MULT_EXPR) + else if (TREE_CODE (arg1) == ADDR_EXPR) { tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0); if (tem) @@ -7867,8 +7892,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step of the array. Loop optimizer sometimes produce this type of expressions. */ - if (TREE_CODE (arg0) == ADDR_EXPR - && TREE_CODE (arg1) == MULT_EXPR) + if (TREE_CODE (arg0) == ADDR_EXPR) { tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1); if (tem) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d92bf93..030b2fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2005-05-11 Richard Guenther + + PR middle-end/19807 + PR tree-optimization/19639 + * g++.dg/tree-ssa/pr19807.C: New testcase. + 2005-05-10 Francois-Xavier Coudert PR libfortran/21471 diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr19807.C b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C new file mode 100644 index 0000000..0ff10db --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/pr19807.C @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int a[4]; +int *x, *y, *z; + +void foo(void) +{ + x = &a[3] - 1; + y = &a[1] + 1; + z = 1 + &a[1]; +} + +void bar(int i) +{ + x = &a[i] - 1; + y = &a[i] + 1; + z = 1 + &a[i]; +} + +/* { dg-final { scan-tree-dump-times "&a\\\[2\\\]" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "&a\\\[.* - 1\\\]" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "&a\\\[.* \\+ 1\\\]" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index 9f9fef1..c83d2cd 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -576,6 +576,12 @@ set_rhs (tree *stmt_p, tree expr) if (!is_gimple_val (TREE_OPERAND (expr, 0))) return false; } + else if (code == ADDR_EXPR) + { + if (TREE_CODE (TREE_OPERAND (expr, 0)) == ARRAY_REF + && !is_gimple_val (TREE_OPERAND (TREE_OPERAND (expr, 0), 1))) + return false; + } else if (code == COMPOUND_EXPR) return false; -- 2.7.4