This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[RFC][patch] improve scev for array element
- From: "Jiangning Liu" <jiangning dot liu at arm dot com>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 5 Jan 2012 17:51:12 +0800
- Subject: [RFC][patch] improve scev for array element
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 &a[i]. In the end the register pressure may be
reduced in the loop. The test case is simplified from a real benchmark, and
only want to show the GIMPLE level changes.
Any suggestions?
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)
+ {
+ 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)
{
Another bigger case may be like below, and register pressure could be
observed lower.
int a[512] ;
int b[512] ;
int *ax ;
int *bx ;
int *ay ;
int *by ;
int i ;
int j ;
int f(int k)
{
for( j = 0 ; j < k ; j++)
{
for( i = j ; i < 512 ; i += k)
{
ax = &a[i+k] ;
bx = &b[i+k] ;
ay = &a[i] ;
by = &b[i] ;
*ax >>= 7 ;
*bx >>= 7 ;
a[i] = 8;
b[i] = 8;
}
}
}
Thanks,
-Jiangning