This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Use div_and_round_double in try_move_mult_to_array_index
- From: Richard Guenther <rguenth at tat dot physik dot uni-tuebingen dot de>
- To: Richard Henderson <rth at redhat dot com>
- Cc: Roger Sayle <roger at eyesopen dot com>, <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 13 May 2005 14:45:31 +0200 (CEST)
- Subject: Re: [PATCH] Use div_and_round_double in try_move_mult_to_array_index
On Wed, 11 May 2005, Richard Henderson wrote:
> On Wed, May 11, 2005 at 08:18:22PM -0600, Roger Sayle wrote:
> > My preference for a slightly cleaner API, would be change the new
> > div_if_zero_remainder function to return a tree, and then use a
> > value of NULL_TREE to indicate a non-zero remainder.
>
> Seconded.
Like this one. Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline?
Thanks,
Richard.
2005-05-13 Richard Guenther <rguenth@gcc.gnu.org>
* fold-const.c (div_if_zero_remainder): New function.
(try_move_mult_to_index): Use it.
* g++.dg/tree-ssa/tmmti-2.C: New testcase.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.578
diff -c -3 -p -r1.578 fold-const.c
*** fold-const.c 11 May 2005 15:21:23 -0000 1.578
--- fold-const.c 13 May 2005 11:09:49 -0000
*************** div_and_round_double (enum tree_code cod
*** 831,836 ****
--- 831,863 ----
add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
return overflow;
}
+
+ /* If ARG2 divides ARG1 with zero remainder, carries out the division
+ of type CODE and returns the quotient.
+ Otherwise returns NULL_TREE. */
+
+ static tree
+ div_if_zero_remainder (enum tree_code code, tree arg1, tree arg2)
+ {
+ unsigned HOST_WIDE_INT int1l, int2l;
+ HOST_WIDE_INT int1h, int2h;
+ unsigned HOST_WIDE_INT quol, reml;
+ HOST_WIDE_INT quoh, remh;
+ tree type = TREE_TYPE (arg1);
+ int uns = TYPE_UNSIGNED (type);
+
+ int1l = TREE_INT_CST_LOW (arg1);
+ int1h = TREE_INT_CST_HIGH (arg1);
+ int2l = TREE_INT_CST_LOW (arg2);
+ int2h = TREE_INT_CST_HIGH (arg2);
+
+ div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
+ &quol, &quoh, &reml, &remh);
+ if (remh != 0 || reml != 0)
+ return NULL_TREE;
+
+ return build_int_cst_wide (type, quol, quoh);
+ }
/* Return true if built-in mathematical function specified by CODE
preserves the sign of it argument, i.e. -f(x) == f(-x). */
*************** try_move_mult_to_index (enum tree_code c
*** 6311,6316 ****
--- 6338,6347 ----
{
if (TREE_CODE (ref) == ARRAY_REF)
{
+ itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+ if (! itype)
+ continue;
+
step = array_ref_element_size (ref);
if (TREE_CODE (step) != INTEGER_CST)
continue;
*************** try_move_mult_to_index (enum tree_code c
*** 6323,6339 ****
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;
!
! delta = int_const_binop (EXACT_DIV_EXPR, delta, step, 0);
}
- itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
- if (! itype)
- continue;
-
break;
}
--- 6354,6365 ----
else
{
/* Try if delta is a multiple of step. */
! tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, delta, step);
! if (! tmp)
continue;
! delta = tmp;
}
break;
}
/* { dg-do compile } */
/* { dg-options { -O -fdump-tree-optimized } } */
int a[4][8];
int foo(int i)
{
return *(&a[0][0] + i*8); // a[i][0]
}
struct Foo { double x, y; };
Foo b[4];
double bar(int i)
{
return *(&b[0].x + i*2); // b[i].x
}
/* { dg-final { scan-tree-dump "a\\\[.*i.*\\\]\\\[0\\\]" "optimized" } } */
/* { dg-final { scan-tree-dump "b\\\[.*i.*\\\].x" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */