From 6b715bf6d991249181ce532442fa5513e137f708 Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Wed, 4 May 2016 18:36:51 +0200 Subject: [PATCH] cgraph.c (cgraph_node::call_for_symbol_thunks_and_aliases): Check availability on NODE, too. * cgraph.c (cgraph_node::call_for_symbol_thunks_and_aliases): Check availability on NODE, too. * cgraph.h (symtab_node::call_for_symbol_and_aliases): Likewise. (cgraph_node::call_for_symbol_and_aliases): Likewise. (varpool_node::call_for_symbol_and_aliase): Likewise. * ipa-pure-const.c (add_new_function): Analyze all bodies. (propagate_pure_const): Propagate across interposable functions, too. (skip_function_for_local_pure_const): Do not skip interposable bodies with aliases. (pass_local_pure_const::execute): Update. * gcc.dg/ipa/pure-const-3.c: New testcase. From-SVN: r235887 --- gcc/ChangeLog | 13 +++ gcc/cgraph.c | 13 ++- gcc/cgraph.h | 31 ++++--- gcc/ipa-pure-const.c | 102 ++++++++++++------------ gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.dg/ipa/pure-const-3.c | 24 ++++++ 6 files changed, 123 insertions(+), 64 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/ipa/pure-const-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 17390ab7471..d3d54ec82a5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2016-05-04 Jan Hubicka + + * cgraph.c (cgraph_node::call_for_symbol_thunks_and_aliases): + Check availability on NODE, too. + * cgraph.h (symtab_node::call_for_symbol_and_aliases): Likewise. + (cgraph_node::call_for_symbol_and_aliases): Likewise. + (varpool_node::call_for_symbol_and_aliase): Likewise. + * ipa-pure-const.c (add_new_function): Analyze all bodies. + (propagate_pure_const): Propagate across interposable functions, too. + (skip_function_for_local_pure_const): Do not skip interposable bodies + with aliases. + (pass_local_pure_const::execute): Update. + 2016-05-04 Marek Polacek * doc/invoke.texi: Document -Wdangling-else. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 782cb520eac..0c6ff93d625 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2289,7 +2289,7 @@ cgraph_node::can_be_local_p (void) } /* Call callback on cgraph_node, thunks and aliases associated to cgraph_node. - When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are + When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are skipped. */ bool @@ -2301,9 +2301,14 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback) { cgraph_edge *e; ipa_ref *ref; + enum availability avail = AVAIL_AVAILABLE; - if (callback (this, data)) - return true; + if (include_overwritable + || (avail = get_availability ()) > AVAIL_INTERPOSABLE) + { + if (callback (this, data)) + return true; + } FOR_EACH_ALIAS (this, ref) { cgraph_node *alias = dyn_cast (ref->referring); @@ -2314,7 +2319,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback) exclude_virtual_thunks)) return true; } - if (get_availability () <= AVAIL_INTERPOSABLE) + if (avail <= AVAIL_INTERPOSABLE) return false; for (e = callers; e; e = e->next_caller) if (e->caller->thunk.thunk_p diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 5ce032e1e57..d714ad75189 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -3096,8 +3096,7 @@ symtab_node::get_availability (symtab_node *ref) } /* Call calback on symtab node and aliases associated to this node. - When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are - skipped. */ + When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */ inline bool symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *, @@ -3105,15 +3104,19 @@ symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *, void *data, bool include_overwritable) { - if (callback (this, data)) - return true; + if (include_overwritable + || get_availability () > AVAIL_INTERPOSABLE) + { + if (callback (this, data)) + return true; + } if (has_aliases_p ()) return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return false; } /* Call callback on function and aliases associated to the function. - When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are + When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */ inline bool @@ -3122,15 +3125,19 @@ cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *, void *data, bool include_overwritable) { - if (callback (this, data)) - return true; + if (include_overwritable + || get_availability () > AVAIL_INTERPOSABLE) + { + if (callback (this, data)) + return true; + } if (has_aliases_p ()) return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return false; } /* Call calback on varpool symbol and aliases associated to varpool symbol. - When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are + When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */ inline bool @@ -3139,8 +3146,12 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *data, bool include_overwritable) { - if (callback (this, data)) - return true; + if (include_overwritable + || get_availability () > AVAIL_INTERPOSABLE) + { + if (callback (this, data)) + return true; + } if (has_aliases_p ()) return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return false; diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 63fbf581c71..ba76275a696 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -927,8 +927,6 @@ end: static void add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { - if (node->get_availability () < AVAIL_INTERPOSABLE) - return; /* There are some shared nodes, in particular the initializers on static declarations. We do not need to scan them more than once since all we would be interested in are the addressof @@ -1222,6 +1220,7 @@ propagate_pure_const (void) int i; struct ipa_dfs_info * w_info; bool remove_p = false; + bool has_cdtor; order_pos = ipa_reduced_postorder (order, true, false, ignore_edge_for_pure_const); @@ -1274,26 +1273,6 @@ propagate_pure_const (void) if (pure_const_state == IPA_NEITHER) break; - /* For interposable nodes we can not assume anything. - FIXME: It should be safe to remove this conditional and allow - interposable functions with non-interposable aliases next - stage 1. */ - if (w->get_availability () == AVAIL_INTERPOSABLE) - { - worse_state (&pure_const_state, &looping, - w_l->state_previously_known, - w_l->looping_previously_known, - NULL, NULL); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, - " Interposable. state %s looping %i\n", - pure_const_names[w_l->state_previously_known], - w_l->looping_previously_known); - } - break; - } - count++; /* We consider recursive cycles as possibly infinite. @@ -1506,9 +1485,22 @@ propagate_pure_const (void) this_looping ? "looping " : "", w->name ()); } - remove_p |= w->call_for_symbol_and_aliases (cdtor_p, - NULL, true); - w->set_const_flag (true, this_looping); + /* Turning constructor or destructor to non-looping const/pure + enables us to possibly remove the function completely. */ + if (this_looping) + has_cdtor = false; + else + has_cdtor = w->call_for_symbol_and_aliases (cdtor_p, + NULL, true); + if (w->set_const_flag (true, this_looping)) + { + if (dump_file) + fprintf (dump_file, + "Declaration updated to be %sconst: %s\n", + this_looping ? "looping " : "", + w->name ()); + remove_p |= has_cdtor; + } break; case IPA_PURE: @@ -1520,9 +1512,20 @@ propagate_pure_const (void) this_looping ? "looping " : "", w->name ()); } - remove_p |= w->call_for_symbol_and_aliases (cdtor_p, - NULL, true); - w->set_pure_flag (true, this_looping); + if (this_looping) + has_cdtor = false; + else + has_cdtor = w->call_for_symbol_and_aliases (cdtor_p, + NULL, true); + if (w->set_pure_flag (true, this_looping)) + { + if (dump_file) + fprintf (dump_file, + "Declaration updated to be %spure: %s\n", + this_looping ? "looping " : "", + w->name ()); + remove_p |= has_cdtor; + } break; default: @@ -1723,11 +1726,14 @@ skip_function_for_local_pure_const (struct cgraph_node *node) fprintf (dump_file, "Function called in recursive cycle; ignoring\n"); return true; } - if (node->get_availability () <= AVAIL_INTERPOSABLE) + /* Save some work and do not analyze functions which are interposable and + do not have any non-interposable aliases. */ + if (node->get_availability () <= AVAIL_INTERPOSABLE + && !node->has_aliases_p ()) { if (dump_file) fprintf (dump_file, - "Function is not available or interposable; not analyzing.\n"); + "Function is interposable; not analyzing.\n"); return true; } return false; @@ -1806,11 +1812,6 @@ pass_local_pure_const::execute (function *fun) if (!TREE_READONLY (current_function_decl)) { warn_function_const (current_function_decl, !l->looping); - if (!skip) - { - node->set_const_flag (true, l->looping); - changed = true; - } if (dump_file) fprintf (dump_file, "Function found to be %sconst: %s\n", l->looping ? "looping " : "", @@ -1819,25 +1820,23 @@ pass_local_pure_const::execute (function *fun) else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) && !l->looping) { - if (!skip) - { - node->set_const_flag (true, false); - changed = true; - } if (dump_file) fprintf (dump_file, "Function found to be non-looping: %s\n", current_function_name ()); } + if (!skip && node->set_const_flag (true, l->looping)) + { + if (dump_file) + fprintf (dump_file, "Declaration updated to be %sconst: %s\n", + l->looping ? "looping " : "", + current_function_name ()); + changed = true; + } break; case IPA_PURE: if (!DECL_PURE_P (current_function_decl)) { - if (!skip) - { - node->set_pure_flag (true, l->looping); - changed = true; - } warn_function_pure (current_function_decl, !l->looping); if (dump_file) fprintf (dump_file, "Function found to be %spure: %s\n", @@ -1847,15 +1846,18 @@ pass_local_pure_const::execute (function *fun) else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) && !l->looping) { - if (!skip) - { - node->set_pure_flag (true, false); - changed = true; - } if (dump_file) fprintf (dump_file, "Function found to be non-looping: %s\n", current_function_name ()); } + if (!skip && node->set_pure_flag (true, l->looping)) + { + if (dump_file) + fprintf (dump_file, "Declaration updated to be %spure: %s\n", + l->looping ? "looping " : "", + current_function_name ()); + changed = true; + } break; default: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fdf961d72ff..5fe37cc2480 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-05-04 Jan Hubicka + + * gcc.dg/ipa/pure-const-3.c: New testcase. + 2016-05-04 Marek Polacek * c-c++-common/Wdangling-else-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/ipa/pure-const-3.c b/gcc/testsuite/gcc.dg/ipa/pure-const-3.c new file mode 100644 index 00000000000..036b82860dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pure-const-3.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-require-alias "" } */ +/* { dg-options "-O2 -fdump-tree-local-pure-const1" } */ + +__attribute__ ((weak)) +__attribute__ ((noinline)) +int a(int v) +{ + return v; +} +__attribute__ ((noinline)) +static int b(int v) __attribute__ ((alias("a"))); +int +main() +{ + int c = a(1)==a(1); + int d = b(1)==b(1); + if (__builtin_constant_p (c)) + __builtin_abort (); + if (!__builtin_constant_p (d)) + __builtin_abort (); + return 0; +} +/* { dg-final { scan-ipa-dump "found to be const" "pure-const"} } */ -- 2.30.2