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