[PATCH] Do not store/stream binfos in jump functions

Martin Jambor mjambor@suse.cz
Fri Sep 23 14:20:00 GMT 2011


Hi,

On Fri, Sep 16, 2011 at 04:29:44PM +0200, Jan Hubicka wrote:
> > 
> > 	* 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.
> 
> OK. If we saved just one pointer to the actual type (i.e. not
> BINFO), would it be any sanier?
> 

When C and C++ code is linked together, the prevailing representation
of shared types might come from the C land and thus lack BINFOs.  This
then might then falsely trigger the assert I added to
ipa_value_from_known_type_jfunc.  Therefore I have committed a
slightly different version with that assert replaced by a test.

Thanks,

Martin


2011-09-23  Martin Jambor  <mjambor@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,20 @@ ipa_get_jf_ancestor_result (struct ipa_j
     return NULL_TREE;
 }
 
+/* Extract the acual BINFO being described by JFUNC which must be a 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);
+  if (!base_binfo)
+    return NULL_TREE;
+  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 +699,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 +1005,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;



More information about the Gcc-patches mailing list