Handle aggregate pass-through for self-recursive call (PR ipa/92794)
authorFeng Xue <fxue@os.amperecomputing.com>
Thu, 19 Dec 2019 02:54:40 +0000 (02:54 +0000)
committerFeng Xue <fxue@gcc.gnu.org>
Thu, 19 Dec 2019 02:54:40 +0000 (02:54 +0000)
2019-12-19  Feng Xue  <fxue@os.amperecomputing.com>

        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.

2019-12-19  Feng Xue  <fxue@os.amperecomputing.com>

        PR ipa/92794
        * gcc.dg/ipa/92794.c: New test.

From-SVN: r279561

gcc/ChangeLog
gcc/ipa-cp.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ipa/pr92794.c [new file with mode: 0644]

index 5927823a83a23fbecdf512fa15cedbd307b4b6f1..e52d05634d34e8d94cbeb1e9cf328a332dff3c2f 100644 (file)
@@ -1,3 +1,14 @@
+2019-12-19  Feng Xue  <fxue@os.amperecomputing.com>
+
+       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.
+
 2019-12-18  David Malcolm  <dmalcolm@redhat.com>
 
        * common.opt (fdiagnostics-show-cwe): Add.
index 243b064ee2ca510c7e4a0384aa17250b2974804b..126d154318cc608accc5a2e61a156e02b60891e5 100644 (file)
@@ -4564,6 +4564,25 @@ 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)
+{
+  enum availability availability;
+  if (cs->caller == cs->callee->function_symbol (&availability)
+      && availability > AVAIL_INTERPOSABLE
+      && 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 +4775,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 +4855,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 +4965,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))
              {
-               struct ipa_agg_value agg_value;
+               /* For a self-recursive call, if aggregate jump function is a
+                  simple pass-through, the exact value that it stands for is
+                  not known at this point, 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
+             {
+               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 +5008,27 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
                  break;
                if (ti->offset == item->offset)
                  {
-                   tree value = ipa_agg_value_from_node (caller_info,
-                                                         cs->caller, ti);
-                   if (value
-                       && values_equal_for_ipcp_p (item->value, value))
-                     found = true;
+                   tree value;
+
+                   if (self_recursive_agg_pass_through_p (cs, ti, index))
+                     {
+                       /* A simple aggregate pass-through in self-recursive
+                          call should lead to same value.  */
+                       found = true;
+                     }
+                   else if ((value = ipa_agg_value_from_node (caller_info,
+                                                            cs->caller, ti)))
+                     {
+                       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;
                  }
                l++;
@@ -5040,6 +5104,9 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
          if (!item->value)
            continue;
 
+         /* All values must be real values, not unknown place holders.  */
+         gcc_assert (item->value != error_mark_node);
+
          v = ggc_alloc<ipa_agg_replacement_value> ();
          v->index = i;
          v->offset = item->offset;
index 18b4ba31348e0fc7c480cdb904778ae0ba520e8b..e66980e07679b4da26375d586a578849c97a759d 100644 (file)
@@ -1,3 +1,8 @@
+2019-12-19  Feng Xue  <fxue@os.amperecomputing.com>
+
+       PR ipa/92794
+       * gcc.dg/ipa/92794.c: New test.
+
 2019-12-18  David Malcolm  <dmalcolm@redhat.com>
 
        * gcc.dg/plugin/diagnostic-test-metadata.c: New test.
diff --git a/gcc/testsuite/gcc.dg/ipa/pr92794.c b/gcc/testsuite/gcc.dg/ipa/pr92794.c
new file mode 100644 (file)
index 0000000..c354617
--- /dev/null
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 --param ipa-cp-eval-threshold=1" } */
+
+int data[100];
+int depth = 0;
+
+int recur_fn (int *__restrict p)
+{
+  int i = *p;
+
+  if (depth++ > 6) 
+    return 10;
+
+  data[i] = i; 
+
+  recur_fn (&i);
+
+  depth--;
+
+  return i;
+}
+
+int main ()
+{
+  int i = 1;
+
+  recur_fn (&i);
+
+  return 0;
+}