diff options
author | Martin Jambor <mjambor@suse.cz> | 2011-01-03 14:06:54 +0100 |
---|---|---|
committer | Martin Jambor <jamborm@gcc.gnu.org> | 2011-01-03 14:06:54 +0100 |
commit | ce47fda3ce6adfe86f725930dedbfb1f775ddd45 (patch) | |
tree | a0198b9cc6e29df5e3c9c571f5a99db84117cc75 /gcc | |
parent | fd0bcb5af982e58e40c5fad1eb0d1a54316b2807 (diff) | |
download | gcc-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/ChangeLog | 23 | ||||
-rw-r--r-- | gcc/cgraph.c | 22 | ||||
-rw-r--r-- | gcc/cgraph.h | 14 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 18 | ||||
-rw-r--r-- | gcc/ipa-prop.c | 4 | ||||
-rw-r--r-- | gcc/lto-cgraph.c | 40 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/pr46984.C | 62 |
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; +} |