Commit 6b715bf6 by Jan Hubicka Committed by Jan Hubicka

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
parent deef7113
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> 2016-05-04 Marek Polacek <polacek@redhat.com>
* doc/invoke.texi: Document -Wdangling-else. * doc/invoke.texi: Document -Wdangling-else.
......
...@@ -2289,7 +2289,7 @@ cgraph_node::can_be_local_p (void) ...@@ -2289,7 +2289,7 @@ cgraph_node::can_be_local_p (void)
} }
/* Call callback on cgraph_node, thunks and aliases associated to cgraph_node. /* 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. When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are
skipped. */ skipped. */
bool bool
...@@ -2301,9 +2301,14 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback) ...@@ -2301,9 +2301,14 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
{ {
cgraph_edge *e; cgraph_edge *e;
ipa_ref *ref; ipa_ref *ref;
enum availability avail = AVAIL_AVAILABLE;
if (callback (this, data)) if (include_overwritable
return true; || (avail = get_availability ()) > AVAIL_INTERPOSABLE)
{
if (callback (this, data))
return true;
}
FOR_EACH_ALIAS (this, ref) FOR_EACH_ALIAS (this, ref)
{ {
cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring); cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
...@@ -2314,7 +2319,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback) ...@@ -2314,7 +2319,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
exclude_virtual_thunks)) exclude_virtual_thunks))
return true; return true;
} }
if (get_availability () <= AVAIL_INTERPOSABLE) if (avail <= AVAIL_INTERPOSABLE)
return false; return false;
for (e = callers; e; e = e->next_caller) for (e = callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p if (e->caller->thunk.thunk_p
......
...@@ -3096,8 +3096,7 @@ symtab_node::get_availability (symtab_node *ref) ...@@ -3096,8 +3096,7 @@ symtab_node::get_availability (symtab_node *ref)
} }
/* Call calback on symtab node and aliases associated to this node. /* Call calback on symtab node and aliases associated to this node.
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are When INCLUDE_OVERWRITABLE is false, overwritable symbols are skipped. */
skipped. */
inline bool inline bool
symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *, 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 *, ...@@ -3105,15 +3104,19 @@ symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
void *data, void *data,
bool include_overwritable) bool include_overwritable)
{ {
if (callback (this, data)) if (include_overwritable
return true; || get_availability () > AVAIL_INTERPOSABLE)
{
if (callback (this, data))
return true;
}
if (has_aliases_p ()) if (has_aliases_p ())
return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
return false; return false;
} }
/* Call callback on function and aliases associated to the function. /* 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. */ skipped. */
inline bool inline bool
...@@ -3122,15 +3125,19 @@ cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *, ...@@ -3122,15 +3125,19 @@ cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
void *data, void *data,
bool include_overwritable) bool include_overwritable)
{ {
if (callback (this, data)) if (include_overwritable
return true; || get_availability () > AVAIL_INTERPOSABLE)
{
if (callback (this, data))
return true;
}
if (has_aliases_p ()) if (has_aliases_p ())
return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
return false; return false;
} }
/* Call calback on varpool symbol and aliases associated to varpool symbol. /* 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. */ skipped. */
inline bool inline bool
...@@ -3139,8 +3146,12 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *, ...@@ -3139,8 +3146,12 @@ varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
void *data, void *data,
bool include_overwritable) bool include_overwritable)
{ {
if (callback (this, data)) if (include_overwritable
return true; || get_availability () > AVAIL_INTERPOSABLE)
{
if (callback (this, data))
return true;
}
if (has_aliases_p ()) if (has_aliases_p ())
return call_for_symbol_and_aliases_1 (callback, data, include_overwritable); return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
return false; return false;
......
...@@ -927,8 +927,6 @@ end: ...@@ -927,8 +927,6 @@ end:
static void static void
add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) 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 /* There are some shared nodes, in particular the initializers on
static declarations. We do not need to scan them more than once static declarations. We do not need to scan them more than once
since all we would be interested in are the addressof since all we would be interested in are the addressof
...@@ -1222,6 +1220,7 @@ propagate_pure_const (void) ...@@ -1222,6 +1220,7 @@ propagate_pure_const (void)
int i; int i;
struct ipa_dfs_info * w_info; struct ipa_dfs_info * w_info;
bool remove_p = false; bool remove_p = false;
bool has_cdtor;
order_pos = ipa_reduced_postorder (order, true, false, order_pos = ipa_reduced_postorder (order, true, false,
ignore_edge_for_pure_const); ignore_edge_for_pure_const);
...@@ -1274,26 +1273,6 @@ propagate_pure_const (void) ...@@ -1274,26 +1273,6 @@ propagate_pure_const (void)
if (pure_const_state == IPA_NEITHER) if (pure_const_state == IPA_NEITHER)
break; 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++; count++;
/* We consider recursive cycles as possibly infinite. /* We consider recursive cycles as possibly infinite.
...@@ -1506,9 +1485,22 @@ propagate_pure_const (void) ...@@ -1506,9 +1485,22 @@ propagate_pure_const (void)
this_looping ? "looping " : "", this_looping ? "looping " : "",
w->name ()); w->name ());
} }
remove_p |= w->call_for_symbol_and_aliases (cdtor_p, /* Turning constructor or destructor to non-looping const/pure
NULL, true); enables us to possibly remove the function completely. */
w->set_const_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_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; break;
case IPA_PURE: case IPA_PURE:
...@@ -1520,9 +1512,20 @@ propagate_pure_const (void) ...@@ -1520,9 +1512,20 @@ propagate_pure_const (void)
this_looping ? "looping " : "", this_looping ? "looping " : "",
w->name ()); w->name ());
} }
remove_p |= w->call_for_symbol_and_aliases (cdtor_p, if (this_looping)
NULL, true); has_cdtor = false;
w->set_pure_flag (true, this_looping); 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; break;
default: default:
...@@ -1723,11 +1726,14 @@ skip_function_for_local_pure_const (struct cgraph_node *node) ...@@ -1723,11 +1726,14 @@ skip_function_for_local_pure_const (struct cgraph_node *node)
fprintf (dump_file, "Function called in recursive cycle; ignoring\n"); fprintf (dump_file, "Function called in recursive cycle; ignoring\n");
return true; 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) if (dump_file)
fprintf (dump_file, fprintf (dump_file,
"Function is not available or interposable; not analyzing.\n"); "Function is interposable; not analyzing.\n");
return true; return true;
} }
return false; return false;
...@@ -1806,11 +1812,6 @@ pass_local_pure_const::execute (function *fun) ...@@ -1806,11 +1812,6 @@ pass_local_pure_const::execute (function *fun)
if (!TREE_READONLY (current_function_decl)) if (!TREE_READONLY (current_function_decl))
{ {
warn_function_const (current_function_decl, !l->looping); warn_function_const (current_function_decl, !l->looping);
if (!skip)
{
node->set_const_flag (true, l->looping);
changed = true;
}
if (dump_file) if (dump_file)
fprintf (dump_file, "Function found to be %sconst: %s\n", fprintf (dump_file, "Function found to be %sconst: %s\n",
l->looping ? "looping " : "", l->looping ? "looping " : "",
...@@ -1819,25 +1820,23 @@ pass_local_pure_const::execute (function *fun) ...@@ -1819,25 +1820,23 @@ pass_local_pure_const::execute (function *fun)
else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
&& !l->looping) && !l->looping)
{ {
if (!skip)
{
node->set_const_flag (true, false);
changed = true;
}
if (dump_file) if (dump_file)
fprintf (dump_file, "Function found to be non-looping: %s\n", fprintf (dump_file, "Function found to be non-looping: %s\n",
current_function_name ()); 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; break;
case IPA_PURE: case IPA_PURE:
if (!DECL_PURE_P (current_function_decl)) 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); warn_function_pure (current_function_decl, !l->looping);
if (dump_file) if (dump_file)
fprintf (dump_file, "Function found to be %spure: %s\n", fprintf (dump_file, "Function found to be %spure: %s\n",
...@@ -1847,15 +1846,18 @@ pass_local_pure_const::execute (function *fun) ...@@ -1847,15 +1846,18 @@ pass_local_pure_const::execute (function *fun)
else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl) else if (DECL_LOOPING_CONST_OR_PURE_P (current_function_decl)
&& !l->looping) && !l->looping)
{ {
if (!skip)
{
node->set_pure_flag (true, false);
changed = true;
}
if (dump_file) if (dump_file)
fprintf (dump_file, "Function found to be non-looping: %s\n", fprintf (dump_file, "Function found to be non-looping: %s\n",
current_function_name ()); 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; break;
default: default:
......
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> 2016-05-04 Marek Polacek <polacek@redhat.com>
* c-c++-common/Wdangling-else-1.c: New test. * c-c++-common/Wdangling-else-1.c: New test.
......
/* { 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"} } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment