+2014-11-26 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR ipa/61190
+ * cgraph.h (symtab_node::call_for_symbol_and_aliases): Fix comment.
+ (cgraph_node::function_or_virtual_thunk_symbol): New function.
+ (cgraph_node::call_for_symbol_and_aliases): Fix comment.
+ (cgraph_node::call_for_symbol_thunks_and_aliases): Adjust comment.
+ Add new optional parameter exclude_virtual_thunks.
+ * cgraph.c (cgraph_node::call_for_symbol_thunks_and_aliases): Add new
+ optional parameter exclude_virtual_thunks.
+ (cgraph_node::set_const_flag): Don't propagate to virtual thunks.
+ (cgraph_node::set_pure_flag): Likewise.
+ (cgraph_node::function_symbol): Simplified.
+ (cgraph_node::function_or_virtual_thunk_symbol): New function.
+ * ipa-pure-const.c (analyze_function): For virtual thunks set
+ pure_const_state to IPA_NEITHER.
+ (propagate_pure_const): Use function_or_virtual_thunk_symbol.
+
2014-11-26 Richard Biener <rguenther@suse.de>
PR middle-end/63738
NULL, true));
}
-/* Call calback 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
- skipped. */
-
+ skipped. When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are
+ skipped. */
bool
cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
(cgraph_node *, void *),
void *data,
- bool include_overwritable)
+ bool include_overwritable,
+ bool exclude_virtual_thunks)
{
cgraph_edge *e;
ipa_ref *ref;
for (e = callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p
&& (include_overwritable
- || e->caller->get_availability () > AVAIL_INTERPOSABLE))
+ || e->caller->get_availability () > AVAIL_INTERPOSABLE)
+ && !(exclude_virtual_thunks
+ && e->caller->thunk.virtual_offset_p))
if (e->caller->call_for_symbol_thunks_and_aliases (callback, data,
- include_overwritable))
+ include_overwritable,
+ exclude_virtual_thunks))
return true;
FOR_EACH_ALIAS (this, ref)
if (include_overwritable
|| alias->get_availability () > AVAIL_INTERPOSABLE)
if (alias->call_for_symbol_thunks_and_aliases (callback, data,
- include_overwritable))
+ include_overwritable,
+ exclude_virtual_thunks))
return true;
}
return false;
}
-/* Call calback 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
- skipped. */
+ skipped. */
bool
cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
{
call_for_symbol_thunks_and_aliases (cgraph_set_const_flag_1,
(void *)(size_t)(readonly + (int)looping * 2),
- false);
+ false, true);
}
/* Worker to set pure flag. */
{
call_for_symbol_thunks_and_aliases (cgraph_set_pure_flag_1,
(void *)(size_t)(pure + (int)looping * 2),
- false);
+ false, true);
}
/* Return true when cgraph_node can not return or throw and thus
}
/* Walk the alias chain to return the function cgraph_node is alias of.
- Walk through thunk, too.
+ Walk through thunks, too.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
cgraph_node *
cgraph_node::function_symbol (enum availability *availability)
{
- cgraph_node *node = this;
+ cgraph_node *node = ultimate_alias_target (availability);
- do
+ while (node->thunk.thunk_p)
{
+ node = node->callees->callee;
+ if (availability)
+ {
+ enum availability a;
+ a = node->get_availability ();
+ if (a < *availability)
+ *availability = a;
+ }
node = node->ultimate_alias_target (availability);
- if (node->thunk.thunk_p)
+ }
+ return node;
+}
+
+/* Walk the alias chain to return the function cgraph_node is alias of.
+ Walk through non virtual thunks, too. Thus we return either a function
+ or a virtual thunk node.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain. */
+
+cgraph_node *
+cgraph_node::function_or_virtual_thunk_symbol
+ (enum availability *availability)
+{
+ cgraph_node *node = ultimate_alias_target (availability);
+
+ while (node->thunk.thunk_p && !node->thunk.virtual_offset_p)
+ {
+ node = node->callees->callee;
+ if (availability)
{
- node = node->callees->callee;
- if (availability)
- {
- enum availability a;
- a = node->get_availability ();
- if (a < *availability)
- *availability = a;
- }
- node = node->ultimate_alias_target (availability);
+ enum availability a;
+ a = node->get_availability ();
+ if (a < *availability)
+ *availability = a;
}
- } while (node && node->thunk.thunk_p);
+ node = node->ultimate_alias_target (availability);
+ }
return node;
}
body aliases. */
void fixup_same_cpp_alias_visibility (symtab_node *target);
- /* Call calback on symtab node and aliases associated to this node.
+ /* Call callback on symtab node and aliases associated to this node.
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
- skipped. */
+ skipped. */
bool call_for_symbol_and_aliases (bool (*callback) (symtab_node *, void *),
void *data,
bool include_overwrite);
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
cgraph_node *function_symbol (enum availability *avail = NULL);
+ /* Walk the alias chain to return the function cgraph_node is alias of.
+ Walk through non virtual thunks, too. Thus we return either a function
+ or a virtual thunk node.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain. */
+ cgraph_node *function_or_virtual_thunk_symbol
+ (enum availability *avail = NULL);
+
/* Create node representing clone of N executed COUNT times. Decrease
the execution counts from original node too.
The new clone will have decl set to DECL that may or may not be the same
if any to PURE. */
void set_pure_flag (bool pure, bool looping);
- /* Call calback 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
skipped. */
void *),
void *data, bool include_overwritable);
- /* Call calback on cgraph_node, thunks and aliases associated to NODE.
+ /* Call callback on cgraph_node, thunks and aliases associated to NODE.
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. When EXCLUDE_VIRTUAL_THUNKS is true, virtual thunks are
skipped. */
bool call_for_symbol_thunks_and_aliases (bool (*callback) (cgraph_node *node,
- void *data),
- void *data,
- bool include_overwritable);
+ void *data),
+ void *data,
+ bool include_overwritable,
+ bool exclude_virtual_thunks = false);
/* Likewise indicate that a node is needed, i.e. reachable via some
external means. */
{
/* Thunk gets propagated through, so nothing interesting happens. */
gcc_assert (ipa);
+ if (fn->thunk.thunk_p && fn->thunk.virtual_offset_p)
+ l->pure_const_state = IPA_NEITHER;
return l;
}
for (e = w->callees; e; e = e->next_callee)
{
enum availability avail;
- struct cgraph_node *y = e->callee->function_symbol (&avail);
+ struct cgraph_node *y = e->callee->
+ function_or_virtual_thunk_symbol (&avail);
enum pure_const_state_e edge_state = IPA_CONST;
bool edge_looping = false;
for (e = w->callees; e && !can_free; e = e->next_callee)
{
enum availability avail;
- struct cgraph_node *y = e->callee->function_symbol (&avail);
+ struct cgraph_node *y = e->callee->
+ function_or_virtual_thunk_symbol (&avail);
if (avail > AVAIL_INTERPOSABLE)
can_free = get_function_state (y)->can_free;
for (e = w->callees; e && !can_throw; e = e->next_callee)
{
enum availability avail;
- struct cgraph_node *y = e->callee->function_symbol (&avail);
+ struct cgraph_node *y = e->callee->
+ function_or_virtual_thunk_symbol (&avail);
if (avail > AVAIL_INTERPOSABLE)
{
+2014-11-26 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR ipa/61190
+ * g++.old-deja/g++.mike/p4736b.C: Use -O2.
+
2014-11-26 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/59114
// { dg-do run }
+// { dg-options "-O2" }
// prms-id: 4736
class Rep {