mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-25 12:06:05 +08:00
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
This commit is contained in:
parent
8f6121903f
commit
108f6c2f4e
@ -1,3 +1,11 @@
|
||||
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>
|
||||
|
||||
PR target/39592
|
||||
|
@ -874,7 +874,7 @@ div_and_round_double (enum tree_code code, int uns,
|
||||
of type CODE and returns the quotient.
|
||||
Otherwise returns NULL_TREE. */
|
||||
|
||||
static tree
|
||||
tree
|
||||
div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
|
||||
{
|
||||
unsigned HOST_WIDE_INT int1l, int2l;
|
||||
|
@ -1,3 +1,7 @@
|
||||
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>
|
||||
|
||||
PR target/39592
|
||||
|
22
gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c
Normal file
22
gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c
Normal file
@ -0,0 +1,22 @@
|
||||
/* { 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,
|
||||
tree def_rhs,
|
||||
gimple_stmt_iterator *use_stmt_gsi)
|
||||
{
|
||||
tree index;
|
||||
tree index, tunit;
|
||||
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. */
|
||||
offset_def = SSA_NAME_DEF_STMT (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
|
||||
allow multiplications because they can be computing index to a higher
|
||||
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)
|
||||
&& gimple_assign_rhs_code (offset_def) == MULT_EXPR)
|
||||
@ -648,18 +653,41 @@ forward_propagate_addr_into_variable_array_index (tree offset,
|
||||
multiplication of an object by the size of the array elements.
|
||||
This implicitly verifies that the size of the array elements
|
||||
is constant. */
|
||||
offset = gimple_assign_rhs1 (offset_def);
|
||||
if (gimple_assign_rhs_code (offset_def) != MULT_EXPR
|
||||
|| TREE_CODE (gimple_assign_rhs2 (offset_def)) != INTEGER_CST
|
||||
|| !simple_cst_equal (gimple_assign_rhs2 (offset_def),
|
||||
TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (def_rhs)))))
|
||||
if (gimple_assign_rhs_code (offset_def) == MULT_EXPR
|
||||
&& TREE_CODE (gimple_assign_rhs2 (offset_def)) == INTEGER_CST
|
||||
&& tree_int_cst_equal (gimple_assign_rhs2 (offset_def), tunit))
|
||||
{
|
||||
/* 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;
|
||||
|
||||
/* The first operand to the MULT_EXPR is the desired index. */
|
||||
index = offset;
|
||||
}
|
||||
|
||||
/* 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));
|
||||
use_stmt = gsi_stmt (*use_stmt_gsi);
|
||||
TREE_OPERAND (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0), 1)
|
||||
|
@ -4832,6 +4832,7 @@ extern tree build_fold_indirect_ref (tree);
|
||||
extern tree fold_indirect_ref (tree);
|
||||
extern tree constant_boolean_node (int, tree);
|
||||
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 enum tree_code swap_tree_comparison (enum tree_code);
|
||||
|
Loading…
Reference in New Issue
Block a user