summaryrefslogtreecommitdiff
path: root/gcc/ipa-reference.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-24 19:14:51 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2010-09-24 19:14:51 +0000
commit7bd95dfd984faaeb4d64ee3f044de98c10cba066 (patch)
tree3586ff30f00807c4e59b1bf02ac5e21a1cdad147 /gcc/ipa-reference.c
parent01c8b828d8905a7565b1cc7803f0ef960a0b4f95 (diff)
downloadgcc-7bd95dfd984faaeb4d64ee3f044de98c10cba066.tar.gz
* doc/extend.texi: (attribute leaf): Document.
* tree.c (local_define_builtin): Handle ECF_LEAF. (build_common_builtin_nodes): Set ECF_LEAF where needed. * tree.h (ECF_LEAF): New. * ipa-reference.c (propagate_bits): For leaf calls propagate ever overwrittable and unavailable functions. (ipa_init): Put all_module_statics into optimization_summary_obstack. (copy_global_bitmap): Do not copy all_module_statics. (read_write_all_from_decl): Use cgraph_node argument; handle ECF_LEAF. (propagate): Handle overwritable and unavailable leaf functions; initialize global info for overwritable and unavailable leaf functions; do not free all module statics. (ipa_reference_get_not_read_global, ipa_reference_get_not_written_global): leaf calls don't clobber local statics. * calls.c (flags_from_decl_or_type): Handle leaf. * tree-cfg.c (stmt_can_make_abnormal_goto): Leaf functions can't do abnormal gotos. * c-common.c (handle_leaf_attribute): New function. (struct attribute_spec c_common_att): Add leaf. * gcc.dg/tree-ssa/leaf.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164606 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-reference.c')
-rw-r--r--gcc/ipa-reference.c52
1 files changed, 46 insertions, 6 deletions
diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c
index 64ccb4ead27..96482f12826 100644
--- a/gcc/ipa-reference.c
+++ b/gcc/ipa-reference.c
@@ -200,6 +200,8 @@ ipa_reference_get_not_read_global (struct cgraph_node *fn)
info = get_reference_optimization_summary (fn);
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;
}
@@ -217,6 +219,8 @@ ipa_reference_get_not_written_global (struct cgraph_node *fn)
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;
}
@@ -299,9 +303,13 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x
for (e = x->callees; e; e = e->next_callee)
{
struct cgraph_node *y = e->callee;
+ enum availability avail;
+ avail = cgraph_function_body_availability (e->callee);
/* 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 (e->callee->decl) & ECF_LEAF)))
{
int flags = flags_from_decl_or_type (e->callee->decl);
if (get_reference_vars_info (y))
@@ -573,17 +581,28 @@ read_write_all_from_decl (struct cgraph_node *node, bool * read_all,
{
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);
}
}
@@ -629,6 +648,11 @@ propagate (void)
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;
@@ -647,9 +671,15 @@ propagate (void)
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;
+ }
}
@@ -659,6 +689,9 @@ propagate (void)
w = w_info->next_cycle;
while (w && (!read_all || !write_all))
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, " Visiting %s/%i\n",
+ cgraph_node_name (w), w->uid);
/* When function is overwrittable, we can not assume anything. */
if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
read_write_all_from_decl (w, &read_all, &write_all);
@@ -671,9 +704,15 @@ propagate (void)
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;
@@ -841,7 +880,8 @@ propagate (void)
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;