Commit c5542940 by Richard Guenther Committed by Richard Biener

re PR middle-end/19807 (fold does not fold &a[4]-1)

2005-05-11  Richard Guenther  <rguenth@gcc.gnu.org>

	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
parent 8a29ce60
2005-05-11 Richard Guenther <rguenth@gcc.gnu.org> 2005-05-11 Richard Guenther <rguenth@gcc.gnu.org>
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 <rguenth@gcc.gnu.org>
* fold-const.c (fold_indirect_ref_1): Avoid removing * fold-const.c (fold_indirect_ref_1): Avoid removing
NOP_EXPRs with type qualifiers like const. NOP_EXPRs with type qualifiers like const.
......
...@@ -6259,55 +6259,81 @@ fold_sign_changed_comparison (enum tree_code code, tree type, ...@@ -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 /* 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 If the function succeeds, the new address expression is returned. Otherwise
NULL_TREE is returned. */ NULL_TREE is returned. */
static tree 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 s, delta, step;
tree arg0 = TREE_OPERAND (mult, 0), arg1 = TREE_OPERAND (mult, 1);
tree ref = TREE_OPERAND (addr, 0), pref; tree ref = TREE_OPERAND (addr, 0), pref;
tree ret, pos; tree ret, pos;
tree itype; tree itype;
STRIP_NOPS (arg0); /* Canonicalize op1 into a possibly non-constant delta
STRIP_NOPS (arg1); and an INTEGER_CST s. */
if (TREE_CODE (op1) == MULT_EXPR)
if (TREE_CODE (arg0) == INTEGER_CST)
{ {
s = arg0; tree arg0 = TREE_OPERAND (op1, 0), arg1 = TREE_OPERAND (op1, 1);
delta = arg1;
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 = op1;
delta = arg0; s = NULL_TREE;
} }
else else
return NULL_TREE; {
/* Simulate we are delta * 1. */
delta = op1;
s = integer_one_node;
}
for (;; ref = TREE_OPERAND (ref, 0)) for (;; ref = TREE_OPERAND (ref, 0))
{ {
if (TREE_CODE (ref) == ARRAY_REF) if (TREE_CODE (ref) == ARRAY_REF)
{ {
step = array_ref_element_size (ref); step = array_ref_element_size (ref);
if (TREE_CODE (step) != INTEGER_CST) if (TREE_CODE (step) != INTEGER_CST)
continue; 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 delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0);
when one of them would overflow. */ }
if (TYPE_PRECISION (itype) != TYPE_PRECISION (TREE_TYPE (s)))
continue;
if (!operand_equal_p (step, fold_convert (itype, s), 0)) itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
if (! itype)
continue; continue;
delta = fold_convert (itype, delta);
break; break;
} }
...@@ -6330,8 +6356,9 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree mult) ...@@ -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) = fold_build2 (code, itype,
TREE_OPERAND (pos, 1), fold_convert (itype,
delta); TREE_OPERAND (pos, 1)),
fold_convert (itype, delta));
return build1 (ADDR_EXPR, TREE_TYPE (addr), ret); return build1 (ADDR_EXPR, TREE_TYPE (addr), ret);
} }
...@@ -7441,15 +7468,13 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) ...@@ -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 /* Try replacing &a[i1] + c * i2 with &a[i1 + i2], if c is step
of the array. Loop optimizer sometimes produce this type of of the array. Loop optimizer sometimes produce this type of
expressions. */ expressions. */
if (TREE_CODE (arg0) == ADDR_EXPR if (TREE_CODE (arg0) == ADDR_EXPR)
&& TREE_CODE (arg1) == MULT_EXPR)
{ {
tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1); tem = try_move_mult_to_index (PLUS_EXPR, arg0, arg1);
if (tem) if (tem)
return fold_convert (type, fold (tem)); return fold_convert (type, fold (tem));
} }
else if (TREE_CODE (arg1) == ADDR_EXPR else if (TREE_CODE (arg1) == ADDR_EXPR)
&& TREE_CODE (arg0) == MULT_EXPR)
{ {
tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0); tem = try_move_mult_to_index (PLUS_EXPR, arg1, arg0);
if (tem) if (tem)
...@@ -7867,8 +7892,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) ...@@ -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 /* Try replacing &a[i1] - c * i2 with &a[i1 - i2], if c is step
of the array. Loop optimizer sometimes produce this type of of the array. Loop optimizer sometimes produce this type of
expressions. */ expressions. */
if (TREE_CODE (arg0) == ADDR_EXPR if (TREE_CODE (arg0) == ADDR_EXPR)
&& TREE_CODE (arg1) == MULT_EXPR)
{ {
tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1); tem = try_move_mult_to_index (MINUS_EXPR, arg0, arg1);
if (tem) if (tem)
......
2005-05-11 Richard Guenther <rguenth@gcc.gnu.org>
PR middle-end/19807
PR tree-optimization/19639
* g++.dg/tree-ssa/pr19807.C: New testcase.
2005-05-10 Francois-Xavier Coudert <coudert@clipper.ens.fr> 2005-05-10 Francois-Xavier Coudert <coudert@clipper.ens.fr>
PR libfortran/21471 PR libfortran/21471
......
/* { 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" } } */
...@@ -576,6 +576,12 @@ set_rhs (tree *stmt_p, tree expr) ...@@ -576,6 +576,12 @@ set_rhs (tree *stmt_p, tree expr)
if (!is_gimple_val (TREE_OPERAND (expr, 0))) if (!is_gimple_val (TREE_OPERAND (expr, 0)))
return false; 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) else if (code == COMPOUND_EXPR)
return false; return false;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment