#include "timevar.h"
#include "diagnostic.h"
#include "langhooks.h"
+#include "data-streamer.h"
#include "lto-streamer.h"
-#include "toplev.h"
static void remove_node_data (struct cgraph_node *node,
void *data ATTRIBUTE_UNUSED);
bitmap statics_written;
};
-/* Information we save about every function after ipa-reference is completted. */
+/* Information we save about every function after ipa-reference is completed. */
struct ipa_reference_optimization_summary_d
{
{
ipa_reference_optimization_summary_t info;
- info = get_reference_optimization_summary (fn);
+ info = get_reference_optimization_summary (cgraph_function_node (fn, NULL));
if (info)
return info->statics_not_read;
+ else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
+ return all_module_statics;
else
return NULL;
}
info = get_reference_optimization_summary (fn);
if (info)
return info->statics_not_written;
+ else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
+ return all_module_statics;
else
return NULL;
}
struct cgraph_edge *e;
for (e = x->callees; e; e = e->next_callee)
{
- struct cgraph_node *y = e->callee;
+ enum availability avail;
+ struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
+ if (!y)
+ continue;
/* Only look into nodes we can propagate something. */
- if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
+ if (avail > AVAIL_OVERWRITABLE
+ || (avail == AVAIL_OVERWRITABLE
+ && (flags_from_decl_or_type (y->decl) & ECF_LEAF)))
{
- int flags = flags_from_decl_or_type (e->callee->decl);
+ int flags = flags_from_decl_or_type (y->decl);
if (get_reference_vars_info (y))
{
ipa_reference_vars_info_t y_info
bitmap_set_bit (local->statics_read, DECL_UID (var));
break;
case IPA_REF_STORE:
+ if (ipa_ref_cannot_lead_to_return (ref))
+ break;
bitmap_set_bit (local->statics_written, DECL_UID (var));
break;
case IPA_REF_ADDR:
{
tree decl = node->decl;
int flags = flags_from_decl_or_type (decl);
- if (flags & ECF_CONST)
+ if ((flags & ECF_LEAF)
+ && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
+ ;
+ else if (flags & ECF_CONST)
;
else if ((flags & ECF_PURE)
|| cgraph_node_cannot_return (node))
- *read_all = true;
+ {
+ *read_all = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " %s/%i -> read all\n",
+ cgraph_node_name (node), node->uid);
+ }
else
{
/* TODO: To be able to produce sane results, we should also handle
common builtins, in particular throw. */
*read_all = true;
*write_all = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " %s/%i -> read all, write all\n",
+ cgraph_node_name (node), node->uid);
}
}
struct cgraph_node *w;
struct cgraph_node **order =
XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
- int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
+ int order_pos;
int i;
if (dump_file)
the global information. All the nodes within a cycle will have
the same info so we collapse cycles first. Then we can do the
propagation in one pass from the leaves to the roots. */
- order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
+ order_pos = ipa_reduced_postorder (order, true, true, NULL);
if (dump_file)
- ipa_utils_print_order(dump_file, "reduced", order, order_pos);
+ ipa_print_order (dump_file, "reduced", order, order_pos);
for (i = 0; i < order_pos; i++ )
{
struct ipa_dfs_info * w_info;
node = order[i];
+ if (node->alias)
+ continue;
node_info = get_reference_vars_info (node);
gcc_assert (node_info);
+
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Starting cycle with %s/%i\n",
+ cgraph_node_name (node), node->uid);
+
node_l = &node_info->local;
node_g = &node_info->global;
read_all = false;
write_all = false;
- /* When function is overwrittable, we can not assume anything. */
+ /* When function is overwritable, we can not assume anything. */
if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
read_write_all_from_decl (node, &read_all, &write_all);
for (e = node->callees; e; e = e->next_callee)
- if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
- read_write_all_from_decl (e->callee, &read_all, &write_all);
+ {
+ enum availability avail;
+ struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
+ if (!callee || avail <= AVAIL_OVERWRITABLE)
+ read_write_all_from_decl (callee, &read_all, &write_all);
+ }
for (ie = node->indirect_calls; ie; ie = ie->next_callee)
if (!(ie->indirect_info->ecf_flags & ECF_CONST))
{
read_all = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " indirect call -> read all\n");
if (!cgraph_edge_cannot_lead_to_return (ie)
&& !(ie->indirect_info->ecf_flags & ECF_PURE))
- write_all = true;
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " indirect call -> write all\n");
+ write_all = true;
+ }
}
w = w_info->next_cycle;
while (w && (!read_all || !write_all))
{
- /* When function is overwrittable, we can not assume anything. */
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Visiting %s/%i\n",
+ cgraph_node_name (w), w->uid);
+ /* When function is overwritable, we can not assume anything. */
if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
read_write_all_from_decl (w, &read_all, &write_all);
for (e = w->callees; e; e = e->next_callee)
- if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
- read_write_all_from_decl (e->callee, &read_all, &write_all);
+ {
+ enum availability avail;
+ struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
+
+ if (avail <= AVAIL_OVERWRITABLE)
+ read_write_all_from_decl (callee, &read_all, &write_all);
+ }
for (ie = w->indirect_calls; ie; ie = ie->next_callee)
if (!(ie->indirect_info->ecf_flags & ECF_CONST))
{
read_all = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " indirect call -> read all\n");
if (!cgraph_edge_cannot_lead_to_return (ie)
&& !(ie->indirect_info->ecf_flags & ECF_PURE))
- write_all = true;
+ {
+ write_all = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " indirect call -> write all\n");
+ }
}
w_info = (struct ipa_dfs_info *) w->aux;
struct ipa_dfs_info * w_info;
node = order[i];
+ if (node->alias)
+ continue;
node_info = get_reference_vars_info (node);
node_g = &node_info->global;
node_l = &node_info->local;
ipa_reference_global_vars_info_t node_g;
ipa_reference_optimization_summary_t opt;
- if (!node->analyzed)
+ if (!node->analyzed || node->alias)
continue;
node_info = get_reference_vars_info (node);
- if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
+ if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
+ || (flags_from_decl_or_type (node->decl) & ECF_LEAF))
{
node_g = &node_info->global;
node_g->statics_written);
}
}
- if (node_info)
- free (node_info);
- if (node->aux)
- {
- free (node->aux);
- node->aux = NULL;
- }
+ free (node_info);
}
+ ipa_free_postorder_info ();
free (order);
bitmap_obstack_release (&local_info_obstack);
bitmap_iterator bi;
if (bits == all_module_statics)
{
- lto_output_sleb128_stream (ob->main_stream, -1);
+ streamer_write_hwi_stream (ob->main_stream, -1);
return;
}
EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
count ++;
if (count == ltrans_statics_bitcount)
{
- lto_output_sleb128_stream (ob->main_stream, -1);
+ streamer_write_hwi_stream (ob->main_stream, -1);
return;
}
- lto_output_sleb128_stream (ob->main_stream, count);
+ streamer_write_hwi_stream (ob->main_stream, count);
if (!count)
return;
EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
set, vset, ltrans_statics))
count++;
- lto_output_uleb128_stream (ob->main_stream, count);
+ streamer_write_uhwi_stream (ob->main_stream, count);
if (count)
stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
-1);
info = get_reference_optimization_summary (node);
node_ref = lto_cgraph_encoder_encode (encoder, node);
- lto_output_uleb128_stream (ob->main_stream, node_ref);
+ streamer_write_uhwi_stream (ob->main_stream, node_ref);
stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
ltrans_statics_bitcount);
if (ib)
{
unsigned int i;
- unsigned int f_count = lto_input_uleb128 (ib);
+ unsigned int f_count = streamer_read_uhwi (ib);
int b_count;
if (!f_count)
continue;
- b_count = lto_input_sleb128 (ib);
+ b_count = streamer_read_hwi (ib);
if (dump_file)
fprintf (dump_file, "all module statics:");
for (i = 0; i < (unsigned int)b_count; i++)
{
- unsigned int var_index = lto_input_uleb128 (ib);
+ unsigned int var_index = streamer_read_uhwi (ib);
tree v_decl = lto_file_decl_data_get_var_decl (file_data,
var_index);
bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
int v_count;
lto_cgraph_encoder_t encoder;
- index = lto_input_uleb128 (ib);
+ index = streamer_read_uhwi (ib);
encoder = file_data->cgraph_node_encoder;
node = lto_cgraph_encoder_deref (encoder, index);
info = XCNEW (struct ipa_reference_optimization_summary_d);
cgraph_node_name (node), node->uid);
/* Set the statics not read. */
- v_count = lto_input_sleb128 (ib);
+ v_count = streamer_read_hwi (ib);
if (v_count == -1)
{
info->statics_not_read = all_module_statics;
else
for (j = 0; j < (unsigned int)v_count; j++)
{
- unsigned int var_index = lto_input_uleb128 (ib);
+ unsigned int var_index = streamer_read_uhwi (ib);
tree v_decl = lto_file_decl_data_get_var_decl (file_data,
var_index);
bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
fprintf (dump_file,
"\n static not written:");
/* Set the statics not written. */
- v_count = lto_input_sleb128 (ib);
+ v_count = streamer_read_hwi (ib);
if (v_count == -1)
{
info->statics_not_written = all_module_statics;
else
for (j = 0; j < (unsigned int)v_count; j++)
{
- unsigned int var_index = lto_input_uleb128 (ib);
+ unsigned int var_index = streamer_read_uhwi (ib);
tree v_decl = lto_file_decl_data_get_var_decl (file_data,
var_index);
bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));