Hi,

this patch is basically a followup to
http://gcc.gnu.org/ml/gcc-patches/2011-09/msg00398.html

The problem is that BINFOs coming from different compilation units and
which are streamed into jump-functions do not undergo any unification
in LTO and we have the same value represented by different BINFO
structures (and compare them by comparing pointers to them).

The solution is to do the BINFO lookup from the type after the type
unification system has chosen the prevailing type (and fixed all
references to it).  This means that in the known type jump functions
we need to store the parameters for get_binfo_at_offset instead of its
result and call the function only when actually using the value of the
function at the IPA decision making stage.

I have bootstrapped and tested the patch on x86_64-linux and have also
successfully LTO-built 483.xalancbmk and now I'm in the process of
LTO-building Firefox with it.  OK for trunk?

Thanks,

Martin


2011-09-15  Martin Jambor  <mjam...@suse.cz>

        * ipa-prop.h (jump_func_type): Updated comments.
        (ipa_known_type_data): New type.
        (ipa_jump_func): Use it to describe known type jump functions.
        * ipa-prop.c (ipa_print_node_jump_functions_for_edge): Updated to
        reflect the new known type jump function contents.
        (compute_known_type_jump_func): Likewise.
        (combine_known_type_and_ancestor_jfs): Likewise.
        (try_make_edge_direct_virtual_call): Likewise.
        (ipa_write_jump_function): Likewise.
        (ipa_read_jump_function): Likewise.
        * ipa-cp.c (ipa_value_from_known_type_jfunc): New function.
        (ipa_value_from_jfunc): Use ipa_value_from_known_type_jfunc.
        (propagate_accross_jump_function): Likewise.

Index: src/gcc/ipa-cp.c
===================================================================
--- src.orig/gcc/ipa-cp.c
+++ src/gcc/ipa-cp.c
@@ -674,6 +674,19 @@ ipa_get_jf_ancestor_result (struct ipa_j
     return NULL_TREE;
 }
 
+/* Extract the acual BINFO being described by JFUNC which must b e known type
+   jump function.  */
+
+static tree
+ipa_value_from_known_type_jfunc (struct ipa_jump_func *jfunc)
+{
+  tree base_binfo = TYPE_BINFO (jfunc->value.known_type.base_type);
+  gcc_checking_assert (base_binfo);
+  return get_binfo_at_offset (base_binfo,
+                             jfunc->value.known_type.offset,
+                             jfunc->value.known_type.component_type);
+}
+
 /* Determine whether JFUNC evaluates to a known value (that is either a
    constant or a binfo) and if so, return it.  Otherwise return NULL. INFO
    describes the caller node so that pass-through jump functions can be
@@ -685,7 +698,7 @@ ipa_value_from_jfunc (struct ipa_node_pa
   if (jfunc->type == IPA_JF_CONST)
     return jfunc->value.constant;
   else if (jfunc->type == IPA_JF_KNOWN_TYPE)
-    return jfunc->value.base_binfo;
+    return ipa_value_from_known_type_jfunc (jfunc);
   else if (jfunc->type == IPA_JF_PASS_THROUGH
           || jfunc->type == IPA_JF_ANCESTOR)
     {
@@ -991,7 +1004,11 @@ propagate_accross_jump_function (struct
       tree val;
 
       if (jfunc->type == IPA_JF_KNOWN_TYPE)
-       val = jfunc->value.base_binfo;
+       {
+         val = ipa_value_from_known_type_jfunc (jfunc);
+         if (!val)
+           return set_lattice_contains_variable (dest_lat);
+       }
       else
        val = jfunc->value.constant;
       return add_value_to_lattice (dest_lat, val, cs, NULL, 0);
Index: src/gcc/ipa-prop.c
===================================================================
--- src.orig/gcc/ipa-prop.c
+++ src/gcc/ipa-prop.c
@@ -164,10 +164,12 @@ ipa_print_node_jump_functions_for_edge (
        fprintf (f, "UNKNOWN\n");
       else if (type == IPA_JF_KNOWN_TYPE)
        {
-         tree binfo_type = TREE_TYPE (jump_func->value.base_binfo);
-         fprintf (f, "KNOWN TYPE, type in binfo is: ");
-         print_generic_expr (f, binfo_type, 0);
-         fprintf (f, " (%u)\n", TYPE_UID (binfo_type));
+         fprintf (f, "KNOWN TYPE: base  ");
+         print_generic_expr (f, jump_func->value.known_type.base_type, 0);
+         fprintf (f, ", offset "HOST_WIDE_INT_PRINT_DEC", component ",
+                  jump_func->value.known_type.offset);
+         print_generic_expr (f, jump_func->value.known_type.component_type, 0);
+         fprintf (f, "\n");
        }
       else if (type == IPA_JF_CONST)
        {
@@ -638,7 +640,7 @@ compute_known_type_jump_func (tree op, s
                              gimple call)
 {
   HOST_WIDE_INT offset, size, max_size;
-  tree base, binfo;
+  tree base;
 
   if (!flag_devirtualize
       || TREE_CODE (op) != ADDR_EXPR
@@ -654,18 +656,14 @@ compute_known_type_jump_func (tree op, s
       || is_global_var (base))
     return;
 
-  if (detect_type_change (op, base, call, jfunc, offset))
+  if (detect_type_change (op, base, call, jfunc, offset)
+      || !TYPE_BINFO (TREE_TYPE (base)))
     return;
 
-  binfo = TYPE_BINFO (TREE_TYPE (base));
-  if (!binfo)
-    return;
-  binfo = get_binfo_at_offset (binfo, offset, TREE_TYPE (op));
-  if (binfo)
-    {
-      jfunc->type = IPA_JF_KNOWN_TYPE;
-      jfunc->value.base_binfo = binfo;
-    }
+  jfunc->type = IPA_JF_KNOWN_TYPE;
+  jfunc->value.known_type.base_type = TREE_TYPE (base);
+  jfunc->value.known_type.offset = offset;
+  jfunc->value.known_type.component_type = TREE_TYPE (op);
 }
 
 
@@ -1504,18 +1502,16 @@ static void
 combine_known_type_and_ancestor_jfs (struct ipa_jump_func *src,
                                     struct ipa_jump_func *dst)
 {
-  tree new_binfo;
+  HOST_WIDE_INT combined_offset;
+  tree combined_type;
 
-  new_binfo = get_binfo_at_offset (src->value.base_binfo,
-                                  dst->value.ancestor.offset,
-                                  dst->value.ancestor.type);
-  if (new_binfo)
-    {
-      dst->type = IPA_JF_KNOWN_TYPE;
-      dst->value.base_binfo = new_binfo;
-    }
-  else
-    dst->type = IPA_JF_UNKNOWN;
+  combined_offset = src->value.known_type.offset + dst->value.ancestor.offset;
+  combined_type = dst->value.ancestor.type;
+
+  dst->type = IPA_JF_KNOWN_TYPE;
+  dst->value.known_type.base_type = src->value.known_type.base_type;
+  dst->value.known_type.offset = combined_offset;
+  dst->value.known_type.component_type = combined_type;
 }
 
 /* Update the jump functions associated with call graph edge E when the call
@@ -1650,22 +1646,19 @@ static struct cgraph_edge *
 try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
                                   struct ipa_jump_func *jfunc)
 {
-  tree binfo, type, target;
-  HOST_WIDE_INT token;
-
-  if (jfunc->type == IPA_JF_KNOWN_TYPE)
-    binfo = jfunc->value.base_binfo;
-  else
-    return NULL;
+  tree binfo, target;
 
-  if (!binfo)
+  if (jfunc->type != IPA_JF_KNOWN_TYPE)
     return NULL;
 
-  token = ie->indirect_info->otr_token;
-  type = ie->indirect_info->otr_type;
-  binfo = get_binfo_at_offset (binfo, ie->indirect_info->anc_offset, type);
+  binfo = TYPE_BINFO (jfunc->value.known_type.base_type);
+  gcc_checking_assert (binfo);
+  binfo = get_binfo_at_offset (binfo, jfunc->value.known_type.offset
+                              + ie->indirect_info->anc_offset,
+                              ie->indirect_info->otr_type);
   if (binfo)
-    target = gimple_get_virt_method_for_binfo (token, binfo);
+    target = gimple_get_virt_method_for_binfo (ie->indirect_info->otr_token,
+                                              binfo);
   else
     return NULL;
 
@@ -2589,7 +2582,9 @@ ipa_write_jump_function (struct output_b
     case IPA_JF_UNKNOWN:
       break;
     case IPA_JF_KNOWN_TYPE:
-      stream_write_tree (ob, jump_func->value.base_binfo, true);
+      streamer_write_uhwi (ob, jump_func->value.known_type.offset);
+      stream_write_tree (ob, jump_func->value.known_type.base_type, true);
+      stream_write_tree (ob, jump_func->value.known_type.component_type, true);
       break;
     case IPA_JF_CONST:
       stream_write_tree (ob, jump_func->value.constant, true);
@@ -2625,7 +2620,10 @@ ipa_read_jump_function (struct lto_input
     case IPA_JF_UNKNOWN:
       break;
     case IPA_JF_KNOWN_TYPE:
-      jump_func->value.base_binfo = stream_read_tree (ib, data_in);
+      jump_func->value.known_type.offset = streamer_read_uhwi (ib);
+      jump_func->value.known_type.base_type = stream_read_tree (ib, data_in);
+      jump_func->value.known_type.component_type = stream_read_tree (ib,
+                                                                    data_in);
       break;
     case IPA_JF_CONST:
       jump_func->value.constant = stream_read_tree (ib, data_in);
Index: src/gcc/ipa-prop.h
===================================================================
--- src.orig/gcc/ipa-prop.h
+++ src/gcc/ipa-prop.h
@@ -72,13 +72,24 @@ along with GCC; see the file COPYING3.
 enum jump_func_type
 {
   IPA_JF_UNKNOWN = 0,  /* newly allocated and zeroed jump functions default */
-  IPA_JF_KNOWN_TYPE,        /* represented by field base_binfo */
+  IPA_JF_KNOWN_TYPE,        /* represented by field known_type */
   IPA_JF_CONST,             /* represented by field costant */
   IPA_JF_CONST_MEMBER_PTR,  /* represented by field member_cst */
   IPA_JF_PASS_THROUGH,     /* represented by field pass_through */
   IPA_JF_ANCESTOR          /* represented by field ancestor */
 };
 
+/* Structure holding data required to describe a known type jump function.  */
+struct GTY(()) ipa_known_type_data
+{
+  /* Offset of the component of the base_type being described.  */
+  HOST_WIDE_INT offset;
+  /* Type of the whole object.  */
+  tree base_type;
+  /* Type of the component of the object that is being described.  */
+  tree component_type;
+};
+
 /* Structure holding data required to describe a pass-through jump function.  
*/
 
 struct GTY(()) ipa_pass_through_data
@@ -127,7 +138,7 @@ typedef struct GTY (()) ipa_jump_func
      functions and member_cst holds constant c++ member functions.  */
   union jump_func_value
   {
-    tree GTY ((tag ("IPA_JF_KNOWN_TYPE"))) base_binfo;
+    struct ipa_known_type_data GTY ((tag ("IPA_JF_KNOWN_TYPE"))) known_type;
     tree GTY ((tag ("IPA_JF_CONST"))) constant;
     struct ipa_member_ptr_cst GTY ((tag ("IPA_JF_CONST_MEMBER_PTR"))) 
member_cst;
     struct ipa_pass_through_data GTY ((tag ("IPA_JF_PASS_THROUGH"))) 
pass_through;

Reply via email to