cgraph.c (cgraph_get_body): Update call of lto_input_function_body.

* cgraph.c (cgraph_get_body): Update call of lto_input_function_body.
	* gimple-streamer-in.c (input_gimple_stmt): Move sanity check to ...
	* ipa-utils.c: Include lto-streamer.h, ipa-inline.h
	(ipa_merge_profiles): New function.
	* lto-streamer-in.c (lto_read_body): Take node instead of fn_decl.
	(lto_input_function_body): Likewise.

From-SVN: r202130
This commit is contained in:
Jan Hubicka 2013-08-31 15:44:46 +02:00 committed by Jan Hubicka
parent 57292ce9bd
commit 4843f03206
5 changed files with 189 additions and 10 deletions

View File

@ -1,3 +1,12 @@
2013-08-31 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_get_body): Update call of lto_input_function_body.
* gimple-streamer-in.c (input_gimple_stmt): Move sanity check to ...
* ipa-utils.c: Include lto-streamer.h, ipa-inline.h
(ipa_merge_profiles): New function.
* lto-streamer-in.c (lto_read_body): Take node instead of fn_decl.
(lto_input_function_body): Likewise.
2013-08-31 Jan Hubicka <jh@suse.cz>
* cgraph.c (cgraph_speculative_call_info): Fix ref lookup

View File

@ -3111,7 +3111,7 @@ cgraph_get_body (struct cgraph_node *node)
gcc_assert (DECL_STRUCT_FUNCTION (decl) == NULL);
lto_input_function_body (file_data, node->symbol.decl, data);
lto_input_function_body (file_data, node, data);
lto_stats.num_function_bodies++;
lto_free_section_data (file_data, LTO_section_function_body, name,
data, len);

View File

@ -282,9 +282,6 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
if (lhs && TREE_CODE (lhs) == SSA_NAME)
SSA_NAME_DEF_STMT (lhs) = stmt;
}
else if (code == GIMPLE_LABEL)
gcc_assert (emit_label_in_global_context_p (gimple_label_label (stmt))
|| DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl);
else if (code == GIMPLE_ASM)
{
unsigned i;

View File

@ -37,6 +37,8 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "diagnostic.h"
#include "langhooks.h"
#include "lto-streamer.h"
#include "ipa-inline.h"
/* Debugging function for postorder and inorder code. NOTE is a string
that is printed before the nodes are printed. ORDER is an array of
@ -618,3 +620,174 @@ debug_varpool_node_set (varpool_node_set set)
{
dump_varpool_node_set (stderr, set);
}
/* SRC and DST are going to be merged. Take SRC's profile and merge it into
DST so it is not going to be lost. Destroy SRC's body on the way. */
void
ipa_merge_profiles (struct cgraph_node *dst,
struct cgraph_node *src)
{
tree oldsrcdecl = src->symbol.decl;
struct function *srccfun, *dstcfun;
bool match = true;
if (!src->symbol.definition
|| !dst->symbol.definition)
return;
if (src->frequency < dst->frequency)
src->frequency = dst->frequency;
if (!dst->count)
return;
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Merging profiles of %s/%i to %s/%i\n",
xstrdup (cgraph_node_name (src)), src->symbol.order,
xstrdup (cgraph_node_name (dst)), dst->symbol.order);
}
dst->count += src->count;
/* This is ugly. We need to get both function bodies into memory.
If declaration is merged, we need to duplicate it to be able
to load body that is being replaced. This makes symbol table
temporarily inconsistent. */
if (src->symbol.decl == dst->symbol.decl)
{
void **slot;
struct lto_in_decl_state temp;
struct lto_in_decl_state *state;
/* We are going to move the decl, we want to remove its file decl data.
and link these with the new decl. */
temp.fn_decl = src->symbol.decl;
slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states,
&temp, NO_INSERT);
state = (lto_in_decl_state *)*slot;
htab_clear_slot (src->symbol.lto_file_data->function_decl_states, slot);
gcc_assert (state);
/* Duplicate the decl and be sure it does not link into body of DST. */
src->symbol.decl = copy_node (src->symbol.decl);
DECL_STRUCT_FUNCTION (src->symbol.decl) = NULL;
DECL_ARGUMENTS (src->symbol.decl) = NULL;
DECL_INITIAL (src->symbol.decl) = NULL;
DECL_RESULT (src->symbol.decl) = NULL;
/* Associate the decl state with new declaration, so LTO streamer
can look it up. */
state->fn_decl = src->symbol.decl;
slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states,
state, INSERT);
gcc_assert (!*slot);
*slot = state;
}
cgraph_get_body (src);
cgraph_get_body (dst);
srccfun = DECL_STRUCT_FUNCTION (src->symbol.decl);
dstcfun = DECL_STRUCT_FUNCTION (dst->symbol.decl);
if (n_basic_blocks_for_function (srccfun)
!= n_basic_blocks_for_function (dstcfun))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"Giving up; number of basic block mismatch.\n");
match = false;
}
else if (last_basic_block_for_function (srccfun)
!= last_basic_block_for_function (dstcfun))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"Giving up; last block mismatch.\n");
match = false;
}
else
{
basic_block srcbb, dstbb;
FOR_ALL_BB_FN (srcbb, srccfun)
{
unsigned int i;
dstbb = BASIC_BLOCK_FOR_FUNCTION (dstcfun, srcbb->index);
if (dstbb == NULL)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"No matching block for bb %i.\n",
srcbb->index);
match = false;
break;
}
if (EDGE_COUNT (srcbb->succs) != EDGE_COUNT (dstbb->succs))
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"Edge count mistmatch for bb %i.\n",
srcbb->index);
match = false;
break;
}
for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
{
edge srce = EDGE_SUCC (srcbb, i);
edge dste = EDGE_SUCC (dstbb, i);
if (srce->dest->index != dste->dest->index)
{
if (cgraph_dump_file)
fprintf (cgraph_dump_file,
"Succ edge mistmatch for bb %i.\n",
srce->dest->index);
match = false;
break;
}
}
}
}
if (match)
{
struct cgraph_edge *e;
basic_block srcbb, dstbb;
/* TODO: merge also statement histograms. */
FOR_ALL_BB_FN (srcbb, srccfun)
{
unsigned int i;
dstbb = BASIC_BLOCK_FOR_FUNCTION (dstcfun, srcbb->index);
dstbb->count += srcbb->count;
for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
{
edge srce = EDGE_SUCC (srcbb, i);
edge dste = EDGE_SUCC (dstbb, i);
dste->count += srce->count;
}
}
push_cfun (dstcfun);
counts_to_freqs ();
compute_function_frequency ();
pop_cfun ();
for (e = dst->callees; e; e = e->next_callee)
{
gcc_assert (!e->speculative);
e->count = gimple_bb (e->call_stmt)->count;
e->frequency = compute_call_stmt_bb_frequency
(dst->symbol.decl,
gimple_bb (e->call_stmt));
}
for (e = dst->indirect_calls; e; e = e->next_callee)
{
gcc_assert (!e->speculative);
e->count = gimple_bb (e->call_stmt)->count;
e->frequency = compute_call_stmt_bb_frequency
(dst->symbol.decl,
gimple_bb (e->call_stmt));
}
cgraph_release_function_body (src);
inline_update_overall_summary (dst);
}
/* TODO: if there is no match, we can scale up. */
src->symbol.decl = oldsrcdecl;
}

View File

@ -1001,14 +1001,14 @@ input_function (tree fn_decl, struct data_in *data_in,
}
/* Read the body from DATA for function FN_DECL and fill it in.
/* Read the body from DATA for function NODE and fill it in.
FILE_DATA are the global decls and types. SECTION_TYPE is either
LTO_section_function_body or LTO_section_static_initializer. If
section type is LTO_section_function_body, FN must be the decl for
that function. */
static void
lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node,
const char *data, enum lto_section_type section_type)
{
const struct lto_function_header *header;
@ -1018,6 +1018,7 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
int string_offset;
struct lto_input_block ib_cfg;
struct lto_input_block ib_main;
tree fn_decl = node->symbol.decl;
header = (const struct lto_function_header *) data;
cfg_offset = sizeof (struct lto_function_header);
@ -1044,7 +1045,6 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
if (section_type == LTO_section_function_body)
{
struct lto_in_decl_state *decl_state;
struct cgraph_node *node = cgraph_get_node (fn_decl);
unsigned from;
gcc_checking_assert (node);
@ -1094,14 +1094,14 @@ lto_read_body (struct lto_file_decl_data *file_data, tree fn_decl,
}
/* Read the body of FN_DECL using DATA. FILE_DATA holds the global
/* Read the body of NODE using DATA. FILE_DATA holds the global
decls and types. */
void
lto_input_function_body (struct lto_file_decl_data *file_data,
tree fn_decl, const char *data)
struct cgraph_node *node, const char *data)
{
lto_read_body (file_data, fn_decl, data, LTO_section_function_body);
lto_read_body (file_data, node, data, LTO_section_function_body);
}