cgraph.h (class ipa_polymorphic_call_context): Move here from ipa-utils.h; add stream...
authorJan Hubicka <hubicka@ucw.cz>
Thu, 25 Sep 2014 01:48:34 +0000 (03:48 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 25 Sep 2014 01:48:34 +0000 (01:48 +0000)
* 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.

From-SVN: r215575

gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-devirt.c
gcc/ipa-prop.c
gcc/ipa-utils.h

index 666f1a61cdc57ce690e56e1b56f902fa4fbbbf84..220027e8a30801cae5de5e314191a139d1d39e7f 100644 (file)
@@ -1,3 +1,36 @@
+2014-09-24  Jan Hubicka  <hubicka@ucw.cz>
+
+       * 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.
+
 2014-09-24  Jan Hubicka  <hubicka@ucw.cz>
 
        * ipa-utils.h (polymorphic_call_context): Add
index 8f04284863f5c509788c9478870502d69cce5291..1cfc783f80a220f6d9dab6d010b99352bc3329f5 100644 (file)
@@ -893,16 +893,7 @@ cgraph_node::create_indirect_edge (gimple call_stmt, int ecf_flags,
         = 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_failed_t reason)
 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 7e90bf07521deec8ba79fa3fcec8f4fb239b0f89..74819064fffb4da9adb914ddfa2763e3fc6e6fb3 100644 (file)
@@ -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_create (tree node)
     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 afa263f1e7f156a600276de8626b186eb99c1c2a..954cd5409871fbde265ef44e22ab068f80ba5efe 100644 (file)
@@ -135,6 +135,9 @@ along with GCC; see the file COPYING3.  If not see
 #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 () const
   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 b65a1e21493ac261da4a76972f6ae9cf3db0cdcc..36949e32709649f971ae6ff79ac997fa1930ecfe 100644 (file)
@@ -416,6 +416,8 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
        }
       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 func_body_info *fbi, gimple call,
                                   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 func_body_info *fbi, gimple call,
       && 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_info *fbi, gimple call)
 
   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 (struct cgraph_edge *cs,
          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 output_block *ob,
   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 output_block *ob,
 
 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 409e4853858e69f5631f681ffd30a4535b120566..7ff29f8c147ee2f15b626adfaa603a59b52da7b4 100644 (file)
@@ -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);