summaryrefslogtreecommitdiff
path: root/gcc/ipa-pure-const.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-22 11:40:18 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2009-10-22 11:40:18 +0000
commitef378c275d52d00d8ed044dc81ec9c48be2222e6 (patch)
tree0ab06e5072b8d0118d4bed1aa031422e8dd59204 /gcc/ipa-pure-const.c
parent8867b500961593ba73be72ea17bbbd4f8a2d74ef (diff)
downloadgcc-ef378c275d52d00d8ed044dc81ec9c48be2222e6.tar.gz
PR tree-optimize/40556
* ipa-reference.c (has_proper_scope_for_analysis): Add fixme about global vars. (check_call): Handle only indirect calls. (propagate_bits): Update comment. (write_node_summary_p): Turn bogus check to assert. (ipa_reference_write_summary): Stream calls_read_all properly. (ipa_reference_read_summary): Stream in calls_read_all properly. (read_write_all_from_decl): New function. (propagate): Handle OVERWRITABLE nodes and external calls here. * ipa-pre-const.c (check_call): In IPA mode handle indirect calls only. (analyze_function): Do not check visibility here. (add_new_function): We summary OVERWRITABLE too. (generate_summary): Stream OVERWRITABLE nodes too. (propagate): Handle external calls and OVERWRITABLE nodes here. (local_pure_const): Check visibility here. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@153450 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ipa-pure-const.c')
-rw-r--r--gcc/ipa-pure-const.c64
1 files changed, 40 insertions, 24 deletions
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index ea1d81ea5e2..e37af05d08e 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -330,12 +330,11 @@ check_call (funct_state local, gimple call, bool ipa)
/* When not in IPA mode, we can still handle self recursion. */
if (!ipa && callee_t == current_function_decl)
local->looping = true;
- /* The callee is either unknown (indirect call) or there is just no
- scannable code for it (external call) . We look to see if there
- are any bits available for the callee (such as by declaration or
- because it is builtin) and process solely on the basis of those
- bits. */
- else if (avail <= AVAIL_OVERWRITABLE || !ipa)
+ /* Either calle is unknown or we are doing local analysis.
+ Look to see if there are any bits available for the callee (such as by
+ declaration or because it is builtin) and process solely on the basis of
+ those bits. */
+ else if (!ipa || !callee_t)
{
if (possibly_throws && flag_non_call_exceptions)
{
@@ -492,13 +491,6 @@ analyze_function (struct cgraph_node *fn, bool ipa)
funct_state l;
basic_block this_block;
- if (cgraph_function_body_availability (fn) <= AVAIL_OVERWRITABLE)
- {
- if (dump_file)
- fprintf (dump_file, "Function is not available or overwrittable; not analyzing.\n");
- return NULL;
- }
-
l = XCNEW (struct funct_state_d);
l->pure_const_state = IPA_CONST;
l->state_previously_known = IPA_NEITHER;
@@ -609,7 +601,7 @@ end:
static void
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
{
- if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
+ if (cgraph_function_body_availability (node) < AVAIL_OVERWRITABLE)
return;
/* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once
@@ -686,12 +678,12 @@ generate_summary (void)
/* Process all of the functions.
- We do NOT process any AVAIL_OVERWRITABLE functions, we cannot
- guarantee that what we learn about the one we see will be true
- for the one that overrides it.
- */
+ We process AVAIL_OVERWRITABLE functions. We can not use the results
+ by default, but the info can be used at LTO with -fwhole-program or
+ when function got clonned and the clone is AVAILABLE. */
+
for (node = cgraph_nodes; node; node = node->next)
- if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
+ if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
set_function_state (node, analyze_function (node, true));
pointer_set_destroy (visited_nodes);
@@ -878,6 +870,12 @@ propagate (void)
if (w_l->looping)
looping = true;
+ if (cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE)
+ {
+ looping |= w_l->looping_previously_known;
+ if (pure_const_state < w_l->state_previously_known)
+ pure_const_state = w_l->state_previously_known;
+ }
if (pure_const_state == IPA_NEITHER)
break;
@@ -901,6 +899,20 @@ propagate (void)
if (y_l->looping)
looping = true;
}
+ else
+ {
+ int flags = flags_from_decl_or_type (y->decl);
+
+ if (flags & ECF_LOOPING_CONST_OR_PURE)
+ looping = true;
+ if (flags & ECF_CONST)
+ ;
+ else if ((flags & ECF_PURE) && pure_const_state == IPA_CONST)
+ pure_const_state = IPA_PURE;
+ else
+ pure_const_state = IPA_NEITHER, looping = true;
+
+ }
}
w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
@@ -988,7 +1000,8 @@ propagate (void)
struct cgraph_edge *e;
funct_state w_l = get_function_state (w);
- if (w_l->can_throw)
+ if (w_l->can_throw
+ || cgraph_function_body_availability (w) == AVAIL_OVERWRITABLE)
can_throw = true;
if (can_throw)
@@ -1008,6 +1021,8 @@ propagate (void)
&& e->can_throw_external)
can_throw = true;
}
+ else if (e->can_throw_external && !TREE_NOTHROW (y->decl))
+ can_throw = true;
}
w_info = (struct ipa_dfs_info *) w->aux;
w = w_info->next_cycle;
@@ -1046,7 +1061,7 @@ propagate (void)
free (node->aux);
node->aux = NULL;
}
- if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
+ if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
free (get_function_state (node));
}
@@ -1109,15 +1124,16 @@ local_pure_const (void)
fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
return 0;
}
-
- l = analyze_function (cgraph_node (current_function_decl), false);
- if (!l)
+ if (cgraph_function_body_availability (cgraph_node (current_function_decl))
+ <= AVAIL_OVERWRITABLE)
{
if (dump_file)
fprintf (dump_file, "Function has wrong visibility; ignoring\n");
return 0;
}
+ l = analyze_function (cgraph_node (current_function_decl), false);
+
switch (l->pure_const_state)
{
case IPA_CONST: