public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Re: [PATCH] Improve SCEV for array element
       [not found] <4f1677c5.0630440a.1021.ffffb00eSMTPIN_ADDED@mx.google.com>
@ 2012-01-18 10:33 ` Richard Guenther
  2012-01-20  9:07   ` Jiangning Liu
                     ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Richard Guenther @ 2012-01-18 10:33 UTC (permalink / raw)
  To: Jiangning Liu; +Cc: gcc-patches

On Wed, Jan 18, 2012 at 8:41 AM, Jiangning Liu <jiangning.liu@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.liu@arm.com>
>
>        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
>        array reference.
>
> ChangeLog for testsuite:
>
> 2012-01-05  Jiangning Liu  <jiangning.liu@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

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Improve SCEV for array element
  2012-01-18 10:33 ` [PATCH] Improve SCEV for array element Richard Guenther
@ 2012-01-20  9:07   ` Jiangning Liu
  2012-02-13 10:15     ` Jiangning Liu
       [not found]   ` <4f38de06.0630440a.4838.5731SMTPIN_ADDED@mx.google.com>
       [not found]   ` <4f192ee1.c84b440a.3d24.ffffae31SMTPIN_ADDED@mx.google.com>
  2 siblings, 1 reply; 10+ messages in thread
From: Jiangning Liu @ 2012-01-20  9:07 UTC (permalink / raw)
  To: 'Richard Guenther'; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5177 bytes --]

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

OK. I may wait until next stage1.

> 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.

OK. New patch is like below, and bootstrapped on x86-32.

ChangeLog:

2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>

        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
        array reference and component reference.


ChangeLog for testsuite:

2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>

        * gcc.dg/tree-ssa/scev-3.c: New.
        * gcc.dg/tree-ssa/scev-4.c: New.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
new file mode 100644
index 0000000..28d5c93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
new file mode 100644
index 0000000..6c1e530
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef struct {
+	int x;
+	int y;
+} S;
+
+int *a_p;
+S a[1000];
+
+f(int k)
+{
+	int i;
+
+	for (i=k; i<1000; i+=k) {
+		a_p = &a[i].y;
+		*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..4e06b75
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1712,16 +1712,61 @@ interpret_rhs_expr (struct loop *loop, gimple
at_stmt,
   switch (code)
     {
     case ADDR_EXPR:
-      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
*/
-      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
-	{
-	  res = chrec_dont_know;
-	  break;
-	}
+      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
+        {
+	  enum machine_mode mode;
+	  HOST_WIDE_INT bitsize, bitpos;
+	  int unsignedp;
+	  int volatilep = 0;
+	  tree base, offset;
+	  tree chrec3;
+
+	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
+				      &bitsize, &bitpos, &offset,
+				      &mode, &unsignedp, &volatilep, false);
+
+	  if (TREE_CODE (base) == MEM_REF)
+	    {
+	      rhs2 = TREE_OPERAND (base, 1);
+	      rhs1 = TREE_OPERAND (base, 0);
+
+	      chrec1 = analyze_scalar_evolution (loop, rhs1);
+	      chrec2 = analyze_scalar_evolution (loop, rhs2);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, chrec1, chrec2);
+	    }
+	  else
+	    {
+	      base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
+	      chrec1 = analyze_scalar_evolution (loop, base);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      res = chrec1;
+	    }
 
-      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
-      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
-      /* Fall through.  */
+	  if (offset != NULL_TREE)
+	    {
+	      chrec2 = analyze_scalar_evolution (loop, offset);
+	      chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec2);
+	    }
+
+	  if (bitpos)
+	    {
+	      gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
+
+	      chrec3 = build_int_cst (integer_type_node,
+	      			      bitpos / BITS_PER_UNIT);
+	      chrec3 = analyze_scalar_evolution (loop, chrec3);
+	      chrec3 = chrec_convert (integer_type_node, chrec3, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec3);
+	    }
+        }
+      else
+	res = chrec_dont_know;
+      break;
 
     case POINTER_PLUS_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);

Thanks,
-Jiangning


[-- Attachment #2: scev-2.patch --]
[-- Type: application/octet-stream, Size: 3586 bytes --]

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
new file mode 100644
index 0000000..28d5c93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
new file mode 100644
index 0000000..6c1e530
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef struct {
+	int x;
+	int y;
+} S;
+
+int *a_p;
+S a[1000];
+
+f(int k)
+{
+	int i;
+
+	for (i=k; i<1000; i+=k) {
+		a_p = &a[i].y;
+		*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..4e06b75
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1712,16 +1712,61 @@ interpret_rhs_expr (struct loop *loop, gimple at_stmt,
   switch (code)
     {
     case ADDR_EXPR:
-      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.  */
-      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
-	{
-	  res = chrec_dont_know;
-	  break;
-	}
+      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
+        {
+	  enum machine_mode mode;
+	  HOST_WIDE_INT bitsize, bitpos;
+	  int unsignedp;
+	  int volatilep = 0;
+	  tree base, offset;
+	  tree chrec3;
+
+	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
+				      &bitsize, &bitpos, &offset,
+				      &mode, &unsignedp, &volatilep, false);
+
+	  if (TREE_CODE (base) == MEM_REF)
+	    {
+	      rhs2 = TREE_OPERAND (base, 1);
+	      rhs1 = TREE_OPERAND (base, 0);
+
+	      chrec1 = analyze_scalar_evolution (loop, rhs1);
+	      chrec2 = analyze_scalar_evolution (loop, rhs2);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, chrec1, chrec2);
+	    }
+	  else
+	    {
+	      base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
+	      chrec1 = analyze_scalar_evolution (loop, base);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      res = chrec1;
+	    }
 
-      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
-      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
-      /* Fall through.  */
+	  if (offset != NULL_TREE)
+	    {
+	      chrec2 = analyze_scalar_evolution (loop, offset);
+	      chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec2);
+	    }
+
+	  if (bitpos)
+	    {
+	      gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
+
+	      chrec3 = build_int_cst (integer_type_node,
+	      			      bitpos / BITS_PER_UNIT);
+	      chrec3 = analyze_scalar_evolution (loop, chrec3);
+	      chrec3 = chrec_convert (integer_type_node, chrec3, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec3);
+	    }
+        }
+      else
+	res = chrec_dont_know;
+      break;
 
     case POINTER_PLUS_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Improve SCEV for array element
  2012-01-20  9:07   ` Jiangning Liu
@ 2012-02-13 10:15     ` Jiangning Liu
  0 siblings, 0 replies; 10+ messages in thread
From: Jiangning Liu @ 2012-02-13 10:15 UTC (permalink / raw)
  To: Jiangning Liu, 'Richard Guenther'; +Cc: gcc-patches



> -----Original Message-----
> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
> owner@gcc.gnu.org] On Behalf Of Jiangning Liu
> Sent: Friday, January 20, 2012 5:07 PM
> To: 'Richard Guenther'
> Cc: gcc-patches@gcc.gnu.org
> Subject: RE: [PATCH] Improve SCEV for array element
> 
> > It's definitely not ok at this stage but at most for next stage1.
> 
> OK. I may wait until next stage1.
> 
> > 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.
> 
> OK. New patch is like below, and bootstrapped on x86-32.
> 
> ChangeLog:
> 
> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
> 
>         * tree-scalar-evolution (interpret_rhs_expr): generate chrec
> for
>         array reference and component reference.
> 
> 
> ChangeLog for testsuite:
> 
> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
> 
>         * gcc.dg/tree-ssa/scev-3.c: New.
>         * gcc.dg/tree-ssa/scev-4.c: New.
> 

Richard,

PING... Is this patch OK after branch 4.7 is created and trunk is open
again?

Thanks,
-Jiangning

> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> new file mode 100644
> index 0000000..28d5c93
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> new file mode 100644
> index 0000000..6c1e530
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +typedef struct {
> +	int x;
> +	int y;
> +} S;
> +
> +int *a_p;
> +S a[1000];
> +
> +f(int k)
> +{
> +	int i;
> +
> +	for (i=k; i<1000; i+=k) {
> +		a_p = &a[i].y;
> +		*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..4e06b75
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -1712,16 +1712,61 @@ interpret_rhs_expr (struct loop *loop, gimple
> at_stmt,
>    switch (code)
>      {
>      case ADDR_EXPR:
> -      /* Handle &MEM[ptr + CST] which is equivalent to
> POINTER_PLUS_EXPR.
> */
> -      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
> -	{
> -	  res = chrec_dont_know;
> -	  break;
> -	}
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
> +        {
> +	  enum machine_mode mode;
> +	  HOST_WIDE_INT bitsize, bitpos;
> +	  int unsignedp;
> +	  int volatilep = 0;
> +	  tree base, offset;
> +	  tree chrec3;
> +
> +	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
> +				      &bitsize, &bitpos, &offset,
> +				      &mode, &unsignedp, &volatilep, false);
> +
> +	  if (TREE_CODE (base) == MEM_REF)
> +	    {
> +	      rhs2 = TREE_OPERAND (base, 1);
> +	      rhs1 = TREE_OPERAND (base, 0);
> +
> +	      chrec1 = analyze_scalar_evolution (loop, rhs1);
> +	      chrec2 = analyze_scalar_evolution (loop, rhs2);
> +	      chrec1 = chrec_convert (type, chrec1, at_stmt);
> +	      chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
> +	      res = chrec_fold_plus (type, chrec1, chrec2);
> +	    }
> +	  else
> +	    {
> +	      base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
> +	      chrec1 = analyze_scalar_evolution (loop, base);
> +	      chrec1 = chrec_convert (type, chrec1, at_stmt);
> +	      res = chrec1;
> +	    }
> 
> -      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
> -      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
> -      /* Fall through.  */
> +	  if (offset != NULL_TREE)
> +	    {
> +	      chrec2 = analyze_scalar_evolution (loop, offset);
> +	      chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
> +	      res = chrec_fold_plus (type, res, chrec2);
> +	    }
> +
> +	  if (bitpos)
> +	    {
> +	      gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
> +
> +	      chrec3 = build_int_cst (integer_type_node,
> +	      			      bitpos / BITS_PER_UNIT);
> +	      chrec3 = analyze_scalar_evolution (loop, chrec3);
> +	      chrec3 = chrec_convert (integer_type_node, chrec3, at_stmt);
> +	      res = chrec_fold_plus (type, res, chrec3);
> +	    }
> +        }
> +      else
> +	res = chrec_dont_know;
> +      break;
> 
>      case POINTER_PLUS_EXPR:
>        chrec1 = analyze_scalar_evolution (loop, rhs1);
> 
> Thanks,
> -Jiangning



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Improve SCEV for array element
       [not found]   ` <4f38de06.0630440a.4838.5731SMTPIN_ADDED@mx.google.com>
@ 2012-02-13 11:30     ` Richard Guenther
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Guenther @ 2012-02-13 11:30 UTC (permalink / raw)
  To: Jiangning Liu; +Cc: gcc-patches

On Mon, Feb 13, 2012 at 10:54 AM, Jiangning Liu <jiangning.liu@arm.com> wrote:
>
>
>> -----Original Message-----
>> From: gcc-patches-owner@gcc.gnu.org [mailto:gcc-patches-
>> owner@gcc.gnu.org] On Behalf Of Jiangning Liu
>> Sent: Friday, January 20, 2012 5:07 PM
>> To: 'Richard Guenther'
>> Cc: gcc-patches@gcc.gnu.org
>> Subject: RE: [PATCH] Improve SCEV for array element
>>
>> > It's definitely not ok at this stage but at most for next stage1.
>>
>> OK. I may wait until next stage1.
>>
>> > 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.
>>
>> OK. New patch is like below, and bootstrapped on x86-32.
>>
>> ChangeLog:
>>
>> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
>>
>>         * tree-scalar-evolution (interpret_rhs_expr): generate chrec
>> for
>>         array reference and component reference.
>>
>>
>> ChangeLog for testsuite:
>>
>> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
>>
>>         * gcc.dg/tree-ssa/scev-3.c: New.
>>         * gcc.dg/tree-ssa/scev-4.c: New.
>>
>
> Richard,
>
> PING... Is this patch OK after branch 4.7 is created and trunk is open
> again?

It's on my (rather large) list of things to review for 4.8.  Be patient ...

Richard.

> Thanks,
> -Jiangning
>
>> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
>> b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
>> new file mode 100644
>> index 0000000..28d5c93
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
>> b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
>> new file mode 100644
>> index 0000000..6c1e530
>> --- /dev/null
>> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
>> @@ -0,0 +1,23 @@
>> +/* { dg-do compile } */
>> +/* { dg-options "-O2 -fdump-tree-optimized" } */
>> +
>> +typedef struct {
>> +     int x;
>> +     int y;
>> +} S;
>> +
>> +int *a_p;
>> +S a[1000];
>> +
>> +f(int k)
>> +{
>> +     int i;
>> +
>> +     for (i=k; i<1000; i+=k) {
>> +             a_p = &a[i].y;
>> +             *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..4e06b75
>> --- a/gcc/tree-scalar-evolution.c
>> +++ b/gcc/tree-scalar-evolution.c
>> @@ -1712,16 +1712,61 @@ interpret_rhs_expr (struct loop *loop, gimple
>> at_stmt,
>>    switch (code)
>>      {
>>      case ADDR_EXPR:
>> -      /* Handle &MEM[ptr + CST] which is equivalent to
>> POINTER_PLUS_EXPR.
>> */
>> -      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
>> -     {
>> -       res = chrec_dont_know;
>> -       break;
>> -     }
>> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
>> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
>> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
>> +        {
>> +       enum machine_mode mode;
>> +       HOST_WIDE_INT bitsize, bitpos;
>> +       int unsignedp;
>> +       int volatilep = 0;
>> +       tree base, offset;
>> +       tree chrec3;
>> +
>> +       base = get_inner_reference (TREE_OPERAND (rhs1, 0),
>> +                                   &bitsize, &bitpos, &offset,
>> +                                   &mode, &unsignedp, &volatilep, false);
>> +
>> +       if (TREE_CODE (base) == MEM_REF)
>> +         {
>> +           rhs2 = TREE_OPERAND (base, 1);
>> +           rhs1 = TREE_OPERAND (base, 0);
>> +
>> +           chrec1 = analyze_scalar_evolution (loop, rhs1);
>> +           chrec2 = analyze_scalar_evolution (loop, rhs2);
>> +           chrec1 = chrec_convert (type, chrec1, at_stmt);
>> +           chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
>> +           res = chrec_fold_plus (type, chrec1, chrec2);
>> +         }
>> +       else
>> +         {
>> +           base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
>> +           chrec1 = analyze_scalar_evolution (loop, base);
>> +           chrec1 = chrec_convert (type, chrec1, at_stmt);
>> +           res = chrec1;
>> +         }
>>
>> -      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
>> -      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
>> -      /* Fall through.  */
>> +       if (offset != NULL_TREE)
>> +         {
>> +           chrec2 = analyze_scalar_evolution (loop, offset);
>> +           chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
>> +           res = chrec_fold_plus (type, res, chrec2);
>> +         }
>> +
>> +       if (bitpos)
>> +         {
>> +           gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
>> +
>> +           chrec3 = build_int_cst (integer_type_node,
>> +                                   bitpos / BITS_PER_UNIT);
>> +           chrec3 = analyze_scalar_evolution (loop, chrec3);
>> +           chrec3 = chrec_convert (integer_type_node, chrec3, at_stmt);
>> +           res = chrec_fold_plus (type, res, chrec3);
>> +         }
>> +        }
>> +      else
>> +     res = chrec_dont_know;
>> +      break;
>>
>>      case POINTER_PLUS_EXPR:
>>        chrec1 = analyze_scalar_evolution (loop, rhs1);
>>
>> Thanks,
>> -Jiangning
>
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Improve SCEV for array element
       [not found]   ` <4f192ee1.c84b440a.3d24.ffffae31SMTPIN_ADDED@mx.google.com>
@ 2012-03-06 13:11     ` Richard Guenther
  2012-03-08  7:13       ` Jiangning Liu
                         ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Richard Guenther @ 2012-03-06 13:11 UTC (permalink / raw)
  To: Jiangning Liu; +Cc: gcc-patches

On Fri, Jan 20, 2012 at 10:06 AM, Jiangning Liu <jiangning.liu@arm.com> wrote:
>> It's definitely not ok at this stage but at most for next stage1.
>
> OK. I may wait until next stage1.
>
>> 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.
>
> OK. New patch is like below, and bootstrapped on x86-32.

You want instead of

+      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
+        {

if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
    || handled_component_p (TREE_OPERAND (rhs1, 0)))
  {

+             base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
+             chrec1 = analyze_scalar_evolution (loop, base);

can you please add a wrapper

tree
analyze_scalar_evolution_for_address_of (struct loop *loop, tree var)
{
  return analyze_scalar_evolution (loop, build_fold_addr_expr (var));
}

and call that instead of building the ADDR_EXPR there?  We want
to avoid building that tree node, but even such a simple wrapper would
be prefered.

+         if (bitpos)

if (bitpos != 0)

+             chrec3 = build_int_cst (integer_type_node,
+                                     bitpos / BITS_PER_UNIT);

please use size_int (bitpos / BITS_PER_UNIT) instead.  Using
integer_type_node is definitely wrong.

Ok with that changes.

Thanks,
Richard.


> ChangeLog:
>
> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
>
>        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
>        array reference and component reference.
>
>
> ChangeLog for testsuite:
>
> 2012-01-20  Jiangning Liu  <jiangning.liu@arm.com>
>
>        * gcc.dg/tree-ssa/scev-3.c: New.
>        * gcc.dg/tree-ssa/scev-4.c: New.
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> new file mode 100644
> index 0000000..28d5c93
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> new file mode 100644
> index 0000000..6c1e530
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +typedef struct {
> +       int x;
> +       int y;
> +} S;
> +
> +int *a_p;
> +S a[1000];
> +
> +f(int k)
> +{
> +       int i;
> +
> +       for (i=k; i<1000; i+=k) {
> +               a_p = &a[i].y;
> +               *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..4e06b75
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -1712,16 +1712,61 @@ interpret_rhs_expr (struct loop *loop, gimple
> at_stmt,
>   switch (code)
>     {
>     case ADDR_EXPR:
> -      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
> */
> -      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
> -       {
> -         res = chrec_dont_know;
> -         break;
> -       }
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
> +        {
> +         enum machine_mode mode;
> +         HOST_WIDE_INT bitsize, bitpos;
> +         int unsignedp;
> +         int volatilep = 0;
> +         tree base, offset;
> +         tree chrec3;
> +
> +         base = get_inner_reference (TREE_OPERAND (rhs1, 0),
> +                                     &bitsize, &bitpos, &offset,
> +                                     &mode, &unsignedp, &volatilep, false);
> +
> +         if (TREE_CODE (base) == MEM_REF)
> +           {
> +             rhs2 = TREE_OPERAND (base, 1);
> +             rhs1 = TREE_OPERAND (base, 0);
> +
> +             chrec1 = analyze_scalar_evolution (loop, rhs1);
> +             chrec2 = analyze_scalar_evolution (loop, rhs2);
> +             chrec1 = chrec_convert (type, chrec1, at_stmt);
> +             chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
> +             res = chrec_fold_plus (type, chrec1, chrec2);
> +           }
> +         else
> +           {
> +             base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
> +             chrec1 = analyze_scalar_evolution (loop, base);
> +             chrec1 = chrec_convert (type, chrec1, at_stmt);
> +             res = chrec1;
> +           }
>
> -      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
> -      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
> -      /* Fall through.  */
> +         if (offset != NULL_TREE)
> +           {
> +             chrec2 = analyze_scalar_evolution (loop, offset);
> +             chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
> +             res = chrec_fold_plus (type, res, chrec2);
> +           }
> +
> +         if (bitpos)
> +           {
> +             gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
> +
> +             chrec3 = build_int_cst (integer_type_node,
> +                                     bitpos / BITS_PER_UNIT);
> +             chrec3 = analyze_scalar_evolution (loop, chrec3);
> +             chrec3 = chrec_convert (integer_type_node, chrec3, at_stmt);
> +             res = chrec_fold_plus (type, res, chrec3);
> +           }
> +        }
> +      else
> +       res = chrec_dont_know;
> +      break;
>
>     case POINTER_PLUS_EXPR:
>       chrec1 = analyze_scalar_evolution (loop, rhs1);
>
> Thanks,
> -Jiangning
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: [PATCH] Improve SCEV for array element
  2012-03-06 13:11     ` Richard Guenther
@ 2012-03-08  7:13       ` Jiangning Liu
       [not found]       ` <4f585bf3.1eecd80a.3185.ffffe392SMTPIN_ADDED@mx.google.com>
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 10+ messages in thread
From: Jiangning Liu @ 2012-03-08  7:13 UTC (permalink / raw)
  To: 'Richard Guenther'; +Cc: gcc-patches



> -----Original Message-----
> From: Richard Guenther [mailto:richard.guenther@gmail.com]
> Sent: Tuesday, March 06, 2012 9:12 PM
> To: Jiangning Liu
> Cc: gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH] Improve SCEV for array element
> 
> On Fri, Jan 20, 2012 at 10:06 AM, Jiangning Liu <jiangning.liu@arm.com>
> wrote:
> >> It's definitely not ok at this stage but at most for next stage1.
> >
> > OK. I may wait until next stage1.
> >
> >> 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.
> >
> > OK. New patch is like below, and bootstrapped on x86-32.
> 
> You want instead of
> 
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
> +        {
> 
> if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
>     || handled_component_p (TREE_OPERAND (rhs1, 0)))
>   {
> 
> +             base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
> +             chrec1 = analyze_scalar_evolution (loop, base);
> 
> can you please add a wrapper
> 
> tree
> analyze_scalar_evolution_for_address_of (struct loop *loop, tree var)
> {
>   return analyze_scalar_evolution (loop, build_fold_addr_expr (var));
> }
> 
> and call that instead of building the ADDR_EXPR there?  We want
> to avoid building that tree node, but even such a simple wrapper would
> be prefered.
> 
> +         if (bitpos)
> 
> if (bitpos != 0)
> 
> +             chrec3 = build_int_cst (integer_type_node,
> +                                     bitpos / BITS_PER_UNIT);
> 
> please use size_int (bitpos / BITS_PER_UNIT) instead.  Using
> integer_type_node is definitely wrong.
> 
> Ok with that changes.
> 

Richard,

Modified as all you suggested, and new code is like below. Bootstrapped on
x86-32. OK for trunk now?

Thanks,
-Jiangning

ChangeLog:

2012-03-08  Jiangning Liu  <jiangning.liu@arm.com>

	* tree-scalar-evolution (interpret_rhs_expr): generate chrec for
	array reference and component reference.
	(analyze_scalar_evolution_for_address_of): New.

ChangeLog for testsuite:

2012-03-08  Jiangning Liu  <jiangning.liu@arm.com>

	* gcc.dg/tree-ssa/scev-3.c: New.
	* gcc.dg/tree-ssa/scev-4.c: New.

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
new file mode 100644
index 0000000..28d5c93
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
new file mode 100644
index 0000000..6c1e530
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+typedef struct {
+	int x;
+	int y;
+} S;
+
+int *a_p;
+S a[1000];
+
+f(int k)
+{
+	int i;
+
+	for (i=k; i<1000; i+=k) {
+		a_p = &a[i].y;
+		*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..c719984
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -266,6 +266,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 
 static tree analyze_scalar_evolution_1 (struct loop *, tree, tree);
+static tree analyze_scalar_evolution_for_address_of (struct loop *loop,
+						     tree var);
 
 /* The cached information about an SSA name VAR, claiming that below
    basic block INSTANTIATED_BELOW, the value of VAR can be expressed
@@ -1712,16 +1714,59 @@ interpret_rhs_expr (struct loop *loop, gimple
at_stmt,
   switch (code)
     {
     case ADDR_EXPR:
-      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
*/
-      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
-	{
-	  res = chrec_dont_know;
-	  break;
-	}
+      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
+	  || handled_component_p (TREE_OPERAND (rhs1, 0)))
+        {
+	  enum machine_mode mode;
+	  HOST_WIDE_INT bitsize, bitpos;
+	  int unsignedp;
+	  int volatilep = 0;
+	  tree base, offset;
+	  tree chrec3;
+	  tree unitpos;
+
+	  base = get_inner_reference (TREE_OPERAND (rhs1, 0),
+				      &bitsize, &bitpos, &offset,
+				      &mode, &unsignedp, &volatilep, false);
+
+	  if (TREE_CODE (base) == MEM_REF)
+	    {
+	      rhs2 = TREE_OPERAND (base, 1);
+	      rhs1 = TREE_OPERAND (base, 0);
+
+	      chrec1 = analyze_scalar_evolution (loop, rhs1);
+	      chrec2 = analyze_scalar_evolution (loop, rhs2);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, chrec1, chrec2);
+	    }
+	  else
+	    {
+	      chrec1 = analyze_scalar_evolution_for_address_of (loop, base);
+	      chrec1 = chrec_convert (type, chrec1, at_stmt);
+	      res = chrec1;
+	    }
+
+	  if (offset != NULL_TREE)
+	    {
+	      chrec2 = analyze_scalar_evolution (loop, offset);
+	      chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec2);
+	    }
+
+	  if (bitpos != 0)
+	    {
+	      gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
 
-      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
-      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
-      /* Fall through.  */
+	      unitpos = size_int_kind (bitpos / BITS_PER_UNIT, SIZETYPE);
+	      chrec3 = analyze_scalar_evolution (loop, unitpos);
+	      chrec3 = chrec_convert (TREE_TYPE (unitpos), chrec3, at_stmt);
+	      res = chrec_fold_plus (type, res, chrec3);
+	    }
+        }
+      else
+	res = chrec_dont_know;
+      break;
 
     case POINTER_PLUS_EXPR:
       chrec1 = analyze_scalar_evolution (loop, rhs1);
@@ -1961,6 +2006,14 @@ analyze_scalar_evolution (struct loop *loop, tree
var)
   return res;
 }
 
+/* Analyzes and returns the scalar evolution of VAR address in LOOP.  */
+
+static tree
+analyze_scalar_evolution_for_address_of (struct loop *loop, tree var)
+{
+  return analyze_scalar_evolution (loop, build_fold_addr_expr (var));
+}
+
 /* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to
    WRTO_LOOP (which should be a superloop of USE_LOOP)



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Improve SCEV for array element
       [not found]       ` <4f585bf3.1eecd80a.3185.ffffe392SMTPIN_ADDED@mx.google.com>
@ 2012-03-12 10:42         ` Richard Guenther
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Guenther @ 2012-03-12 10:42 UTC (permalink / raw)
  To: Jiangning Liu; +Cc: gcc-patches

On Thu, Mar 8, 2012 at 8:13 AM, Jiangning Liu <jiangning.liu@arm.com> wrote:
>
>
>> -----Original Message-----
>> From: Richard Guenther [mailto:richard.guenther@gmail.com]
>> Sent: Tuesday, March 06, 2012 9:12 PM
>> To: Jiangning Liu
>> Cc: gcc-patches@gcc.gnu.org
>> Subject: Re: [PATCH] Improve SCEV for array element
>>
>> On Fri, Jan 20, 2012 at 10:06 AM, Jiangning Liu <jiangning.liu@arm.com>
>> wrote:
>> >> It's definitely not ok at this stage but at most for next stage1.
>> >
>> > OK. I may wait until next stage1.
>> >
>> >> 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.
>> >
>> > OK. New patch is like below, and bootstrapped on x86-32.
>>
>> You want instead of
>>
>> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == ARRAY_REF
>> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
>> +          || TREE_CODE (TREE_OPERAND (rhs1, 0)) == COMPONENT_REF)
>> +        {
>>
>> if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
>>     || handled_component_p (TREE_OPERAND (rhs1, 0)))
>>   {
>>
>> +             base = build1 (ADDR_EXPR, TREE_TYPE (rhs1), base);
>> +             chrec1 = analyze_scalar_evolution (loop, base);
>>
>> can you please add a wrapper
>>
>> tree
>> analyze_scalar_evolution_for_address_of (struct loop *loop, tree var)
>> {
>>   return analyze_scalar_evolution (loop, build_fold_addr_expr (var));
>> }
>>
>> and call that instead of building the ADDR_EXPR there?  We want
>> to avoid building that tree node, but even such a simple wrapper would
>> be prefered.
>>
>> +         if (bitpos)
>>
>> if (bitpos != 0)
>>
>> +             chrec3 = build_int_cst (integer_type_node,
>> +                                     bitpos / BITS_PER_UNIT);
>>
>> please use size_int (bitpos / BITS_PER_UNIT) instead.  Using
>> integer_type_node is definitely wrong.
>>
>> Ok with that changes.
>>
>
> Richard,
>
> Modified as all you suggested, and new code is like below. Bootstrapped on
> x86-32. OK for trunk now?

Ok.

Thanks,
Richard.

> Thanks,
> -Jiangning
>
> ChangeLog:
>
> 2012-03-08  Jiangning Liu  <jiangning.liu@arm.com>
>
>        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
>        array reference and component reference.
>        (analyze_scalar_evolution_for_address_of): New.
>
> ChangeLog for testsuite:
>
> 2012-03-08  Jiangning Liu  <jiangning.liu@arm.com>
>
>        * gcc.dg/tree-ssa/scev-3.c: New.
>        * gcc.dg/tree-ssa/scev-4.c: New.
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> new file mode 100644
> index 0000000..28d5c93
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.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/testsuite/gcc.dg/tree-ssa/scev-4.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> new file mode 100644
> index 0000000..6c1e530
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> @@ -0,0 +1,23 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +typedef struct {
> +       int x;
> +       int y;
> +} S;
> +
> +int *a_p;
> +S a[1000];
> +
> +f(int k)
> +{
> +       int i;
> +
> +       for (i=k; i<1000; i+=k) {
> +               a_p = &a[i].y;
> +               *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..c719984
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -266,6 +266,8 @@ along with GCC; see the file COPYING3.  If not see
>  #include "params.h"
>
>  static tree analyze_scalar_evolution_1 (struct loop *, tree, tree);
> +static tree analyze_scalar_evolution_for_address_of (struct loop *loop,
> +                                                    tree var);
>
>  /* The cached information about an SSA name VAR, claiming that below
>    basic block INSTANTIATED_BELOW, the value of VAR can be expressed
> @@ -1712,16 +1714,59 @@ interpret_rhs_expr (struct loop *loop, gimple
> at_stmt,
>   switch (code)
>     {
>     case ADDR_EXPR:
> -      /* Handle &MEM[ptr + CST] which is equivalent to POINTER_PLUS_EXPR.
> */
> -      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != MEM_REF)
> -       {
> -         res = chrec_dont_know;
> -         break;
> -       }
> +      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == MEM_REF
> +         || handled_component_p (TREE_OPERAND (rhs1, 0)))
> +        {
> +         enum machine_mode mode;
> +         HOST_WIDE_INT bitsize, bitpos;
> +         int unsignedp;
> +         int volatilep = 0;
> +         tree base, offset;
> +         tree chrec3;
> +         tree unitpos;
> +
> +         base = get_inner_reference (TREE_OPERAND (rhs1, 0),
> +                                     &bitsize, &bitpos, &offset,
> +                                     &mode, &unsignedp, &volatilep, false);
> +
> +         if (TREE_CODE (base) == MEM_REF)
> +           {
> +             rhs2 = TREE_OPERAND (base, 1);
> +             rhs1 = TREE_OPERAND (base, 0);
> +
> +             chrec1 = analyze_scalar_evolution (loop, rhs1);
> +             chrec2 = analyze_scalar_evolution (loop, rhs2);
> +             chrec1 = chrec_convert (type, chrec1, at_stmt);
> +             chrec2 = chrec_convert (TREE_TYPE (rhs2), chrec2, at_stmt);
> +             res = chrec_fold_plus (type, chrec1, chrec2);
> +           }
> +         else
> +           {
> +             chrec1 = analyze_scalar_evolution_for_address_of (loop, base);
> +             chrec1 = chrec_convert (type, chrec1, at_stmt);
> +             res = chrec1;
> +           }
> +
> +         if (offset != NULL_TREE)
> +           {
> +             chrec2 = analyze_scalar_evolution (loop, offset);
> +             chrec2 = chrec_convert (TREE_TYPE (offset), chrec2, at_stmt);
> +             res = chrec_fold_plus (type, res, chrec2);
> +           }
> +
> +         if (bitpos != 0)
> +           {
> +             gcc_assert ((bitpos % BITS_PER_UNIT) == 0);
>
> -      rhs2 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1);
> -      rhs1 = TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0);
> -      /* Fall through.  */
> +             unitpos = size_int_kind (bitpos / BITS_PER_UNIT, SIZETYPE);
> +             chrec3 = analyze_scalar_evolution (loop, unitpos);
> +             chrec3 = chrec_convert (TREE_TYPE (unitpos), chrec3, at_stmt);
> +             res = chrec_fold_plus (type, res, chrec3);
> +           }
> +        }
> +      else
> +       res = chrec_dont_know;
> +      break;
>
>     case POINTER_PLUS_EXPR:
>       chrec1 = analyze_scalar_evolution (loop, rhs1);
> @@ -1961,6 +2006,14 @@ analyze_scalar_evolution (struct loop *loop, tree
> var)
>   return res;
>  }
>
> +/* Analyzes and returns the scalar evolution of VAR address in LOOP.  */
> +
> +static tree
> +analyze_scalar_evolution_for_address_of (struct loop *loop, tree var)
> +{
> +  return analyze_scalar_evolution (loop, build_fold_addr_expr (var));
> +}
> +
>  /* Analyze scalar evolution of use of VERSION in USE_LOOP with respect to
>    WRTO_LOOP (which should be a superloop of USE_LOOP)
>
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH][Testsuite] XFAIL scev-3/4.c and add scev-5.c
  2012-03-06 13:11     ` Richard Guenther
  2012-03-08  7:13       ` Jiangning Liu
       [not found]       ` <4f585bf3.1eecd80a.3185.ffffe392SMTPIN_ADDED@mx.google.com>
@ 2012-03-22  2:19       ` Jiangning Liu
       [not found]       ` <4f6a8c26.45abb60a.1dd0.01b7SMTPIN_ADDED@mx.google.com>
  3 siblings, 0 replies; 10+ messages in thread
From: Jiangning Liu @ 2012-03-22  2:19 UTC (permalink / raw)
  To: gcc-patches

Hi,

This patch is to XFAIL scev-3.c and scev-5.c. 

The bug is going to be fixed after Richard Guenther fix a serials of
problems related to POINTER_PLUS_EXPR and sizetype precision.

Thanks,
-Jiangning 

ChangeLog for testsuite:

2012-03-21  Jiangning Liu  <jiangning.liu@arm.com>

	PR tree-optimization/52563
	* gcc.dg/tree-ssa/scev-3.c: XFAIL on lp64.
	* gcc.dg/tree-ssa/scev-4.c: XFAIL on lp64.
	* gcc.dg/tree-ssa/scev-5.c: New.

Thanks,
-Jiangning

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
index 28d5c93..ed63a18 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
@@ -14,5 +14,5 @@ f(int k)
         }
 }
 
-/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" { xfail lp64 } 
+} } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git
a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
index 6c1e530..a538c32 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
@@ -19,5 +19,5 @@ f(int k)
         }
 }
 
-/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" { xfail lp64 } 
+} } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git
a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
new file mode 100644
index 0000000..b9de36a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int *a_p;
+int a[1000];
+
+f(int k)
+{
+        long long 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" } } */



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH][Testsuite] XFAIL scev-3/4.c and add scev-5.c
       [not found]       ` <4f6a8c26.45abb60a.1dd0.01b7SMTPIN_ADDED@mx.google.com>
@ 2012-03-22  7:16         ` Richard Guenther
  0 siblings, 0 replies; 10+ messages in thread
From: Richard Guenther @ 2012-03-22  7:16 UTC (permalink / raw)
  To: Jiangning Liu; +Cc: gcc-patches

On Thu, Mar 22, 2012 at 3:19 AM, Jiangning Liu <jiangning.liu@arm.com> wrote:
> Hi,
>
> This patch is to XFAIL scev-3.c and scev-5.c.
>
> The bug is going to be fixed after Richard Guenther fix a serials of
> problems related to POINTER_PLUS_EXPR and sizetype precision.

Ok.

Thanks,
Richard.

> Thanks,
> -Jiangning
>
> ChangeLog for testsuite:
>
> 2012-03-21  Jiangning Liu  <jiangning.liu@arm.com>
>
>        PR tree-optimization/52563
>        * gcc.dg/tree-ssa/scev-3.c: XFAIL on lp64.
>        * gcc.dg/tree-ssa/scev-4.c: XFAIL on lp64.
>        * gcc.dg/tree-ssa/scev-5.c: New.
>
> Thanks,
> -Jiangning
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> index 28d5c93..ed63a18 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-3.c
> @@ -14,5 +14,5 @@ f(int k)
>         }
>  }
>
> -/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" { xfail lp64 }
> +} } */
>  /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git
> a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> index 6c1e530..a538c32 100644
> --- a/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-4.c
> @@ -19,5 +19,5 @@ f(int k)
>         }
>  }
>
> -/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" } } */
> +/* { dg-final { scan-tree-dump-times "&a" 1 "optimized" { xfail lp64 }
> +} } */
>  /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git
> a/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
> b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
> new file mode 100644
> index 0000000..b9de36a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-5.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +
> +int *a_p;
> +int a[1000];
> +
> +f(int k)
> +{
> +        long long 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" } } */
>
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH] Improve SCEV for array element
@ 2012-01-18  7:41 Jiangning Liu
  0 siblings, 0 replies; 10+ messages in thread
From: Jiangning Liu @ 2012-01-18  7:41 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2967 bytes --]

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?

ChangeLog:

2012-01-05  Jiangning Liu  <jiangning.liu@arm.com>

        * tree-scalar-evolution (interpret_rhs_expr): generate chrec for
        array reference.

ChangeLog for testsuite:

2012-01-05  Jiangning Liu  <jiangning.liu@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)
+        {
+	  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

[-- Attachment #2: scev.patch --]
[-- Type: application/octet-stream, Size: 2175 bytes --]

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)
 	{

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2012-03-22  7:16 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <4f1677c5.0630440a.1021.ffffb00eSMTPIN_ADDED@mx.google.com>
2012-01-18 10:33 ` [PATCH] Improve SCEV for array element Richard Guenther
2012-01-20  9:07   ` Jiangning Liu
2012-02-13 10:15     ` Jiangning Liu
     [not found]   ` <4f38de06.0630440a.4838.5731SMTPIN_ADDED@mx.google.com>
2012-02-13 11:30     ` Richard Guenther
     [not found]   ` <4f192ee1.c84b440a.3d24.ffffae31SMTPIN_ADDED@mx.google.com>
2012-03-06 13:11     ` Richard Guenther
2012-03-08  7:13       ` Jiangning Liu
     [not found]       ` <4f585bf3.1eecd80a.3185.ffffe392SMTPIN_ADDED@mx.google.com>
2012-03-12 10:42         ` Richard Guenther
2012-03-22  2:19       ` [PATCH][Testsuite] XFAIL scev-3/4.c and add scev-5.c Jiangning Liu
     [not found]       ` <4f6a8c26.45abb60a.1dd0.01b7SMTPIN_ADDED@mx.google.com>
2012-03-22  7:16         ` Richard Guenther
2012-01-18  7:41 [PATCH] Improve SCEV for array element Jiangning Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).