Commit 108f6c2f by Richard Guenther Committed by Richard Biener

tree.h (div_if_zero_remainder): Declare.

2009-03-31  Richard Guenther  <rguenther@suse.de>

	* tree.h (div_if_zero_remainder): Declare.
	* fold-const.c (div_if_zero_remainder): Export.
	* tree-ssa-forwprop.c
	(forward_propagate_addr_into_variable_array_index): Handle
	constant array index addition outside of the variable index.

	* gcc.dg/tree-ssa/forwprop-12.c: New testcase.

From-SVN: r145343
parent 8f612190
2009-03-31 Richard Guenther <rguenther@suse.de>
* tree.h (div_if_zero_remainder): Declare.
* fold-const.c (div_if_zero_remainder): Export.
* tree-ssa-forwprop.c
(forward_propagate_addr_into_variable_array_index): Handle
constant array index addition outside of the variable index.
2009-03-31 Joseph Myers <joseph@codesourcery.com> 2009-03-31 Joseph Myers <joseph@codesourcery.com>
PR target/39592 PR target/39592
......
...@@ -874,7 +874,7 @@ div_and_round_double (enum tree_code code, int uns, ...@@ -874,7 +874,7 @@ div_and_round_double (enum tree_code code, int uns,
of type CODE and returns the quotient. of type CODE and returns the quotient.
Otherwise returns NULL_TREE. */ Otherwise returns NULL_TREE. */
static tree tree
div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2) div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
{ {
unsigned HOST_WIDE_INT int1l, int2l; unsigned HOST_WIDE_INT int1l, int2l;
......
2009-03-31 Richard Guenther <rguenther@suse.de>
* gcc.dg/tree-ssa/forwprop-12.c: New testcase.
2009-03-31 Joseph Myers <joseph@codesourcery.com> 2009-03-31 Joseph Myers <joseph@codesourcery.com>
PR target/39592 PR target/39592
......
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-forwprop1" } */
struct X { int a[256]; };
int foo(struct X *p, __SIZE_TYPE__ i)
{
int *q = &p->a[0];
int *q2 = (int *)((void *)q + i*4 + 32);
return *q2;
}
int bar(struct X *p, int i)
{
return *((int *)p + i + 8);
}
/* We should have propagated the base array address through the
address arithmetic into the memory access as an array access. */
/* { dg-final { scan-tree-dump-times "->a\\\[D\\\." 2 "forwprop1" } } */
/* { dg-final { cleanup-tree-dump "forwprop1" } } */
...@@ -618,8 +618,13 @@ forward_propagate_addr_into_variable_array_index (tree offset, ...@@ -618,8 +618,13 @@ forward_propagate_addr_into_variable_array_index (tree offset,
tree def_rhs, tree def_rhs,
gimple_stmt_iterator *use_stmt_gsi) gimple_stmt_iterator *use_stmt_gsi)
{ {
tree index; tree index, tunit;
gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi); gimple offset_def, use_stmt = gsi_stmt (*use_stmt_gsi);
tree tmp;
tunit = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)));
if (!host_integerp (tunit, 1))
return false;
/* Get the offset's defining statement. */ /* Get the offset's defining statement. */
offset_def = SSA_NAME_DEF_STMT (offset); offset_def = SSA_NAME_DEF_STMT (offset);
...@@ -629,7 +634,7 @@ forward_propagate_addr_into_variable_array_index (tree offset, ...@@ -629,7 +634,7 @@ forward_propagate_addr_into_variable_array_index (tree offset,
along in case the element size is one. In that case, however, we do not along in case the element size is one. In that case, however, we do not
allow multiplications because they can be computing index to a higher allow multiplications because they can be computing index to a higher
level dimension (PR 37861). */ level dimension (PR 37861). */
if (integer_onep (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs))))) if (integer_onep (tunit))
{ {
if (is_gimple_assign (offset_def) if (is_gimple_assign (offset_def)
&& gimple_assign_rhs_code (offset_def) == MULT_EXPR) && gimple_assign_rhs_code (offset_def) == MULT_EXPR)
...@@ -648,18 +653,41 @@ forward_propagate_addr_into_variable_array_index (tree offset, ...@@ -648,18 +653,41 @@ forward_propagate_addr_into_variable_array_index (tree offset,
multiplication of an object by the size of the array elements. multiplication of an object by the size of the array elements.
This implicitly verifies that the size of the array elements This implicitly verifies that the size of the array elements
is constant. */ is constant. */
offset = gimple_assign_rhs1 (offset_def); if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
if (gimple_assign_rhs_code (offset_def) != MULT_EXPR && TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
|| TREE_CODE (gimple_assign_rhs2 (offset_def)) != INTEGER_CST && tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit))
|| !simple_cst_equal (gimple_assign_rhs2 (offset_def), {
TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs))))) /* The first operand to the MULT_EXPR is the desired index. */
index = gimple_assign_rhs1 (offset_def);
}
/* If we have idx * tunit + CST * tunit re-associate that. */
else if ((gimple_assign_rhs_code (offset_def) == PLUS_EXPR
|| gimple_assign_rhs_code (offset_def) == MINUS_EXPR)
&& TREE_CODE (gimple_assign_rhs1 (offset_def)) == SSA_NAME
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
&& (tmp = div_if_zero_remainder (EXACT_DIV_EXPR,
gimple_assign_rhs2 (offset_def),
tunit)) != NULL_TREE)
{
gimple offset_def2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (offset_def));
if (gimple_assign_rhs_code (offset_def2) == MULT_EXPR
&& TREE_CODE (gimple_assign_rhs2 (offset_def2)) == INTEGER_CST
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def2), tunit))
{
index = fold_build2 (gimple_assign_rhs_code (offset_def),
TREE_TYPE (offset),
gimple_assign_rhs1 (offset_def2), tmp);
}
else
return false;
}
else
return false; return false;
/* The first operand to the MULT_EXPR is the desired index. */
index = offset;
} }
/* Replace the pointer addition with array indexing. */ /* Replace the pointer addition with array indexing. */
index = force_gimple_operand_gsi (use_stmt_gsi, index, true, NULL_TREE,
true, GSI_SAME_STMT);
gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs)); gimple_assign_set_rhs_from_tree (use_stmt_gsi, unshare_expr (def_rhs));
use_stmt = gsi_stmt (*use_stmt_gsi); use_stmt = gsi_stmt (*use_stmt_gsi);
TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1) TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
......
...@@ -4832,6 +4832,7 @@ extern tree build_fold_indirect_ref (tree); ...@@ -4832,6 +4832,7 @@ extern tree build_fold_indirect_ref (tree);
extern tree fold_indirect_ref (tree); extern tree fold_indirect_ref (tree);
extern tree constant_boolean_node (int, tree); extern tree constant_boolean_node (int, tree);
extern tree build_low_bits_mask (tree, unsigned); extern tree build_low_bits_mask (tree, unsigned);
extern tree div_if_zero_remainder (enum tree_code, const_tree, const_tree);
extern bool tree_swap_operands_p (const_tree, const_tree, bool); extern bool tree_swap_operands_p (const_tree, const_tree, bool);
extern enum tree_code swap_tree_comparison (enum tree_code); extern enum tree_code swap_tree_comparison (enum tree_code);
......
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