ipa-devirt TLC 4

Jan Hubicka hubicka@ucw.cz
Thu Sep 25 01:49:00 GMT 2014


Hi,
this patch (finally) moves polymorphic call contextes into indirect call info
solving ugly clash in between OFFSET used by IPA_PROP (where it is offset
within aggregate passed by the pointer) and OFFSET used by ipa-devirt (where it
is offset within the type of instance).

The patch aslo moves ipa_polymorphic_call_context into cgraph.h so it can
be nested within indirect_call_info.

This is a first step needed to move ipa-prop to work on contextes instead of
BINFOs.  The second step is (of course) the actual propagation part.

Honza


	* cgraph.h (class ipa_polymorphic_call_context): Move here from
	ipa-utils.h; add stream_int and stream_out methods.
	(cgraph_indirect_call_info): Remove SPECILATIVE_OFFSET,
	OUTER_TYPE, SPECULATIVE_OUTER_TYPE, MAYBE_IN_CONSTRUCTION
	MAYBE_DERIVED_TYPE and SPECULATIEVE_MAYBE_DERIVED_TYPE;
	add CONTEXT.
	(ipa_polymorphic_call_context::ipa_polymorphic_call_context,
	ipa_polymorphic_call_context::ipa_polymorphic_call_context,
	ipa_polymorphic_call_context::clear_speculation,
	ipa_polymorphic_call_context::clear_outer_type): Move here from
	ipa-utils.h
	* ipa-utils.h (class ipa_polymorphic_call_context): Move to cgraph.h
	(ipa_polymorphic_call_context::ipa_polymorphic_call_context,
	ipa_polymorphic_call_context::ipa_polymorphic_call_context,
	ipa_polymorphic_call_context::clear_speculation,
	ipa_polymorphic_call_context::clear_outer_type): Likewise.
	* ipa-devirt.c: Include data-streamer.h, lto-streamer.h and
	streamer-hooks.h
	(ipa_polymorphic_call_context::stream_out): New method.
	(ipa_polymorphic_call_context::stream_in): New method.
	(noncall_stmt_may_be_vtbl_ptr_store): Add forgotten static.
	* ipa-prop.c (ipa_analyze_indirect_call_uses): Do not care about
	OUTER_TYPE.
	(ipa_analyze_call_uses): Simplify.
	(update_indirect_edges_after_inlining): Do not care about outer_type.
	(ipa_write_indirect_edge_info): Update.
	(ipa_write_indirect_edge_info): Likewise.
	* cgraph.c (cgraph_node::create_indirect_edge): Simplify.
	(dump_edge_flags): Break out from ...
	(cgraph_node::dump): ... here; dump indirect edges.
Index: cgraph.c
===================================================================
--- cgraph.c	(revision 215569)
+++ cgraph.c	(working copy)
@@ -893,16 +893,7 @@ cgraph_node::create_indirect_edge (gimpl
 	 = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
       edge->indirect_info->otr_type = obj_type_ref_class (target);
       gcc_assert (TREE_CODE (edge->indirect_info->otr_type) == RECORD_TYPE);
-      edge->indirect_info->outer_type = context.outer_type;
-      edge->indirect_info->speculative_outer_type
-	 = context.speculative_outer_type;
-      edge->indirect_info->offset = context.offset;
-      edge->indirect_info->speculative_offset = context.speculative_offset;
-      edge->indirect_info->maybe_in_construction
-	 = context.maybe_in_construction;
-      edge->indirect_info->maybe_derived_type = context.maybe_derived_type;
-      edge->indirect_info->speculative_maybe_derived_type
-	 = context.speculative_maybe_derived_type;
+      edge->indirect_info->context = context;
     }
 
   edge->next_callee = indirect_calls;
@@ -1851,6 +1842,26 @@ cgraph_inline_failed_type (cgraph_inline
 const char * const cgraph_availability_names[] =
   {"unset", "not_available", "overwritable", "available", "local"};
 
+/* Output flags of edge E.  */
+
+static void
+dump_edge_flags (FILE *f, struct cgraph_edge *edge)
+{
+  if (edge->speculative)
+    fprintf (f, "(speculative) ");
+  if (!edge->inline_failed)
+    fprintf (f, "(inlined) ");
+  if (edge->indirect_inlining_edge)
+    fprintf (f, "(indirect_inlining) ");
+  if (edge->count)
+    fprintf (f, "(%"PRId64"x) ",
+	     (int64_t)edge->count);
+  if (edge->frequency)
+    fprintf (f, "(%.2f per call) ",
+	     edge->frequency / (double)CGRAPH_FREQ_BASE);
+  if (edge->can_throw_external)
+    fprintf (f, "(can throw external) ");
+}
 
 /* Dump call graph node to file F.  */
 
@@ -1858,7 +1869,6 @@ void
 cgraph_node::dump (FILE *f)
 {
   cgraph_edge *edge;
-  int indirect_calls_count = 0;
 
   dump_base (f);
 
@@ -1937,20 +1947,7 @@ cgraph_node::dump (FILE *f)
     {
       fprintf (f, "%s/%i ", edge->caller->asm_name (),
 	       edge->caller->order);
-      if (count)
-	fprintf (f, "(%"PRId64"x) ",
-		 (int64_t)count);
-      if (frequency)
-	fprintf (f, "(%.2f per call) ",
-		 frequency / (double)CGRAPH_FREQ_BASE);
-      if (edge->speculative)
-	fprintf (f, "(speculative) ");
-      if (!edge->inline_failed)
-	fprintf (f, "(inlined) ");
-      if (edge->indirect_inlining_edge)
-	fprintf (f, "(indirect_inlining) ");
-      if (edge->can_throw_external)
-	fprintf (f, "(can throw external) ");
+      dump_edge_flags (f, edge);
     }
 
   fprintf (f, "\n  Calls: ");
@@ -1958,28 +1955,34 @@ cgraph_node::dump (FILE *f)
     {
       fprintf (f, "%s/%i ", edge->callee->asm_name (),
 	       edge->callee->order);
-      if (edge->speculative)
-	fprintf (f, "(speculative) ");
-      if (!edge->inline_failed)
-	fprintf (f, "(inlined) ");
-      if (edge->indirect_inlining_edge)
-	fprintf (f, "(indirect_inlining) ");
-      if (edge->count)
-	fprintf (f, "(%"PRId64"x) ",
-		 (int64_t)count);
-      if (edge->frequency)
-	fprintf (f, "(%.2f per call) ",
-		 frequency / (double)CGRAPH_FREQ_BASE);
-      if (edge->can_throw_external)
-	fprintf (f, "(can throw external) ");
+      dump_edge_flags (f, edge);
     }
   fprintf (f, "\n");
 
   for (edge = indirect_calls; edge; edge = edge->next_callee)
-    indirect_calls_count++;
-  if (indirect_calls_count)
-    fprintf (f, "  Has %i outgoing edges for indirect calls.\n",
-	     indirect_calls_count);
+    {
+      if (edge->indirect_info->polymorphic)
+	{
+          fprintf (f, "   Polymorphic indirect call of type ");
+	  print_generic_expr (f, edge->indirect_info->otr_type, TDF_SLIM);
+	  fprintf (f, " token:%i", (int) edge->indirect_info->otr_token);
+	}
+      else
+        fprintf (f, "   Indirect call");
+      dump_edge_flags (f, edge);
+      if (edge->indirect_info->param_index != -1)
+	{
+	  fprintf (f, " of param:%i", edge->indirect_info->param_index);
+	  if (edge->indirect_info->agg_contents)
+	   fprintf (f, " loaded from %s %s at offset %i",
+		    edge->indirect_info->member_ptr ? "member ptr" : "aggregate",
+		    edge->indirect_info->by_ref ? "passed by reference":"",
+		    (int)edge->indirect_info->offset);
+	}
+      fprintf (f, "\n");
+      if (edge->indirect_info->polymorphic)
+	edge->indirect_info->context.dump (f);
+    }
 }
 
 /* Dump call graph node NODE to stderr.  */
Index: cgraph.h
===================================================================
--- cgraph.h	(revision 215569)
+++ cgraph.h	(working copy)
@@ -1267,19 +1267,83 @@ struct varpool_node_set_iterator
   unsigned index;
 };
 
+/* Context of polymorphic call. It represent information about the type of
+   instance that may reach the call.  This is used by ipa-devirt walkers of the
+   type inheritance graph.  */
+
+class GTY(()) ipa_polymorphic_call_context {
+public:
+  /* The called object appears in an object of type OUTER_TYPE
+     at offset OFFSET.  When information is not 100% reliable, we
+     use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
+  HOST_WIDE_INT offset;
+  HOST_WIDE_INT speculative_offset;
+  tree outer_type;
+  tree speculative_outer_type;
+  /* True if outer object may be in construction or destruction.  */
+  bool maybe_in_construction;
+  /* True if outer object may be of derived type.  */
+  bool maybe_derived_type;
+  /* True if speculative outer object may be of derived type.  We always
+     speculate that construction does not happen.  */
+  bool speculative_maybe_derived_type;
+  /* True if the context is invalid and all calls should be redirected
+     to BUILTIN_UNREACHABLE.  */
+  bool invalid;
+
+  /* Build empty "I know nothing" context.  */
+  ipa_polymorphic_call_context ();
+  /* Build polymorphic call context for indirect call E.  */
+  ipa_polymorphic_call_context (cgraph_edge *e);
+  /* Build polymorphic call context for IP invariant CST.
+     If specified, OTR_TYPE specify the type of polymorphic call
+     that takes CST+OFFSET as a prameter.  */
+  ipa_polymorphic_call_context (tree cst, tree otr_type = NULL,
+				HOST_WIDE_INT offset = 0);
+  /* Build context for pointer REF contained in FNDECL at statement STMT.
+     if INSTANCE is non-NULL, return pointer to the object described by
+     the context.  */
+  ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt,
+				tree *instance = NULL);
+
+  /* Look for vtable stores or constructor calls to work out dynamic type
+     of memory location.  */
+  bool get_dynamic_type (tree, tree, tree, gimple);
+
+  /* Make context non-speculative.  */
+  void clear_speculation ();
+
+  /* Walk container types and modify context to point to actual class
+     containing EXPECTED_TYPE as base class.  */
+  bool restrict_to_inner_class (tree expected_type);
+
+  /* Dump human readable context to F.  */
+  void dump (FILE *f) const;
+  void DEBUG_FUNCTION debug () const;
+
+  /* LTO streaming.  */
+  void stream_out (struct output_block *) const;
+  void stream_in (struct lto_input_block *, struct data_in *data_in);
+
+private:
+  void set_by_decl (tree, HOST_WIDE_INT);
+  bool set_by_invariant (tree, tree, HOST_WIDE_INT);
+  void clear_outer_type (tree otr_type = NULL);
+};
+
 /* Structure containing additional information about an indirect call.  */
 
 struct GTY(()) cgraph_indirect_call_info
 {
-  /* When polymorphic is set, this field contains offset where the object which
-     was actually used in the polymorphic resides within a larger structure.
-     If agg_contents is set, the field contains the offset within the aggregate
-     from which the address to call was loaded.  */
-  HOST_WIDE_INT offset, speculative_offset;
+  /* When agg_content is set, an offset where the call pointer is located
+     within the aggregate.  */
+  HOST_WIDE_INT offset;
+  /* Context of the polymorphic call; use only when POLYMORPHIC flag is set.  */
+  ipa_polymorphic_call_context context;
   /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set).  */
   HOST_WIDE_INT otr_token;
   /* Type of the object from OBJ_TYPE_REF_OBJECT. */
-  tree otr_type, outer_type, speculative_outer_type;
+  tree otr_type;
   /* Index of the parameter that is called.  */
   int param_index;
   /* ECF flags determined from the caller.  */
@@ -1300,9 +1364,6 @@ struct GTY(()) cgraph_indirect_call_info
   /* When the previous bit is set, this one determines whether the destination
      is loaded from a parameter passed by reference. */
   unsigned by_ref : 1;
-  unsigned int maybe_in_construction : 1;
-  unsigned int maybe_derived_type : 1;
-  unsigned int speculative_maybe_derived_type : 1;
 };
 
 struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"))) cgraph_edge {
@@ -2532,4 +2593,45 @@ inline symtab_node * symtab_node::get_cr
     return cgraph_node::get_create (node);
 }
 
+/* Build polymorphic call context for indirect call E.  */
+
+inline
+ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
+{
+  gcc_checking_assert (e->indirect_info->polymorphic);
+  *this = e->indirect_info->context;
+}
+
+/* Build empty "I know nothing" context.  */
+
+inline
+ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
+{
+  clear_speculation ();
+  clear_outer_type ();
+  invalid = false;
+}
+
+/* Make context non-speculative.  */
+
+inline void
+ipa_polymorphic_call_context::clear_speculation ()
+{
+  speculative_outer_type = NULL;
+  speculative_offset = 0;
+  speculative_maybe_derived_type = false;
+}
+
+/* Produce context specifying all derrived types of OTR_TYPE.
+   If OTR_TYPE is NULL or type of the OBJ_TYPE_REF, the context is set
+   to dummy "I know nothing" setting.  */
+
+inline void
+ipa_polymorphic_call_context::clear_outer_type (tree otr_type)
+{
+  outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL;
+  offset = 0;
+  maybe_derived_type = true;
+  maybe_in_construction = true;
+}
 #endif  /* GCC_CGRAPH_H  */
Index: ipa-devirt.c
===================================================================
--- ipa-devirt.c	(revision 215569)
+++ ipa-devirt.c	(working copy)
@@ -135,6 +135,9 @@ along with GCC; see the file COPYING3.
 #include "stor-layout.h"
 #include "intl.h"
 #include "hash-map.h"
+#include "data-streamer.h"
+#include "lto-streamer.h"
+#include "streamer-hooks.h"
 
 /* Hash based set of pairs of types.  */
 typedef struct
@@ -2570,6 +2573,71 @@ ipa_polymorphic_call_context::debug () c
   dump (stderr);
 }
 
+/* Stream out the context to OB.  */
+
+void
+ipa_polymorphic_call_context::stream_out (struct output_block *ob) const
+{
+  struct bitpack_d bp = bitpack_create (ob->main_stream);
+
+  bp_pack_value (&bp, invalid, 1);
+  bp_pack_value (&bp, maybe_in_construction, 1);
+  bp_pack_value (&bp, maybe_derived_type, 1);
+  bp_pack_value (&bp, speculative_maybe_derived_type, 1);
+  bp_pack_value (&bp, outer_type != NULL, 1);
+  bp_pack_value (&bp, offset != 0, 1);
+  bp_pack_value (&bp, speculative_outer_type != NULL, 1);
+  streamer_write_bitpack (&bp);
+
+  if (outer_type != NULL)
+    stream_write_tree (ob, outer_type, true);
+  if (offset)
+    streamer_write_hwi (ob, offset);
+  if (speculative_outer_type != NULL)
+    {
+      stream_write_tree (ob, speculative_outer_type, true);
+      streamer_write_hwi (ob, speculative_offset);
+    }
+  else
+    gcc_assert (!speculative_offset);
+}
+
+/* Stream in the context from IB and DATA_IN.  */
+
+void
+ipa_polymorphic_call_context::stream_in (struct lto_input_block *ib,
+					 struct data_in *data_in)
+{
+  struct bitpack_d bp = streamer_read_bitpack (ib);
+
+  invalid = bp_unpack_value (&bp, 1);
+  maybe_in_construction = bp_unpack_value (&bp, 1);
+  maybe_derived_type = bp_unpack_value (&bp, 1);
+  speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
+  bool outer_type_p = bp_unpack_value (&bp, 1);
+  bool offset_p = bp_unpack_value (&bp, 1);
+  bool speculative_outer_type_p = bp_unpack_value (&bp, 1);
+
+  if (outer_type_p)
+    outer_type = stream_read_tree (ib, data_in);
+  else
+    outer_type = NULL;
+  if (offset_p)
+    offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
+  else
+    offset = 0;
+  if (speculative_outer_type_p)
+    {
+      speculative_outer_type = stream_read_tree (ib, data_in);
+      speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
+    }
+  else
+    {
+      speculative_outer_type = NULL;
+      speculative_offset = 0;
+    }
+}
+
 /* Proudce polymorphic call context for call method of instance
    that is located within BASE (that is assumed to be a decl) at offset OFF. */
 
@@ -2894,7 +2962,7 @@ struct type_change_info
    We take advantage of fact that vtable stores must appear within constructor
    and destructor functions.  */
 
-bool
+static bool
 noncall_stmt_may_be_vtbl_ptr_store (gimple stmt)
 {
   if (is_gimple_assign (stmt))
Index: ipa-prop.c
===================================================================
--- ipa-prop.c	(revision 215569)
+++ ipa-prop.c	(working copy)
@@ -416,6 +416,8 @@ ipa_print_node_jump_functions (FILE *f,
 	}
       else
 	fprintf (f, "\n");
+      if (ii->polymorphic)
+	ii->context.dump (f);
       ipa_print_node_jump_functions_for_edge (f, cs);
     }
 }
@@ -2153,8 +2155,6 @@ ipa_analyze_indirect_call_uses (struct f
 				   NULL, &by_ref))
     {
       struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
-      if (cs->indirect_info->offset != offset)
-	cs->indirect_info->outer_type = NULL;
       cs->indirect_info->offset = offset;
       cs->indirect_info->agg_contents = 1;
       cs->indirect_info->by_ref = by_ref;
@@ -2255,8 +2255,6 @@ ipa_analyze_indirect_call_uses (struct f
       && parm_preserved_before_stmt_p (fbi, index, call, rec))
     {
       struct cgraph_edge *cs = ipa_note_param_call (fbi->node, index, call);
-      if (cs->indirect_info->offset != offset)
-	cs->indirect_info->outer_type = NULL;
       cs->indirect_info->offset = offset;
       cs->indirect_info->agg_contents = 1;
       cs->indirect_info->member_ptr = 1;
@@ -2345,36 +2343,20 @@ ipa_analyze_call_uses (struct func_body_
 
   if (cs->indirect_info->polymorphic)
     {
-      tree otr_type;
-      HOST_WIDE_INT otr_token;
       tree instance;
       tree target = gimple_call_fn (call);
       ipa_polymorphic_call_context context (current_function_decl,
 					    target, call, &instance);
 
-      otr_type = obj_type_ref_class (target);
-      otr_token = tree_to_uhwi (OBJ_TYPE_REF_TOKEN (target));
+      gcc_checking_assert (cs->indirect_info->otr_type
+			   == obj_type_ref_class (target));
+      gcc_checking_assert (cs->indirect_info->otr_token
+			   == tree_to_shwi (OBJ_TYPE_REF_TOKEN (target)));
 
       if (context.get_dynamic_type (instance,
 				    OBJ_TYPE_REF_OBJECT (target),
-				    otr_type, call)
-	  && context.offset == cs->indirect_info->offset)
-	{
-	  gcc_assert (TREE_CODE (otr_type) == RECORD_TYPE);
-	  cs->indirect_info->polymorphic = true;
-	  cs->indirect_info->param_index = -1;
-	  cs->indirect_info->otr_token = otr_token;
-	  cs->indirect_info->otr_type = otr_type;
-	  cs->indirect_info->outer_type = context.outer_type;
-	  cs->indirect_info->speculative_outer_type = context.speculative_outer_type;
-	  cs->indirect_info->offset = context.offset;
-	  cs->indirect_info->speculative_offset = context.speculative_offset;
-	  cs->indirect_info->maybe_in_construction
-	     = context.maybe_in_construction;
-	  cs->indirect_info->maybe_derived_type = context.maybe_derived_type;
-	  cs->indirect_info->speculative_maybe_derived_type
-	     = context.speculative_maybe_derived_type;
-	}
+				    obj_type_ref_class (target), call))
+	cs->indirect_info->context = context;
     }
 
   if (TREE_CODE (target) == SSA_NAME)
@@ -3253,8 +3235,6 @@ update_indirect_edges_after_inlining (st
 	  else
 	    {
 	      ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc);
-	      if (ipa_get_jf_ancestor_offset (jfunc))
-	        ici->outer_type = NULL;
 	      ici->offset += ipa_get_jf_ancestor_offset (jfunc);
 	    }
 	}
@@ -4735,25 +4715,22 @@ ipa_write_indirect_edge_info (struct out
   struct bitpack_d bp;
 
   streamer_write_hwi (ob, ii->param_index);
-  streamer_write_hwi (ob, ii->offset);
   bp = bitpack_create (ob->main_stream);
   bp_pack_value (&bp, ii->polymorphic, 1);
   bp_pack_value (&bp, ii->agg_contents, 1);
   bp_pack_value (&bp, ii->member_ptr, 1);
   bp_pack_value (&bp, ii->by_ref, 1);
-  bp_pack_value (&bp, ii->maybe_in_construction, 1);
-  bp_pack_value (&bp, ii->maybe_derived_type, 1);
-  bp_pack_value (&bp, ii->speculative_maybe_derived_type, 1);
   streamer_write_bitpack (&bp);
+  if (ii->agg_contents || ii->polymorphic)
+    streamer_write_hwi (ob, ii->offset);
+  else
+    gcc_assert (ii->offset == 0);
 
   if (ii->polymorphic)
     {
       streamer_write_hwi (ob, ii->otr_token);
       stream_write_tree (ob, ii->otr_type, true);
-      stream_write_tree (ob, ii->outer_type, true);
-      stream_write_tree (ob, ii->speculative_outer_type, true);
-      if (ii->speculative_outer_type)
-        streamer_write_hwi (ob, ii->speculative_offset);
+      ii->context.stream_out (ob);
     }
 }
 
@@ -4762,30 +4739,27 @@ ipa_write_indirect_edge_info (struct out
 
 static void
 ipa_read_indirect_edge_info (struct lto_input_block *ib,
-			     struct data_in *data_in ATTRIBUTE_UNUSED,
+			     struct data_in *data_in,
 			     struct cgraph_edge *cs)
 {
   struct cgraph_indirect_call_info *ii = cs->indirect_info;
   struct bitpack_d bp;
 
   ii->param_index = (int) streamer_read_hwi (ib);
-  ii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
   bp = streamer_read_bitpack (ib);
   ii->polymorphic = bp_unpack_value (&bp, 1);
   ii->agg_contents = bp_unpack_value (&bp, 1);
   ii->member_ptr = bp_unpack_value (&bp, 1);
   ii->by_ref = bp_unpack_value (&bp, 1);
-  ii->maybe_in_construction = bp_unpack_value (&bp, 1);
-  ii->maybe_derived_type = bp_unpack_value (&bp, 1);
-  ii->speculative_maybe_derived_type = bp_unpack_value (&bp, 1);
+  if (ii->agg_contents || ii->polymorphic)
+    ii->offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
+  else
+    ii->offset = 0;
   if (ii->polymorphic)
     {
       ii->otr_token = (HOST_WIDE_INT) streamer_read_hwi (ib);
       ii->otr_type = stream_read_tree (ib, data_in);
-      ii->outer_type = stream_read_tree (ib, data_in);
-      ii->speculative_outer_type = stream_read_tree (ib, data_in);
-      if (ii->speculative_outer_type)
-        ii->speculative_offset = (HOST_WIDE_INT) streamer_read_hwi (ib);
+      ii->context.stream_in (ib, data_in);
     }
 }
 
Index: ipa-utils.h
===================================================================
--- ipa-utils.h	(revision 215569)
+++ ipa-utils.h	(working copy)
@@ -34,114 +34,6 @@ struct ipa_dfs_info {
   PTR aux;
 };
 
-/* Context of polymorphic call.  This is used by ipa-devirt walkers of the
-   type inheritance graph.  */
-
-class ipa_polymorphic_call_context {
-public:
-  /* The called object appears in an object of type OUTER_TYPE
-     at offset OFFSET.  When information is not 100% reliable, we
-     use SPECULATIVE_OUTER_TYPE and SPECULATIVE_OFFSET. */
-  HOST_WIDE_INT offset;
-  HOST_WIDE_INT speculative_offset;
-  tree outer_type;
-  tree speculative_outer_type;
-  /* True if outer object may be in construction or destruction.  */
-  bool maybe_in_construction;
-  /* True if outer object may be of derived type.  */
-  bool maybe_derived_type;
-  /* True if speculative outer object may be of derived type.  We always
-     speculate that construction does not happen.  */
-  bool speculative_maybe_derived_type;
-  /* True if the context is invalid and all calls should be redirected
-     to BUILTIN_UNREACHABLE.  */
-  bool invalid;
-
-  /* Build empty "I know nothing" context.  */
-  ipa_polymorphic_call_context ();
-  /* Build polymorphic call context for indirect call E.  */
-  ipa_polymorphic_call_context (cgraph_edge *e);
-  /* Build polymorphic call context for IP invariant CST.
-     If specified, OTR_TYPE specify the type of polymorphic call
-     that takes CST+OFFSET as a prameter.  */
-  ipa_polymorphic_call_context (tree cst, tree otr_type = NULL,
-				HOST_WIDE_INT offset = 0);
-  /* Build context for pointer REF contained in FNDECL at statement STMT.
-     if INSTANCE is non-NULL, return pointer to the object described by
-     the context.  */
-  ipa_polymorphic_call_context (tree fndecl, tree ref, gimple stmt,
-				tree *instance = NULL);
-
-  /* Look for vtable stores or constructor calls to work out dynamic type
-     of memory location.  */
-  bool get_dynamic_type (tree, tree, tree, gimple);
-
-  /* Make context non-speculative.  */
-  void clear_speculation ();
-
-  /* Walk container types and modify context to point to actual class
-     containing EXPECTED_TYPE as base class.  */
-  bool restrict_to_inner_class (tree expected_type);
-
-  /* Dump human readable context to F.  */
-  void dump (FILE *f) const;
-  void DEBUG_FUNCTION debug () const;
-
-private:
-  void set_by_decl (tree, HOST_WIDE_INT);
-  bool set_by_invariant (tree, tree, HOST_WIDE_INT);
-  void clear_outer_type (tree otr_type = NULL);
-};
-
-/* Build polymorphic call context for indirect call E.  */
-
-inline
-ipa_polymorphic_call_context::ipa_polymorphic_call_context (cgraph_edge *e)
-{
-  gcc_checking_assert (e->indirect_info->polymorphic);
-
-  offset = e->indirect_info->offset;
-  speculative_offset = e->indirect_info->speculative_offset;
-  outer_type = e->indirect_info->outer_type;
-  speculative_outer_type = e->indirect_info->speculative_outer_type;
-  maybe_in_construction = e->indirect_info->maybe_in_construction;
-  maybe_derived_type = e->indirect_info->maybe_derived_type;
-  speculative_maybe_derived_type = e->indirect_info->speculative_maybe_derived_type;
-  invalid = false;
-}
-
-/* Build empty "I know nothing" context.  */
-
-inline
-ipa_polymorphic_call_context::ipa_polymorphic_call_context ()
-{
-  clear_speculation ();
-  clear_outer_type ();
-  invalid = false;
-}
-
-/* Make context non-speculative.  */
-
-inline void
-ipa_polymorphic_call_context::clear_speculation ()
-{
-  speculative_outer_type = NULL;
-  speculative_offset = 0;
-  speculative_maybe_derived_type = false;
-}
-
-/* Produce context specifying all derrived types of OTR_TYPE.
-   If OTR_TYPE is NULL or type of the OBJ_TYPE_REF, the context is set
-   to dummy "I know nothing" setting.  */
-
-inline void
-ipa_polymorphic_call_context::clear_outer_type (tree otr_type)
-{
-  outer_type = otr_type ? TYPE_MAIN_VARIANT (otr_type) : NULL;
-  offset = 0;
-  maybe_derived_type = true;
-  maybe_in_construction = true;
-}
 
 /* In ipa-utils.c  */
 void ipa_print_order (FILE*, const char *, struct cgraph_node**, int);



More information about the Gcc-patches mailing list