aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2011-01-03 14:06:54 +0100
committerMartin Jambor <jamborm@gcc.gnu.org>2011-01-03 14:06:54 +0100
commitce47fda3ce6adfe86f725930dedbfb1f775ddd45 (patch)
treea0198b9cc6e29df5e3c9c571f5a99db84117cc75 /gcc
parentfd0bcb5af982e58e40c5fad1eb0d1a54316b2807 (diff)
downloadgcc-ce47fda3ce6adfe86f725930dedbfb1f775ddd45.zip
gcc-ce47fda3ce6adfe86f725930dedbfb1f775ddd45.tar.gz
gcc-ce47fda3ce6adfe86f725930dedbfb1f775ddd45.tar.bz2
re PR tree-optimization/46984 (g++.dg/torture/pr45699.C FAILs with -fno-early-inlining -flto)
2011-01-03 Martin Jambor <mjambor@suse.cz> PR tree-optimization/46984 * cgraph.h (cgraph_indirect_call_info): make field thunk_delta HOST_WIDE_INT. (cgraph_create_indirect_edge): Fixed line length. (cgraph_indirect_call_info): Declare. (cgraph_make_edge_direct) Update declaration. * cgraph.c (cgraph_allocate_init_indirect_info): New function. (cgraph_create_indirect_edge): Use it. (cgraph_make_edge_direct): Made delta HOST_WIDE_INT. Updated all callees. * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Update for the new thunk_delta representation. * ipa-prop.c (ipa_make_edge_direct_to_target): Convert delta to HOST_WIDE_INT. (ipa_write_indirect_edge_info): Remove streaming of thunk_delta. (ipa_read_indirect_edge_info): Likewise. * lto-cgraph.c (output_edge_opt_summary): New function. (output_node_opt_summary): Call it on all outgoing edges. (input_edge_opt_summary): New function. (input_node_opt_summary): Call it on all outgoing edges. * testsuite/g++.dg/ipa/pr46984.C: New test. From-SVN: r168420
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/cgraph.c22
-rw-r--r--gcc/cgraph.h14
-rw-r--r--gcc/cgraphunit.c18
-rw-r--r--gcc/ipa-prop.c4
-rw-r--r--gcc/lto-cgraph.c40
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr46984.C62
8 files changed, 162 insertions, 26 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aebe391..c908a7b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,26 @@
+2011-01-03 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/46984
+ * cgraph.h (cgraph_indirect_call_info): make field thunk_delta
+ HOST_WIDE_INT.
+ (cgraph_create_indirect_edge): Fixed line length.
+ (cgraph_indirect_call_info): Declare.
+ (cgraph_make_edge_direct) Update declaration.
+ * cgraph.c (cgraph_allocate_init_indirect_info): New function.
+ (cgraph_create_indirect_edge): Use it.
+ (cgraph_make_edge_direct): Made delta HOST_WIDE_INT. Updated all
+ callees.
+ * cgraphunit.c (cgraph_redirect_edge_call_stmt_to_callee): Update for
+ the new thunk_delta representation.
+ * ipa-prop.c (ipa_make_edge_direct_to_target): Convert delta to
+ HOST_WIDE_INT.
+ (ipa_write_indirect_edge_info): Remove streaming of thunk_delta.
+ (ipa_read_indirect_edge_info): Likewise.
+ * lto-cgraph.c (output_edge_opt_summary): New function.
+ (output_node_opt_summary): Call it on all outgoing edges.
+ (input_edge_opt_summary): New function.
+ (input_node_opt_summary): Call it on all outgoing edges.
+
2011-01-02 H.J. Lu <hongjiu.lu@intel.com>
PR driver/47137
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index f96bd64..c8f9b04 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -860,7 +860,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt)
indirect call into a direct one. */
struct cgraph_node *new_callee = cgraph_node (decl);
- cgraph_make_edge_direct (e, new_callee, NULL);
+ cgraph_make_edge_direct (e, new_callee, 0);
}
push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
@@ -1070,6 +1070,17 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
return edge;
}
+/* Allocate cgraph_indirect_call_info and set its fields to default values. */
+
+struct cgraph_indirect_call_info *
+cgraph_allocate_init_indirect_info (void)
+{
+ struct cgraph_indirect_call_info *ii;
+
+ ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
+ ii->param_index = -1;
+ return ii;
+}
/* Create an indirect edge with a yet-undetermined callee where the call
statement destination is a formal parameter of the caller with index
@@ -1086,8 +1097,7 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
edge->indirect_unknown_callee = 1;
initialize_inline_failed (edge);
- edge->indirect_info = ggc_alloc_cleared_cgraph_indirect_call_info ();
- edge->indirect_info->param_index = -1;
+ edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->ecf_flags = ecf_flags;
edge->next_callee = caller->indirect_calls;
@@ -1195,12 +1205,12 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n)
}
/* Make an indirect EDGE with an unknown callee an ordinary edge leading to
- CALLEE. DELTA, if non-NULL, is an integer constant that is to be added to
- the this pointer (first parameter). */
+ CALLEE. DELTA is an integer constant that is to be added to the this
+ pointer (first parameter) to compensate for skipping a thunk adjustment. */
void
cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee,
- tree delta)
+ HOST_WIDE_INT delta)
{
edge->indirect_unknown_callee = 0;
edge->indirect_info->thunk_delta = delta;
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 69bc79c..33b3167 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -386,11 +386,11 @@ struct GTY(()) cgraph_indirect_call_info
HOST_WIDE_INT anc_offset;
/* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
HOST_WIDE_INT otr_token;
+ /* Delta by which must be added to this parameter to compensate for a skipped
+ this adjusting thunk. */
+ HOST_WIDE_INT thunk_delta;
/* Type of the object from OBJ_TYPE_REF_OBJECT. */
tree otr_type;
- /* Delta by which must be added to this parameter. For polymorphic calls
- only. */
- tree thunk_delta;
/* Index of the parameter that is called. */
int param_index;
/* ECF flags determined from the caller. */
@@ -549,8 +549,9 @@ void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *,
gimple, gcov_type, int, int);
-struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int,
- gcov_type, int, int);
+struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
+ int, gcov_type, int, int);
+struct cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
struct cgraph_node * cgraph_get_node (const_tree);
struct cgraph_node * cgraph_get_node_or_alias (const_tree);
struct cgraph_node * cgraph_node (tree);
@@ -578,7 +579,8 @@ struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type, i
int, bool, VEC(cgraph_edge_p,heap) *);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
-void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *, tree);
+void cgraph_make_edge_direct (struct cgraph_edge *, struct cgraph_node *,
+ HOST_WIDE_INT);
struct cgraph_asm_node *cgraph_add_asm_node (tree);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 013cf63..36ba75a 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2168,22 +2168,20 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
}
}
- if (e->indirect_info && e->indirect_info->thunk_delta
- && integer_nonzerop (e->indirect_info->thunk_delta)
+ if (e->indirect_info &&
+ e->indirect_info->thunk_delta != 0
&& (!e->callee->clone.combined_args_to_skip
|| !bitmap_bit_p (e->callee->clone.combined_args_to_skip, 0)))
{
if (cgraph_dump_file)
- {
- fprintf (cgraph_dump_file, " Thunk delta is ");
- print_generic_expr (cgraph_dump_file,
- e->indirect_info->thunk_delta, 0);
- fprintf (cgraph_dump_file, "\n");
- }
+ fprintf (cgraph_dump_file, " Thunk delta is "
+ HOST_WIDE_INT_PRINT_DEC "\n", e->indirect_info->thunk_delta);
gsi = gsi_for_stmt (e->call_stmt);
gsi_computed = true;
- gimple_adjust_this_by_delta (&gsi, e->indirect_info->thunk_delta);
- e->indirect_info->thunk_delta = NULL_TREE;
+ gimple_adjust_this_by_delta (&gsi,
+ build_int_cst (sizetype,
+ e->indirect_info->thunk_delta));
+ e->indirect_info->thunk_delta = 0;
}
if (e->callee->clone.combined_args_to_skip)
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index b6e3f37..f85a4ff 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -1483,7 +1483,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta)
return NULL;
ipa_check_create_node_params ();
- cgraph_make_edge_direct (ie, callee, delta);
+ cgraph_make_edge_direct (ie, callee, delta ? tree_low_cst (delta, 0) : 0);
if (dump_file)
{
fprintf (dump_file, "ipa-prop: Discovered %s call to a known target "
@@ -2549,7 +2549,6 @@ ipa_write_indirect_edge_info (struct output_block *ob,
{
lto_output_sleb128_stream (ob->main_stream, ii->otr_token);
lto_output_tree (ob, ii->otr_type, true);
- lto_output_tree (ob, ii->thunk_delta, true);
}
}
@@ -2572,7 +2571,6 @@ ipa_read_indirect_edge_info (struct lto_input_block *ib,
{
ii->otr_token = (HOST_WIDE_INT) lto_input_sleb128 (ib);
ii->otr_type = lto_input_tree (ib, data_in);
- ii->thunk_delta = lto_input_tree (ib, data_in);
}
}
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 76597a0..96697e4 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -1605,6 +1605,18 @@ output_cgraph_opt_summary_p (struct cgraph_node *node)
|| node->clone.combined_args_to_skip);
}
+/* Output optimization summary for EDGE to OB. */
+static void
+output_edge_opt_summary (struct output_block *ob,
+ struct cgraph_edge *edge)
+{
+ if (edge->indirect_info)
+ lto_output_sleb128_stream (ob->main_stream,
+ edge->indirect_info->thunk_delta);
+ else
+ lto_output_sleb128_stream (ob->main_stream, 0);
+}
+
/* Output optimization summary for NODE to OB. */
static void
@@ -1616,6 +1628,7 @@ output_node_opt_summary (struct output_block *ob,
struct ipa_replace_map *map;
struct bitpack_d bp;
int i;
+ struct cgraph_edge *e;
lto_output_uleb128_stream (ob->main_stream,
bitmap_count_bits (node->clone.args_to_skip));
@@ -1646,6 +1659,10 @@ output_node_opt_summary (struct output_block *ob,
bp_pack_value (&bp, map->ref_p, 1);
lto_output_bitpack (&bp);
}
+ for (e = node->callees; e; e = e->next_callee)
+ output_edge_opt_summary (ob, e);
+ for (e = node->indirect_calls; e; e = e->next_callee)
+ output_edge_opt_summary (ob, e);
}
/* Output optimization summaries stored in callgraph.
@@ -1680,7 +1697,23 @@ output_cgraph_opt_summary (void)
destroy_output_block (ob);
}
-/* Input optimiation summary of NODE. */
+/* Input optimisation summary of EDGE. */
+
+static void
+input_edge_opt_summary (struct cgraph_edge *edge,
+ struct lto_input_block *ib_main)
+{
+ HOST_WIDE_INT thunk_delta;
+ thunk_delta = lto_input_sleb128 (ib_main);
+ if (thunk_delta != 0)
+ {
+ gcc_assert (!edge->indirect_info);
+ edge->indirect_info = cgraph_allocate_init_indirect_info ();
+ edge->indirect_info->thunk_delta = thunk_delta;
+ }
+}
+
+/* Input optimisation summary of NODE. */
static void
input_node_opt_summary (struct cgraph_node *node,
@@ -1691,6 +1724,7 @@ input_node_opt_summary (struct cgraph_node *node,
int count;
int bit;
struct bitpack_d bp;
+ struct cgraph_edge *e;
count = lto_input_uleb128 (ib_main);
if (count)
@@ -1726,6 +1760,10 @@ input_node_opt_summary (struct cgraph_node *node,
map->replace_p = bp_unpack_value (&bp, 1);
map->ref_p = bp_unpack_value (&bp, 1);
}
+ for (e = node->callees; e; e = e->next_callee)
+ input_edge_opt_summary (e, ib_main);
+ for (e = node->indirect_calls; e; e = e->next_callee)
+ input_edge_opt_summary (e, ib_main);
}
/* Read section in file FILE_DATA of length LEN with data DATA. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index df5ce01..86f8e3e 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-01-03 Martin Jambor <mjambor@suse.cz>
+
+ PR tree-optimization/46984
+ * g++.dg/ipa/pr46984.C: New test.
+
2011-01-02 Janus Weil <janus@gcc.gnu.org>
PR fortran/46408
diff --git a/gcc/testsuite/g++.dg/ipa/pr46984.C b/gcc/testsuite/g++.dg/ipa/pr46984.C
new file mode 100644
index 0000000..f7bb8409
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr46984.C
@@ -0,0 +1,62 @@
+// { dg-options "-O -fipa-cp -fno-early-inlining -flto" }
+// { dg-do run }
+
+extern "C" void abort ();
+
+class A
+{
+public:
+ virtual void foo () {abort();}
+};
+
+class B : public A
+{
+public:
+ int z;
+ virtual void foo () {abort();}
+};
+
+class C : public A
+{
+public:
+ void *a[32];
+ unsigned long b;
+ long c[32];
+
+ virtual void foo () {abort();}
+};
+
+class D : public C, public B
+{
+public:
+ D () : C(), B()
+ {
+ int i;
+ for (i = 0; i < 32; i++)
+ {
+ a[i] = (void *) 0;
+ c[i] = 0;
+ }
+ b = 0xaaaa;
+ }
+
+ virtual void foo ();
+};
+
+void D::foo()
+{
+ if (b != 0xaaaa)
+ abort();
+}
+
+static inline void bar (B &b)
+{
+ b.foo ();
+}
+
+int main()
+{
+ D d;
+ bar (d);
+ return 0;
+}