aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-09-25 03:48:34 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2014-09-25 01:48:34 +0000
commitba3923391e896c0efdfcd49eb0334525ed8bd2c0 (patch)
treed4102419e20affeb7736989b54eabee0db65012a /gcc
parent20149bd284864c06f0051f50d73ff50be46505f8 (diff)
downloadgcc-ba3923391e896c0efdfcd49eb0334525ed8bd2c0.zip
gcc-ba3923391e896c0efdfcd49eb0334525ed8bd2c0.tar.gz
gcc-ba3923391e896c0efdfcd49eb0334525ed8bd2c0.tar.bz2
cgraph.h (class ipa_polymorphic_call_context): Move here from ipa-utils.h; add stream_int and stream_out methods.
* 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog33
-rw-r--r--gcc/cgraph.c89
-rw-r--r--gcc/cgraph.h120
-rw-r--r--gcc/ipa-devirt.c70
-rw-r--r--gcc/ipa-prop.c64
-rw-r--r--gcc/ipa-utils.h108
6 files changed, 278 insertions, 206 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 666f1a6..220027e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,38 @@
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
metdhos dump, debug and clear_outer_type.
(ipa_polymorphic_call_context::ipa_polymorphic_call_context): Simplify.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 8f04284..1cfc783 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -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. */
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 7e90bf0..7481906 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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 */
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index afa263f..954cd54 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -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))
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index b65a1e2..36949e3 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -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);
}
}
diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h
index 409e485..7ff29f8 100644
--- a/gcc/ipa-utils.h
+++ b/gcc/ipa-utils.h
@@ -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);