diff mbox

Optional alternative base_expr in finding basis for CAND_REFs

Message ID 52840A69.1020308@arm.com
State New
Headers show

Commit Message

Yufeng Zhang Nov. 13, 2013, 11:25 p.m. UTC
Hi Bill,

On 11/13/13 20:54, Bill Schmidt wrote:
> Hi Yufeng,
>
> The second version of your original patch is ok with me with the
> following changes.  Sorry for the little side adventure into the
> next-interp logic; in the end that's going to hurt more than it helps in
> this case.  Thanks for having a look at it, anyway.  Thanks also for
> cleaning up this version to be less intrusive to common interfaces; I
> appreciate it.

Thanks a lot for the review.  I've attached an updated patch with the 
suggested changes incorporated.

For the next-interp adventure, I was quite happy to do the experiment; 
it's a good chance of gaining insight into the pass.  Many thanks for 
your prompt replies and patience in guiding!

> Everything else looks OK to me.  Please ask Richard for final approval,
> as I'm not a maintainer.

Hi Richard, would you be happy to OK the patch?

Regards,
Yufeng

gcc/

	* gimple-ssa-strength-reduction.c: Include tree-affine.h.
	(name_expansions): New static variable.
	(alt_base_map): Ditto.
	(get_alternative_base): New function.
	(find_basis_for_candidate): For CAND_REF, optionally call
	find_basis_for_base_expr with the returned value from
	get_alternative_base.
	(record_potential_basis): Add new parameter 'base' of type 'tree';
	add an assertion of non-NULL base; use base to set node->base_expr.
	(alloc_cand_and_find_basis): Update; call record_potential_basis
	for CAND_REF with the returned value from get_alternative_base.
	(execute_strength_reduction): Call pointer_map_create for
	alt_base_map; call free_affine_expand_cache with &name_expansions.

gcc/testsuite/

	* gcc.dg/tree-ssa/slsr-41.c: New test.

Comments

Yufeng Zhang Nov. 19, 2013, 11:45 a.m. UTC | #1
Hi Richard,

Can I get an approval or some feedback from you about the patch?

Regards,
Yufeng

On 11/13/13 23:25, Yufeng Zhang wrote:
> On 11/13/13 20:54, Bill Schmidt wrote:
>> Hi Yufeng,
>>
>> The second version of your original patch is ok with me with the
>> following changes.
>
> Thanks a lot for the review.  I've attached an updated patch with the
> suggested changes incorporated.
>
>> Everything else looks OK to me.  Please ask Richard for final approval,
>> as I'm not a maintainer.
>
> Hi Richard, would you be happy to OK the patch?
>
> Regards,
> Yufeng
>
> gcc/
>
> 	* gimple-ssa-strength-reduction.c: Include tree-affine.h.
> 	(name_expansions): New static variable.
> 	(alt_base_map): Ditto.
> 	(get_alternative_base): New function.
> 	(find_basis_for_candidate): For CAND_REF, optionally call
> 	find_basis_for_base_expr with the returned value from
> 	get_alternative_base.
> 	(record_potential_basis): Add new parameter 'base' of type 'tree';
> 	add an assertion of non-NULL base; use base to set node->base_expr.
> 	(alloc_cand_and_find_basis): Update; call record_potential_basis
> 	for CAND_REF with the returned value from get_alternative_base.
> 	(execute_strength_reduction): Call pointer_map_create for
> 	alt_base_map; call free_affine_expand_cache with&name_expansions.
>
> gcc/testsuite/
>
> 	* gcc.dg/tree-ssa/slsr-41.c: New test.
Yufeng Zhang Nov. 26, 2013, 12:03 p.m. UTC | #2
Ping^2

The patch was posted here:

http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01523.html

Thanks,
Yufeng

On 11/19/13 11:45, Yufeng Zhang wrote:
> Hi Richard,
>
> Can I get an approval or some feedback from you about the patch?
>
> Regards,
> Yufeng
>
> On 11/13/13 23:25, Yufeng Zhang wrote:
>> On 11/13/13 20:54, Bill Schmidt wrote:
>>> Hi Yufeng,
>>>
>>> The second version of your original patch is ok with me with the
>>> following changes.
>>
>> Thanks a lot for the review.  I've attached an updated patch with the
>> suggested changes incorporated.
>>
>>> Everything else looks OK to me.  Please ask Richard for final approval,
>>> as I'm not a maintainer.
>>
>> Hi Richard, would you be happy to OK the patch?
>>
>> Regards,
>> Yufeng
>>
>> gcc/
>>
>> 	* gimple-ssa-strength-reduction.c: Include tree-affine.h.
>> 	(name_expansions): New static variable.
>> 	(alt_base_map): Ditto.
>> 	(get_alternative_base): New function.
>> 	(find_basis_for_candidate): For CAND_REF, optionally call
>> 	find_basis_for_base_expr with the returned value from
>> 	get_alternative_base.
>> 	(record_potential_basis): Add new parameter 'base' of type 'tree';
>> 	add an assertion of non-NULL base; use base to set node->base_expr.
>> 	(alloc_cand_and_find_basis): Update; call record_potential_basis
>> 	for CAND_REF with the returned value from get_alternative_base.
>> 	(execute_strength_reduction): Call pointer_map_create for
>> 	alt_base_map; call free_affine_expand_cache with&name_expansions.
>>
>> gcc/testsuite/
>>
>> 	* gcc.dg/tree-ssa/slsr-41.c: New test.
>
>
>
Richard Biener Nov. 26, 2013, 12:45 p.m. UTC | #3
On Thu, Nov 14, 2013 at 12:25 AM, Yufeng Zhang <Yufeng.Zhang@arm.com> wrote:
> Hi Bill,
>
>
> On 11/13/13 20:54, Bill Schmidt wrote:
>>
>> Hi Yufeng,
>>
>> The second version of your original patch is ok with me with the
>> following changes.  Sorry for the little side adventure into the
>> next-interp logic; in the end that's going to hurt more than it helps in
>> this case.  Thanks for having a look at it, anyway.  Thanks also for
>> cleaning up this version to be less intrusive to common interfaces; I
>> appreciate it.
>
>
> Thanks a lot for the review.  I've attached an updated patch with the
> suggested changes incorporated.
>
> For the next-interp adventure, I was quite happy to do the experiment; it's
> a good chance of gaining insight into the pass.  Many thanks for your prompt
> replies and patience in guiding!
>
>
>> Everything else looks OK to me.  Please ask Richard for final approval,
>> as I'm not a maintainer.
>
>
> Hi Richard, would you be happy to OK the patch?

Hmm,

+static tree
+get_alternative_base (tree base)
+{
+  tree *result = (tree *) pointer_map_contains (alt_base_map, base);
+
+  if (result == NULL)
+    {
+      tree expr;
+      aff_tree aff;
+
+      tree_to_aff_combination_expand (base, TREE_TYPE (base),
+                                     &aff, &name_expansions);
+      aff.offset = tree_to_double_int (integer_zero_node);
+      expr = aff_combination_to_tree (&aff);
+
+      result = (tree *) pointer_map_insert (alt_base_map, base);
+      gcc_assert (!*result);

I believe this cache will never hit (unless you repeatedly ask for
the exact same statement?) - any non-trivial 'base' trees are
not shared and thus not pointer equivalent.

Also using tree_to_aff_combination_expand to get at - what
exactly? The address with any constant offset stripped?
Where do you re-construct that offset?  That is, aff.offset,
which you definitely need to get at a candidate?

+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-slsr" } */
+
+typedef int arr_2[50][50];
+
+void foo (arr_2 a2, int v1)
+{
+  int i, j;
+
+  i = v1 + 5;
+  j = i;
+  a2 [i-10] [j] = 2;
+  a2 [i] [j++] = i;
+  a2 [i+20] [j++] = i;
+  a2 [i-3] [i-1] += 1;
+  return;
+}
+
+/* { dg-final { scan-tree-dump-times "MEM" 5 "slsr" } } */
+/* { dg-final { cleanup-tree-dump "slsr" } } */

scanning for 5 MEMs looks non-sensical.  What transform do
you expect?  I see other slsr testcases do similar non-sensical
checking which is bad, too.

Richard.

> Regards,
>
> Yufeng
>
> gcc/
>
>         * gimple-ssa-strength-reduction.c: Include tree-affine.h.
>         (name_expansions): New static variable.
>         (alt_base_map): Ditto.
>         (get_alternative_base): New function.
>         (find_basis_for_candidate): For CAND_REF, optionally call
>         find_basis_for_base_expr with the returned value from
>         get_alternative_base.
>         (record_potential_basis): Add new parameter 'base' of type 'tree';
>         add an assertion of non-NULL base; use base to set node->base_expr.
>
>         (alloc_cand_and_find_basis): Update; call record_potential_basis
>         for CAND_REF with the returned value from get_alternative_base.
>         (execute_strength_reduction): Call pointer_map_create for
>         alt_base_map; call free_affine_expand_cache with &name_expansions.
>
> gcc/testsuite/
>
>         * gcc.dg/tree-ssa/slsr-41.c: New test.
Yufeng Zhang Nov. 26, 2013, 3:02 p.m. UTC | #4
On 11/26/13 12:45, Richard Biener wrote:
> On Thu, Nov 14, 2013 at 12:25 AM, Yufeng Zhang<Yufeng.Zhang@arm.com>  wrote:
>> Hi Bill,
>>
>>
>> On 11/13/13 20:54, Bill Schmidt wrote:
>>>
>>> Hi Yufeng,
>>>
>>> The second version of your original patch is ok with me with the
>>> following changes.  Sorry for the little side adventure into the
>>> next-interp logic; in the end that's going to hurt more than it helps in
>>> this case.  Thanks for having a look at it, anyway.  Thanks also for
>>> cleaning up this version to be less intrusive to common interfaces; I
>>> appreciate it.
>>
>>
>> Thanks a lot for the review.  I've attached an updated patch with the
>> suggested changes incorporated.
>>
>> For the next-interp adventure, I was quite happy to do the experiment; it's
>> a good chance of gaining insight into the pass.  Many thanks for your prompt
>> replies and patience in guiding!
>>
>>
>>> Everything else looks OK to me.  Please ask Richard for final approval,
>>> as I'm not a maintainer.
>>
>>
>> Hi Richard, would you be happy to OK the patch?
>
> Hmm,
>
> +static tree
> +get_alternative_base (tree base)
> +{
> +  tree *result = (tree *) pointer_map_contains (alt_base_map, base);
> +
> +  if (result == NULL)
> +    {
> +      tree expr;
> +      aff_tree aff;
> +
> +      tree_to_aff_combination_expand (base, TREE_TYPE (base),
> +&aff,&name_expansions);
> +      aff.offset = tree_to_double_int (integer_zero_node);
> +      expr = aff_combination_to_tree (&aff);
> +
> +      result = (tree *) pointer_map_insert (alt_base_map, base);
> +      gcc_assert (!*result);
>
> I believe this cache will never hit (unless you repeatedly ask for
> the exact same statement?) - any non-trivial 'base' trees are
> not shared and thus not pointer equivalent.

Yes, you are right about the non-trivial 'base' tree are rarely shared. 
  The cached is introduced mainly because get_alternative_base () may be 
called twice on the same 'base' tree, once in the 
find_basis_for_candidate () for look-up and the other time in 
alloc_cand_and_find_basis () for record_potential_basis ().  I'm happy 
to leave out the cache if you think the benefit is trivial.

> Also using tree_to_aff_combination_expand to get at - what
> exactly? The address with any constant offset stripped?
> Where do you re-construct that offset?  That is, aff.offset,
> which you definitely need to get at a candidate?

As explained in the previous RFC emails, the expanded and 
constant-offset-stripped base expr is only used for the purpose of basis 
look-up.  The corresponding candidate still has the unexpanded base expr 
as its 'base_expr', therefore the info on the constant offset is not 
lost and doesn't need to be re-constructed.

> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-slsr" } */
> +
> +typedef int arr_2[50][50];
> +
> +void foo (arr_2 a2, int v1)
> +{
> +  int i, j;
> +
> +  i = v1 + 5;
> +  j = i;
> +  a2 [i-10] [j] = 2;
> +  a2 [i] [j++] = i;
> +  a2 [i+20] [j++] = i;
> +  a2 [i-3] [i-1] += 1;
> +  return;
> +}
> +
> +/* { dg-final { scan-tree-dump-times "MEM" 5 "slsr" } } */
> +/* { dg-final { cleanup-tree-dump "slsr" } } */
>
> scanning for 5 MEMs looks non-sensical.  What transform do
> you expect?  I see other slsr testcases do similar non-sensical
> checking which is bad, too.

As the slsr optimizes CAND_REF candidates by simply lowering them to 
MEM_REF from e.g. ARRAY_REF, I think scanning for the number of MEM_REFs 
is an effective check.  Alternatively, I can add a follow-up patch to 
add some dumping facility in replace_ref () to print out the replacing 
actions when -fdump-tree-slsr-details is on.

I hope these can address your concerns.


Regards,
Yufeng



>
> Richard.
>
>> Regards,
>>
>> Yufeng
>>
>> gcc/
>>
>>          * gimple-ssa-strength-reduction.c: Include tree-affine.h.
>>          (name_expansions): New static variable.
>>          (alt_base_map): Ditto.
>>          (get_alternative_base): New function.
>>          (find_basis_for_candidate): For CAND_REF, optionally call
>>          find_basis_for_base_expr with the returned value from
>>          get_alternative_base.
>>          (record_potential_basis): Add new parameter 'base' of type 'tree';
>>          add an assertion of non-NULL base; use base to set node->base_expr.
>>
>>          (alloc_cand_and_find_basis): Update; call record_potential_basis
>>          for CAND_REF with the returned value from get_alternative_base.
>>          (execute_strength_reduction): Call pointer_map_create for
>>          alt_base_map; call free_affine_expand_cache with&name_expansions.
>>
>> gcc/testsuite/
>>
>>          * gcc.dg/tree-ssa/slsr-41.c: New test.
>
diff mbox

Patch

diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 88afc91..26502c3 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -53,6 +53,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "params.h"
 #include "hash-table.h"
 #include "tree-ssa-address.h"
+#include "tree-affine.h"
 
 /* Information about a strength reduction candidate.  Each statement
    in the candidate table represents an expression of one of the
@@ -420,6 +421,42 @@  cand_chain_hasher::equal (const value_type *chain1, const compare_type *chain2)
 /* Hash table embodying a mapping from base exprs to chains of candidates.  */
 static hash_table <cand_chain_hasher> base_cand_map;
 
+/* Pointer map used by tree_to_aff_combination_expand.  */
+static struct pointer_map_t *name_expansions;
+/* Pointer map embodying a mapping from bases to alternative bases.  */
+static struct pointer_map_t *alt_base_map;
+
+/* Given BASE, use the tree affine combiniation facilities to
+   find the underlying tree expression for BASE, with any
+   immediate offset excluded.  */
+
+static tree
+get_alternative_base (tree base)
+{
+  tree *result = (tree *) pointer_map_contains (alt_base_map, base);
+
+  if (result == NULL)
+    {
+      tree expr;
+      aff_tree aff;
+
+      tree_to_aff_combination_expand (base, TREE_TYPE (base),
+				      &aff, &name_expansions);
+      aff.offset = tree_to_double_int (integer_zero_node);
+      expr = aff_combination_to_tree (&aff);
+
+      result = (tree *) pointer_map_insert (alt_base_map, base);
+      gcc_assert (!*result);
+
+      if (expr == base)
+	*result = NULL;
+      else
+	*result = expr;
+    }
+
+  return *result;
+}
+
 /* Look in the candidate table for a CAND_PHI that defines BASE and
    return it if found; otherwise return NULL.  */
 
@@ -440,8 +477,9 @@  find_phi_def (tree base)
 }
 
 /* Helper routine for find_basis_for_candidate.  May be called twice:
-   once for the candidate's base expr, and optionally again for the
-   candidate's phi definition.  */
+   once for the candidate's base expr, and optionally again either for
+   the candidate's phi definition or for a CAND_REF's alternative base
+   expression.  */
 
 static slsr_cand_t
 find_basis_for_base_expr (slsr_cand_t c, tree base_expr)
@@ -518,6 +556,13 @@  find_basis_for_candidate (slsr_cand_t c)
 	}
     }
 
+  if (!basis && c->kind == CAND_REF)
+    {
+      tree alt_base_expr = get_alternative_base (c->base_expr);
+      if (alt_base_expr)
+	basis = find_basis_for_base_expr (c, alt_base_expr);
+    }
+
   if (basis)
     {
       c->sibling = basis->dependent;
@@ -528,17 +573,21 @@  find_basis_for_candidate (slsr_cand_t c)
   return 0;
 }
 
-/* Record a mapping from the base expression of C to C itself, indicating that
-   C may potentially serve as a basis using that base expression.  */
+/* Record a mapping from BASE to C, indicating that C may potentially serve
+   as a basis using that base expression.  BASE may be the same as
+   C->BASE_EXPR; alternatively BASE can be a different tree that share the
+   underlining expression of C->BASE_EXPR.  */
 
 static void
-record_potential_basis (slsr_cand_t c)
+record_potential_basis (slsr_cand_t c, tree base)
 {
   cand_chain_t node;
   cand_chain **slot;
 
+  gcc_assert (base);
+
   node = (cand_chain_t) obstack_alloc (&chain_obstack, sizeof (cand_chain));
-  node->base_expr = c->base_expr;
+  node->base_expr = base;
   node->cand = c;
   node->next = NULL;
   slot = base_cand_map.find_slot (node, INSERT);
@@ -554,10 +603,18 @@  record_potential_basis (slsr_cand_t c)
 }
 
 /* Allocate storage for a new candidate and initialize its fields.
-   Attempt to find a basis for the candidate.  */
+   Attempt to find a basis for the candidate.
+
+   For CAND_REF, an alternative base may also be recorded and used
+   to find a basis.  This helps cases where the expression hidden
+   behind BASE (which is usually an SSA_NAME) has immediate offset,
+   e.g.
+
+     a2[i][j] = 1;
+     a2[i + 20][j] = 2;  */
 
 static slsr_cand_t
-alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base, 
+alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base,
 			   double_int index, tree stride, tree ctype,
 			   unsigned savings)
 {
@@ -583,7 +640,13 @@  alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base,
   else
     c->basis = find_basis_for_candidate (c);
 
-  record_potential_basis (c);
+  record_potential_basis (c, base);
+  if (kind == CAND_REF)
+    {
+      tree alt_base = get_alternative_base (base);
+      if (alt_base)
+	record_potential_basis (c, alt_base);
+    }
 
   return c;
 }
@@ -3524,6 +3587,9 @@  execute_strength_reduction (void)
   /* Allocate the mapping from base expressions to candidate chains.  */
   base_cand_map.create (500);
 
+  /* Allocate the mapping from bases to alternative bases.  */
+  alt_base_map = pointer_map_create ();
+
   /* Initialize the loop optimizer.  We need to detect flow across
      back edges, and this gives us dominator information as well.  */
   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
@@ -3539,6 +3605,9 @@  execute_strength_reduction (void)
       dump_cand_chains ();
     }
 
+  pointer_map_destroy (alt_base_map);
+  free_affine_expand_cache (&name_expansions);
+
   /* Analyze costs and make appropriate replacements.  */
   analyze_candidates_and_replace ();
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c
new file mode 100644
index 0000000..870d714
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c
@@ -0,0 +1,24 @@ 
+/* Verify straight-line strength reduction in using
+   alternative base expr to record and look for the
+   potential candidate.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-slsr" } */
+
+typedef int arr_2[50][50];
+
+void foo (arr_2 a2, int v1)
+{
+  int i, j;
+
+  i = v1 + 5;
+  j = i;
+  a2 [i-10] [j] = 2;
+  a2 [i] [j++] = i;
+  a2 [i+20] [j++] = i;
+  a2 [i-3] [i-1] += 1;
+  return;
+}
+
+/* { dg-final { scan-tree-dump-times "MEM" 5 "slsr" } } */
+/* { dg-final { cleanup-tree-dump "slsr" } } */