Commit ce47fda3 by Martin Jambor Committed by Martin Jambor

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
parent fd0bcb5a
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> 2011-01-02 H.J. Lu <hongjiu.lu@intel.com>
PR driver/47137 PR driver/47137
......
...@@ -860,7 +860,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt) ...@@ -860,7 +860,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt)
indirect call into a direct one. */ indirect call into a direct one. */
struct cgraph_node *new_callee = cgraph_node (decl); 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)); push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl));
...@@ -1070,6 +1070,17 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee, ...@@ -1070,6 +1070,17 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee,
return edge; 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 /* Create an indirect edge with a yet-undetermined callee where the call
statement destination is a formal parameter of the caller with index 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, ...@@ -1086,8 +1097,7 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt,
edge->indirect_unknown_callee = 1; edge->indirect_unknown_callee = 1;
initialize_inline_failed (edge); initialize_inline_failed (edge);
edge->indirect_info = ggc_alloc_cleared_cgraph_indirect_call_info (); edge->indirect_info = cgraph_allocate_init_indirect_info ();
edge->indirect_info->param_index = -1;
edge->indirect_info->ecf_flags = ecf_flags; edge->indirect_info->ecf_flags = ecf_flags;
edge->next_callee = caller->indirect_calls; edge->next_callee = caller->indirect_calls;
...@@ -1195,12 +1205,12 @@ cgraph_redirect_edge_callee (struct cgraph_edge *e, struct cgraph_node *n) ...@@ -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 /* 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 CALLEE. DELTA is an integer constant that is to be added to the this
the this pointer (first parameter). */ pointer (first parameter) to compensate for skipping a thunk adjustment. */
void void
cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee, 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_unknown_callee = 0;
edge->indirect_info->thunk_delta = delta; edge->indirect_info->thunk_delta = delta;
......
...@@ -386,11 +386,11 @@ struct GTY(()) cgraph_indirect_call_info ...@@ -386,11 +386,11 @@ struct GTY(()) cgraph_indirect_call_info
HOST_WIDE_INT anc_offset; HOST_WIDE_INT anc_offset;
/* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */ /* OBJ_TYPE_REF_TOKEN of a polymorphic call (if polymorphic is set). */
HOST_WIDE_INT otr_token; 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. */ /* Type of the object from OBJ_TYPE_REF_OBJECT. */
tree otr_type; 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. */ /* Index of the parameter that is called. */
int param_index; int param_index;
/* ECF flags determined from the caller. */ /* ECF flags determined from the caller. */
...@@ -549,8 +549,9 @@ void cgraph_node_remove_callees (struct cgraph_node *node); ...@@ -549,8 +549,9 @@ void cgraph_node_remove_callees (struct cgraph_node *node);
struct cgraph_edge *cgraph_create_edge (struct cgraph_node *, struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
struct cgraph_node *, struct cgraph_node *,
gimple, gcov_type, int, int); gimple, gcov_type, int, int);
struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple, int, struct cgraph_edge *cgraph_create_indirect_edge (struct cgraph_node *, gimple,
gcov_type, int, int); 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 (const_tree);
struct cgraph_node * cgraph_get_node_or_alias (const_tree); struct cgraph_node * cgraph_get_node_or_alias (const_tree);
struct cgraph_node * cgraph_node (tree); struct cgraph_node * cgraph_node (tree);
...@@ -578,7 +579,8 @@ struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type, i ...@@ -578,7 +579,8 @@ struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type, i
int, bool, VEC(cgraph_edge_p,heap) *); int, bool, VEC(cgraph_edge_p,heap) *);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *); 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); struct cgraph_asm_node *cgraph_add_asm_node (tree);
......
...@@ -2168,22 +2168,20 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) ...@@ -2168,22 +2168,20 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e)
} }
} }
if (e->indirect_info && e->indirect_info->thunk_delta if (e->indirect_info &&
&& integer_nonzerop (e->indirect_info->thunk_delta) e->indirect_info->thunk_delta != 0
&& (!e->callee->clone.combined_args_to_skip && (!e->callee->clone.combined_args_to_skip
|| !bitmap_bit_p (e->callee->clone.combined_args_to_skip, 0))) || !bitmap_bit_p (e->callee->clone.combined_args_to_skip, 0)))
{ {
if (cgraph_dump_file) if (cgraph_dump_file)
{ fprintf (cgraph_dump_file, " Thunk delta is "
fprintf (cgraph_dump_file, " Thunk delta is "); HOST_WIDE_INT_PRINT_DEC "\n", e->indirect_info->thunk_delta);
print_generic_expr (cgraph_dump_file,
e->indirect_info->thunk_delta, 0);
fprintf (cgraph_dump_file, "\n");
}
gsi = gsi_for_stmt (e->call_stmt); gsi = gsi_for_stmt (e->call_stmt);
gsi_computed = true; gsi_computed = true;
gimple_adjust_this_by_delta (&gsi, e->indirect_info->thunk_delta); gimple_adjust_this_by_delta (&gsi,
e->indirect_info->thunk_delta = NULL_TREE; build_int_cst (sizetype,
e->indirect_info->thunk_delta));
e->indirect_info->thunk_delta = 0;
} }
if (e->callee->clone.combined_args_to_skip) if (e->callee->clone.combined_args_to_skip)
......
...@@ -1483,7 +1483,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta) ...@@ -1483,7 +1483,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target, tree delta)
return NULL; return NULL;
ipa_check_create_node_params (); 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) if (dump_file)
{ {
fprintf (dump_file, "ipa-prop: Discovered %s call to a known target " 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, ...@@ -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_sleb128_stream (ob->main_stream, ii->otr_token);
lto_output_tree (ob, ii->otr_type, true); 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, ...@@ -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_token = (HOST_WIDE_INT) lto_input_sleb128 (ib);
ii->otr_type = lto_input_tree (ib, data_in); ii->otr_type = lto_input_tree (ib, data_in);
ii->thunk_delta = lto_input_tree (ib, data_in);
} }
} }
......
...@@ -1605,6 +1605,18 @@ output_cgraph_opt_summary_p (struct cgraph_node *node) ...@@ -1605,6 +1605,18 @@ output_cgraph_opt_summary_p (struct cgraph_node *node)
|| node->clone.combined_args_to_skip); || 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. */ /* Output optimization summary for NODE to OB. */
static void static void
...@@ -1616,6 +1628,7 @@ output_node_opt_summary (struct output_block *ob, ...@@ -1616,6 +1628,7 @@ output_node_opt_summary (struct output_block *ob,
struct ipa_replace_map *map; struct ipa_replace_map *map;
struct bitpack_d bp; struct bitpack_d bp;
int i; int i;
struct cgraph_edge *e;
lto_output_uleb128_stream (ob->main_stream, lto_output_uleb128_stream (ob->main_stream,
bitmap_count_bits (node->clone.args_to_skip)); bitmap_count_bits (node->clone.args_to_skip));
...@@ -1646,6 +1659,10 @@ output_node_opt_summary (struct output_block *ob, ...@@ -1646,6 +1659,10 @@ output_node_opt_summary (struct output_block *ob,
bp_pack_value (&bp, map->ref_p, 1); bp_pack_value (&bp, map->ref_p, 1);
lto_output_bitpack (&bp); 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. /* Output optimization summaries stored in callgraph.
...@@ -1680,7 +1697,23 @@ output_cgraph_opt_summary (void) ...@@ -1680,7 +1697,23 @@ output_cgraph_opt_summary (void)
destroy_output_block (ob); 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 static void
input_node_opt_summary (struct cgraph_node *node, input_node_opt_summary (struct cgraph_node *node,
...@@ -1691,6 +1724,7 @@ input_node_opt_summary (struct cgraph_node *node, ...@@ -1691,6 +1724,7 @@ input_node_opt_summary (struct cgraph_node *node,
int count; int count;
int bit; int bit;
struct bitpack_d bp; struct bitpack_d bp;
struct cgraph_edge *e;
count = lto_input_uleb128 (ib_main); count = lto_input_uleb128 (ib_main);
if (count) if (count)
...@@ -1726,6 +1760,10 @@ input_node_opt_summary (struct cgraph_node *node, ...@@ -1726,6 +1760,10 @@ input_node_opt_summary (struct cgraph_node *node,
map->replace_p = bp_unpack_value (&bp, 1); map->replace_p = bp_unpack_value (&bp, 1);
map->ref_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. */ /* Read section in file FILE_DATA of length LEN with data DATA. */
......
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> 2011-01-02 Janus Weil <janus@gcc.gnu.org>
PR fortran/46408 PR fortran/46408
......
// { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment