On Wed, Jan 18, 2012 at 8:41 AM, Jiangning Liu <jiangning....@arm.com> wrote:
> This code change intends to improve scev for array element and reduce the
> common sub-expressions in loop, which may be introduced by multiple
> reference of expression like &a[i]. With this optimization the register
> pressure can be reduced in loops.
>
> The problem is originally from a real benchmark, and the test case only
> tries to detect the GIMPLE level changes.
>
> Bootstraped on x86-32. OK for trunk?

It's definitely not ok at this stage but at most for next stage1.  But ...

> ChangeLog:
>
> 2012-01-05  Jiangning Liu  <jiangning....@arm.com>
>
>        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
>        array reference.
>
> ChangeLog for testsuite:
>
> 2012-01-05  Jiangning Liu  <jiangning....@arm.com>
>
>        * gcc.dg/scev-1.c: New.
>
> diff --git a/gcc/testsuite/gcc.dg/scev-1.c b/gcc/testsuite/gcc.dg/scev-1.c
> new file mode 100644 index 0000000..28d5c93
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/scev-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +int *a_p;
> +int a[1000];
> +
> +f(int k)
> +{
> +       int i;
> +
> +       for (i=k; i<1000; i+=k) {
> +               a_p = &a[i];
> +               *a_p = 100;
> +        }
> +}
> +
> +/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" } } */
> +/* { dg-final { cleanup-tree-dump "optimized" } } */
> diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index
> 2077c8d..de89fc4
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -1712,6 +1712,42 @@ interpret_rhs_expr (struct loop *loop, gimple
> at_stmt,
>   switch (code)
>     {
>     case ADDR_EXPR:
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF)

This is a very narrow pattern-match.  It doesn't allow for &a[i].x for example,
even if a[i] is a one-element structure.  I think the canonical way of handling
ADDR_EXPR is to use sth like

base = get_inner_reference (TREE_OPERAND (rhs1, 0), ..., &offset,  ...);
base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
        chrec1 = analyze_scalar_evolution (loop, base);
        chrec2 = analyze_scalar_evolution (loop, offset);
        chrec1 = chrec_convert (type, chrec1, at_stmt);
        chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
        res = chrec_fold_plus (type, chrec1, chrec2);

where you probably need to handle scev_not_known when analyzing offset
(which might be NULL).  You also need to add bitpos to the base address
(in bytes, of course).  Note that the &MEM_REF case would naturally work
with this as well.

Richard.

> +        {
> +         tree array_ref;
> +         tree var_decl, base, offset;
> +         tree low_bound;
> +         tree unit_size;
> +         tree index;
> +
> +         array_ref = TREE_OPERAND (rhs1, 0);
> +         var_decl = TREE_OPERAND (array_ref, 0);
> +         index = TREE_OPERAND (array_ref, 1);
> +
> +         low_bound = array_ref_low_bound (array_ref);
> +         unit_size = array_ref_element_size (array_ref);
> +
> +         /* We assume all arrays have sizes that are a multiple of a byte.
> +            First subtract the lower bound, if any, in the type of the
> +            index, then convert to sizetype and multiply by the size of
> +            the array element.  */
> +         if (! integer_zerop (low_bound))
> +           index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
> +                                index, low_bound);
> +
> +         offset = size_binop (MULT_EXPR,
> +                              fold_convert (sizetype, index),
> +                              unit_size);
> +
> +         base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), var_decl);
> +         chrec1 = analyze_scalar_evolution (loop, base);
> +         chrec2 = analyze_scalar_evolution (loop, offset);
> +          chrec1 = chrec_convert (type, chrec1, at_stmt);
> +          chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
> +         res = chrec_fold_plus (type, chrec1, chrec2);
> +         break;
> +        }
> +
>       /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
> */
>       if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
>        {
>
> Thanks,
> -Jiangning

Reply via email to