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
This commit is contained in:
parent
deef711327
commit
6b715bf6d9
|
@ -1,3 +1,16 @@
|
|||
2016-05-04 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* 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 <polacek@redhat.com>
|
||||
|
||||
* doc/invoke.texi: Document -Wdangling-else.
|
||||
|
|
13
gcc/cgraph.c
13
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 <cgraph_node *> (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
|
||||
|
|
31
gcc/cgraph.h
31
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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2016-05-04 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* gcc.dg/ipa/pure-const-3.c: New testcase.
|
||||
|
||||
2016-05-04 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
* c-c++-common/Wdangling-else-1.c: New test.
|
||||
|
|
|
@ -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"} } */
|
Loading…
Reference in New Issue