Re: [PATCH] Handle aggregate pass-through for self-recursive call (PR ipa/92794)

2019-12-18 Thread Feng Xue OS


>> +static bool
>> +self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
>> +int i)
>> +{
>> +  if (cs->caller == cs->callee->function_symbol ()

> I don't know if self-recursive calls can be interposed at all, if yes
> you need to add the availability check like we have in
> self_recursive_pass_through_p (if not, we should probably remove it
> there).

Added.  

Feng

Re: [PATCH] Handle aggregate pass-through for self-recursive call (PR ipa/92794)

2019-12-18 Thread Jan Hubicka
> Hi,
> 
> On Tue, Dec 17 2019, Feng Xue OS wrote:
> > If argument for a self-recursive call is a simple pass-through, the call
> > edge is also considered as source of any value originated from
> > non-recursive call to the function. Scalar pass-through and full aggregate
> > pass-through due to pointer pass-through have also been handled.
> > But we missed another kind of pass-through like below case,  partial
> > aggregate pass-through. This patch is meant to fix the problem which
> > caused ICE as in 92794.
> >
> >   void foo(struct T *val_ptr)
> >   {
> > struct T new_val;
> > new_val.field = val_ptr->field;
> > foo ();
> > ...
> >   }
> >
> > Bootstrapped/regtested on x86_64-linux and aarch64-linux.
> >
> > 2019-12-17  Feng Xue  
> >
> > PR ipa/92794
> > * ipa-cp.c (self_recursive_agg_pass_through_p): New function.
> > (intersect_with_plats): Use error_mark_node as place holder
> > when aggregate jump function is simple pass-through for
> > self-recursive call.
> > (intersect_with_agg_replacements): Likewise.
> > (intersect_aggregates_with_edge): Likewise.
> > (find_aggregate_values_for_callers_subset): Likewise.
> >
> > Thanks,
> > Feng
> > From 42ba553ebf80eadb62619c5570a4b406f8c90c49 Mon Sep 17 00:00:00 2001
> > From: Feng Xue 
> > Date: Mon, 16 Dec 2019 20:33:36 +0800
> > Subject: [PATCH] Handle aggregate simple pass-through for self-recursive 
> > call
> >
> > ---
> >  gcc/ipa-cp.c   | 97 +-
> >  gcc/testsuite/gcc.dg/ipa/pr92794.c | 30 +
> >  2 files changed, 111 insertions(+), 16 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.dg/ipa/pr92794.c
> >
> > diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
> > index 1a80ccbde2d..0e17fedd649 100644
> > --- a/gcc/ipa-cp.c
> > +++ b/gcc/ipa-cp.c
> > @@ -4564,6 +4564,23 @@ self_recursive_pass_through_p (cgraph_edge *cs, 
> > ipa_jump_func *jfunc, int i)
> >return false;
> >  }
> >  
> > +/* Return true, if JFUNC, which describes a part of an aggregate 
> > represented
> > +   or pointed to by the i-th parameter of call CS, is a simple no-operation
> > +   pass-through function to itself.  */
> > +
> > +static bool
> > +self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
> > +  int i)
> > +{
> > +  if (cs->caller == cs->callee->function_symbol ()
> 
> I don't know if self-recursive calls can be interposed at all, if yes
> you need to add the availability check like we have in
> self_recursive_pass_through_p (if not, we should probably remove it
> there).

Yes, self recursion can interpose if you have alias and enter the
recursive loop by different symbol name then recurse.
We have optional ref argument in ultimate_alias_target and friends where
you can specify symbol in which the reference appears and then the
predicate knows how to verify this (odd) condition.

There is cgraph_edge::recursive_p that can make mistake in positive
direction in the case of interposition. We probably want to distinguish
these cases and have parameter for that...

Honza
> 
> Apart from that, I believe the patch is probably the best thing we can
> do to deal with these interesting situations.
> 
> Thanks for looking into the bug,
> 
> Martin
> 
> 
> > +  && jfunc->jftype == IPA_JF_LOAD_AGG
> > +  && jfunc->offset == jfunc->value.load_agg.offset
> > +  && jfunc->value.pass_through.operation == NOP_EXPR
> > +  && jfunc->value.pass_through.formal_id == i)
> > +return true;
> > +  return false;
> > +}


Re: [PATCH] Handle aggregate pass-through for self-recursive call (PR ipa/92794)

2019-12-18 Thread Martin Jambor
Hi,

On Tue, Dec 17 2019, Feng Xue OS wrote:
> If argument for a self-recursive call is a simple pass-through, the call
> edge is also considered as source of any value originated from
> non-recursive call to the function. Scalar pass-through and full aggregate
> pass-through due to pointer pass-through have also been handled.
> But we missed another kind of pass-through like below case,  partial
> aggregate pass-through. This patch is meant to fix the problem which
> caused ICE as in 92794.
>
>   void foo(struct T *val_ptr)
>   {
> struct T new_val;
> new_val.field = val_ptr->field;
> foo ();
> ...
>   }
>
> Bootstrapped/regtested on x86_64-linux and aarch64-linux.
>
> 2019-12-17  Feng Xue  
>
> PR ipa/92794
> * ipa-cp.c (self_recursive_agg_pass_through_p): New function.
> (intersect_with_plats): Use error_mark_node as place holder
> when aggregate jump function is simple pass-through for
> self-recursive call.
> (intersect_with_agg_replacements): Likewise.
> (intersect_aggregates_with_edge): Likewise.
> (find_aggregate_values_for_callers_subset): Likewise.
>
> Thanks,
> Feng
> From 42ba553ebf80eadb62619c5570a4b406f8c90c49 Mon Sep 17 00:00:00 2001
> From: Feng Xue 
> Date: Mon, 16 Dec 2019 20:33:36 +0800
> Subject: [PATCH] Handle aggregate simple pass-through for self-recursive call
>
> ---
>  gcc/ipa-cp.c   | 97 +-
>  gcc/testsuite/gcc.dg/ipa/pr92794.c | 30 +
>  2 files changed, 111 insertions(+), 16 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/ipa/pr92794.c
>
> diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
> index 1a80ccbde2d..0e17fedd649 100644
> --- a/gcc/ipa-cp.c
> +++ b/gcc/ipa-cp.c
> @@ -4564,6 +4564,23 @@ self_recursive_pass_through_p (cgraph_edge *cs, 
> ipa_jump_func *jfunc, int i)
>return false;
>  }
>  
> +/* Return true, if JFUNC, which describes a part of an aggregate represented
> +   or pointed to by the i-th parameter of call CS, is a simple no-operation
> +   pass-through function to itself.  */
> +
> +static bool
> +self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
> +int i)
> +{
> +  if (cs->caller == cs->callee->function_symbol ()

I don't know if self-recursive calls can be interposed at all, if yes
you need to add the availability check like we have in
self_recursive_pass_through_p (if not, we should probably remove it
there).

Apart from that, I believe the patch is probably the best thing we can
do to deal with these interesting situations.

Thanks for looking into the bug,

Martin


> +  && jfunc->jftype == IPA_JF_LOAD_AGG
> +  && jfunc->offset == jfunc->value.load_agg.offset
> +  && jfunc->value.pass_through.operation == NOP_EXPR
> +  && jfunc->value.pass_through.formal_id == i)
> +return true;
> +  return false;
> +}


[PATCH] Handle aggregate pass-through for self-recursive call (PR ipa/92794)

2019-12-17 Thread Feng Xue OS
If argument for a self-recursive call is a simple pass-through, the call
edge is also considered as source of any value originated from
non-recursive call to the function. Scalar pass-through and full aggregate
pass-through due to pointer pass-through have also been handled.
But we missed another kind of pass-through like below case,  partial
aggregate pass-through. This patch is meant to fix the problem which
caused ICE as in 92794.

  void foo(struct T *val_ptr)
  {
struct T new_val;
new_val.field = val_ptr->field;
foo ();
...
  }

Bootstrapped/regtested on x86_64-linux and aarch64-linux.

2019-12-17  Feng Xue  

PR ipa/92794
* ipa-cp.c (self_recursive_agg_pass_through_p): New function.
(intersect_with_plats): Use error_mark_node as place holder
when aggregate jump function is simple pass-through for
self-recursive call.
(intersect_with_agg_replacements): Likewise.
(intersect_aggregates_with_edge): Likewise.
(find_aggregate_values_for_callers_subset): Likewise.

Thanks,
FengFrom 42ba553ebf80eadb62619c5570a4b406f8c90c49 Mon Sep 17 00:00:00 2001
From: Feng Xue 
Date: Mon, 16 Dec 2019 20:33:36 +0800
Subject: [PATCH] Handle aggregate simple pass-through for self-recursive call

---
 gcc/ipa-cp.c   | 97 +-
 gcc/testsuite/gcc.dg/ipa/pr92794.c | 30 +
 2 files changed, 111 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr92794.c

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 1a80ccbde2d..0e17fedd649 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -4564,6 +4564,23 @@ self_recursive_pass_through_p (cgraph_edge *cs, ipa_jump_func *jfunc, int i)
   return false;
 }
 
+/* Return true, if JFUNC, which describes a part of an aggregate represented
+   or pointed to by the i-th parameter of call CS, is a simple no-operation
+   pass-through function to itself.  */
+
+static bool
+self_recursive_agg_pass_through_p (cgraph_edge *cs, ipa_agg_jf_item *jfunc,
+   int i)
+{
+  if (cs->caller == cs->callee->function_symbol ()
+  && jfunc->jftype == IPA_JF_LOAD_AGG
+  && jfunc->offset == jfunc->value.load_agg.offset
+  && jfunc->value.pass_through.operation == NOP_EXPR
+  && jfunc->value.pass_through.formal_id == i)
+return true;
+  return false;
+}
+
 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in
KNOWN_CSTS with constants that are also known for all of the CALLERS.  */
 
@@ -4756,10 +4773,19 @@ intersect_with_plats (class ipcp_param_lattices *plats,
 	  if (aglat->offset - offset == item->offset)
 	{
 	  gcc_checking_assert (item->value);
-	  if (aglat->is_single_const ()
-		  && values_equal_for_ipcp_p (item->value,
-	  aglat->values->value))
-		found = true;
+	  if (aglat->is_single_const ())
+		{
+		  tree value = aglat->values->value;
+
+		  if (values_equal_for_ipcp_p (item->value, value))
+		found = true;
+		  else if (item->value == error_mark_node)
+		{
+		  /* Replace unknown place holder value with real one.  */
+		  item->value = value;
+		  found = true;
+		}
+		}
 	  break;
 	}
 	  aglat = aglat->next;
@@ -4827,6 +4853,12 @@ intersect_with_agg_replacements (struct cgraph_node *node, int index,
 	{
 	  if (values_equal_for_ipcp_p (item->value, av->value))
 		found = true;
+	  else if (item->value == error_mark_node)
+		{
+		  /* Replace place holder value with real one.  */
+		  item->value = av->value;
+		  found = true;
+		}
 	  break;
 	}
 	}
@@ -4931,17 +4963,31 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
 	for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
 	  {
 	struct ipa_agg_jf_item *agg_item = &(*jfunc->agg.items)[i];
-	tree value = ipa_agg_value_from_node (caller_info, cs->caller,
-		  agg_item);
-	if (value)
+	struct ipa_agg_value agg_value;
+
+	if (self_recursive_agg_pass_through_p (cs, agg_item, index))
+	  {
+		/* For a self-recursive call, if aggregate jump function is a
+		   simple pass-through, the exact value it stands for is not
+		   known, which must comes from other call sites.  But we
+		   still need to add a place holder in value sets to indicate
+		   it, here we use error_mark_node to represent the special
+		   unknown value, which will be replaced with real one during
+		   later intersecting operations.  */
+		agg_value.value = error_mark_node;
+	  }
+	else
 	  {
-		struct ipa_agg_value agg_value;
+		tree value = ipa_agg_value_from_node (caller_info, cs->caller,
+		  agg_item);
+		if (!value)
+		  continue;
 
-		agg_value.offset = agg_item->offset;
 		agg_value.value = value;
-
-		inter.safe_push (agg_value);
 	  }
+
+	agg_value.offset = agg_item->offset;
+	inter.safe_push (agg_value);
 	  }
   else
 	FOR_EACH_VEC_ELT (inter, k, item)
@@ -4960,11 +5006,27 @@ intersect_aggregates_with_edge