re PR tree-optimization/55260 (ICE: in ipa_get_parm_lattices, at ipa-cp.c:263 with...
authorMartin Jambor <mjambor@suse.cz>
Wed, 21 Nov 2012 17:04:45 +0000 (18:04 +0100)
committerMartin Jambor <jamborm@gcc.gnu.org>
Wed, 21 Nov 2012 17:04:45 +0000 (18:04 +0100)
2012-11-21  Martin Jambor  <mjambor@suse.cz>

PR tree-optimization/55260
* ipa-cp.c (intersect_aggregates_with_edge): New function.
(find_aggregate_values_for_callers_subset): Part moved to the function
above.  Call it.
(cgraph_edge_brings_all_agg_vals_for_node): Reimplemented using
intersect_aggregates_with_edge.

* testsuite/g++.dg/torture/pr55260-2.C: New test.

From-SVN: r193700

gcc/ChangeLog
gcc/ipa-cp.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr55260-2.C [new file with mode: 0644]

index cdce51e7b58b55fee67f580c2d4574f10ee028a0..58f69d1747cf1da6873c9592c0e6e7b79bb23499 100644 (file)
@@ -1,3 +1,12 @@
+2012-11-21  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/55260
+       * ipa-cp.c (intersect_aggregates_with_edge): New function.
+       (find_aggregate_values_for_callers_subset): Part moved to the function
+       above.  Call it.
+       (cgraph_edge_brings_all_agg_vals_for_node): Reimplemented using
+       intersect_aggregates_with_edge.
+
 2012-11-21  Matthias Klose  <doko@ubuntu.com>
 
        * config/s390/t-linux64: Add multiarch names in MULTILIB_OSDIRNAMES.
index c22f63bf6529a36442f44af0037f9b99dad36a78..16cf990dc67193c4c79a9d9e0db5acbb8823847b 100644 (file)
@@ -2850,6 +2850,127 @@ intersect_with_agg_replacements (struct cgraph_node *node, int index,
     }
 }
 
+/* Intersect values in INTER with aggregate values that come along edge CS to
+   parameter number INDEX and return it.  If INTER does not actually exist yet,
+   copy all incoming values to it.  If we determine we ended up with no values
+   whatsoever, return a released vector.  */
+
+static vec<ipa_agg_jf_item_t>
+intersect_aggregates_with_edge (struct cgraph_edge *cs, int index,
+                               vec<ipa_agg_jf_item_t> inter)
+{
+  struct ipa_jump_func *jfunc;
+  jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index);
+  if (jfunc->type == IPA_JF_PASS_THROUGH
+      && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
+    {
+      struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+      int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
+
+      if (caller_info->ipcp_orig_node)
+       {
+         struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
+         struct ipcp_param_lattices *orig_plats;
+         orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
+                                             src_idx);
+         if (agg_pass_through_permissible_p (orig_plats, jfunc))
+           {
+             if (!inter.exists ())
+               inter = agg_replacements_to_vector (cs->caller, 0);
+             else
+               intersect_with_agg_replacements (cs->caller, src_idx,
+                                                &inter, 0);
+           }
+       }
+      else
+       {
+         struct ipcp_param_lattices *src_plats;
+         src_plats = ipa_get_parm_lattices (caller_info, src_idx);
+         if (agg_pass_through_permissible_p (src_plats, jfunc))
+           {
+             /* Currently we do not produce clobber aggregate jump
+                functions, adjust when we do.  */
+             gcc_checking_assert (!jfunc->agg.items);
+             if (!inter.exists ())
+               inter = copy_plats_to_inter (src_plats, 0);
+             else
+               intersect_with_plats (src_plats, &inter, 0);
+           }
+       }
+    }
+  else if (jfunc->type == IPA_JF_ANCESTOR
+          && ipa_get_jf_ancestor_agg_preserved (jfunc))
+    {
+      struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+      int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
+      struct ipcp_param_lattices *src_plats;
+      HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
+
+      if (caller_info->ipcp_orig_node)
+       {
+         if (!inter.exists ())
+           inter = agg_replacements_to_vector (cs->caller, delta);
+         else
+           intersect_with_agg_replacements (cs->caller, index, &inter,
+                                            delta);
+       }
+      else
+       {
+         src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
+         /* Currently we do not produce clobber aggregate jump
+            functions, adjust when we do.  */
+         gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
+         if (!inter.exists ())
+           inter = copy_plats_to_inter (src_plats, delta);
+         else
+           intersect_with_plats (src_plats, &inter, delta);
+       }
+    }
+  else if (jfunc->agg.items)
+    {
+      struct ipa_agg_jf_item *item;
+      int k;
+
+      if (!inter.exists ())
+       for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
+         inter.safe_push ((*jfunc->agg.items)[i]);
+      else
+       FOR_EACH_VEC_ELT (inter, k, item)
+         {
+           int l = 0;
+           bool found = false;;
+
+           if (!item->value)
+             continue;
+
+           while ((unsigned) l < jfunc->agg.items->length ())
+             {
+               struct ipa_agg_jf_item *ti;
+               ti = &(*jfunc->agg.items)[l];
+               if (ti->offset > item->offset)
+                 break;
+               if (ti->offset == item->offset)
+                 {
+                   gcc_checking_assert (ti->value);
+                   if (values_equal_for_ipcp_p (item->value,
+                                                ti->value))
+                     found = true;
+                   break;
+                 }
+               l++;
+             }
+           if (!found)
+             item->value = NULL;
+         }
+    }
+  else
+    {
+      inter.release();
+      return vec<ipa_agg_jf_item_t>();
+    }
+  return inter;
+}
+
 /* Look at edges in CALLERS and collect all known aggregate values that arrive
    from all of them.  */
 
@@ -2883,111 +3004,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
 
       FOR_EACH_VEC_ELT (callers, j, cs)
        {
-         struct ipa_jump_func *jfunc;
-         jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i);
-         if (jfunc->type == IPA_JF_PASS_THROUGH
-             && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
-           {
-             struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
-             int src_idx = ipa_get_jf_pass_through_formal_id (jfunc);
-
-             if (caller_info->ipcp_orig_node)
-               {
-                 struct cgraph_node *orig_node = caller_info->ipcp_orig_node;
-                 struct ipcp_param_lattices *orig_plats;
-                 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node),
-                                                     src_idx);
-                 if (agg_pass_through_permissible_p (orig_plats, jfunc))
-                   {
-                     if (!inter.exists ())
-                       inter = agg_replacements_to_vector (cs->caller, 0);
-                     else
-                       intersect_with_agg_replacements (cs->caller, src_idx,
-                                                        &inter, 0);
-                   }
-               }
-             else
-               {
-                 struct ipcp_param_lattices *src_plats;
-                 src_plats = ipa_get_parm_lattices (caller_info, src_idx);
-                 if (agg_pass_through_permissible_p (src_plats, jfunc))
-                   {
-                     /* Currently we do not produce clobber aggregate jump
-                        functions, adjust when we do.  */
-                     gcc_checking_assert (!jfunc->agg.items);
-                     if (!inter.exists ())
-                       inter = copy_plats_to_inter (src_plats, 0);
-                     else
-                       intersect_with_plats (src_plats, &inter, 0);
-                   }
-               }
-           }
-         else if (jfunc->type == IPA_JF_ANCESTOR
-                  && ipa_get_jf_ancestor_agg_preserved (jfunc))
-           {
-             struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
-             int src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
-             struct ipcp_param_lattices *src_plats;
-             HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc);
-
-             if (caller_info->ipcp_orig_node)
-               {
-                 if (!inter.exists ())
-                   inter = agg_replacements_to_vector (cs->caller, delta);
-                 else
-                   intersect_with_agg_replacements (cs->caller, i, &inter,
-                                                    delta);
-               }
-             else
-               {
-                 src_plats = ipa_get_parm_lattices (caller_info, src_idx);;
-                 /* Currently we do not produce clobber aggregate jump
-                    functions, adjust when we do.  */
-                 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items);
-                 if (!inter.exists ())
-                   inter = copy_plats_to_inter (src_plats, delta);
-                 else
-                   intersect_with_plats (src_plats, &inter, delta);
-               }
-           }
-         else if (jfunc->agg.items)
-           {
-             int k;
-
-             if (!inter.exists ())
-               for (unsigned i = 0; i < jfunc->agg.items->length (); i++)
-                 inter.safe_push ((*jfunc->agg.items)[i]);
-             else
-               FOR_EACH_VEC_ELT (inter, k, item)
-                 {
-                   int l = 0;
-                   bool found = false;;
-
-                   if (!item->value)
-                     continue;
-
-                   while ((unsigned) l < jfunc->agg.items->length ())
-                     {
-                       struct ipa_agg_jf_item *ti;
-                       ti = &(*jfunc->agg.items)[l];
-                       if (ti->offset > item->offset)
-                         break;
-                       if (ti->offset == item->offset)
-                         {
-                           gcc_checking_assert (ti->value);
-                           if (values_equal_for_ipcp_p (item->value,
-                                                         ti->value))
-                             found = true;
-                           break;
-                         }
-                       l++;
-                     }
-                   if (!found)
-                     item->value = NULL;
-                 }
-           }
-         else
-           goto next_param;
+         inter = intersect_aggregates_with_edge (cs, i, inter);
 
          if (!inter.exists ())
            goto next_param;
@@ -3079,37 +3096,63 @@ static bool
 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs,
                                          struct cgraph_node *node)
 {
-  struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
+  struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller);
   struct ipa_agg_replacement_value *aggval;
+  int i, ec, count;
 
   aggval = ipa_get_agg_replacements_for_node (node);
-  while (aggval)
+  if (!aggval)
+    return true;
+
+  count = ipa_get_param_count (IPA_NODE_REF (node));
+  ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs));
+  if (ec < count)
+    for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+      if (aggval->index >= ec)
+       return false;
+
+  if (orig_caller_info->ipcp_orig_node)
+    orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node);
+
+  for (i = 0; i < count; i++)
     {
-      bool found = false;
+      static vec<ipa_agg_jf_item_t> values = vec<ipa_agg_jf_item_t>();
       struct ipcp_param_lattices *plats;
-      plats = ipa_get_parm_lattices (caller_info, aggval->index);
-      if (plats->aggs_bottom || plats->aggs_contain_variable)
+      bool interesting = false;
+      for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+       if (aggval->index == i)
+         {
+           interesting = true;
+           break;
+         }
+      if (!interesting)
+       continue;
+
+      plats = ipa_get_parm_lattices (orig_caller_info, aggval->index);
+      if (plats->aggs_bottom)
        return false;
-      for (struct ipcp_agg_lattice *aglat = plats->aggs;
-          aglat;
-          aglat = aglat->next)
-         if (aglat->offset == aggval->offset)
-           {
-             if (ipa_lat_is_single_const (aglat)
-                 && values_equal_for_ipcp_p (aggval->value,
-                                             aglat->values->value))
-               {
-                 found = true;
-                 break;
-               }
-             else
-               return false;
-           }
 
-      if (!found)
+      values = intersect_aggregates_with_edge (cs, i, values);
+      if (!values.exists())
        return false;
 
-      aggval = aggval->next;
+      for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next)
+       if (aggval->index == i)
+         {
+           struct ipa_agg_jf_item *item;
+           int j;
+           bool found = false;
+           FOR_EACH_VEC_ELT (values, j, item)
+             if (item->value
+                 && item->offset == av->offset
+                 && values_equal_for_ipcp_p (item->value, av->value))
+               found = true;
+           if (!found)
+             {
+               values.release();
+               return false;
+             }
+         }
     }
   return true;
 }
index 965c7e195e8e5ce0044d2153694ed4a054a09b33..5def603e53539456a6e29d0ed772b293c9538a70 100644 (file)
@@ -1,3 +1,8 @@
+2012-11-21  Martin Jambor  <mjambor@suse.cz>
+
+       PR tree-optimization/55260
+       * g++.dg/torture/pr55260-2.C: New test.
+
 2012-11-21  Martin Jambor  <mjambor@suse.cz>
 
        * gcc.dg/torture/pr55238.c: Remove hidden attribute.
diff --git a/gcc/testsuite/g++.dg/torture/pr55260-2.C b/gcc/testsuite/g++.dg/torture/pr55260-2.C
new file mode 100644 (file)
index 0000000..43ed1e7
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-add-options bind_pic_locally } */
+
+struct B
+{
+    virtual void test_suite_finish ();
+};
+void
+fn1 (B & p2)
+{
+    fn1 (p2);
+    B & a = p2;
+    a.test_suite_finish ();
+    B b;
+    fn1 (b);
+}