@@ -301,14 +301,13 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node)
thunk is this_adjusting but we are removing this parameter. */
static cgraph_node *
-duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node,
- bitmap args_to_skip)
+duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
{
cgraph_node *new_thunk, *thunk_of;
thunk_of = cgraph_function_or_thunk_node (thunk->callees->callee);
if (thunk_of->thunk.thunk_p)
- node = duplicate_thunk_for_node (thunk_of, node, args_to_skip);
+ node = duplicate_thunk_for_node (thunk_of, node);
struct cgraph_edge *cs;
for (cs = node->callers; cs; cs = cs->next_caller)
@@ -320,17 +319,18 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node,
return cs->caller;
tree new_decl;
- if (!args_to_skip)
+ if (!node->clone.args_to_skip)
new_decl = copy_node (thunk->decl);
else
{
/* We do not need to duplicate this_adjusting thunks if we have removed
this. */
if (thunk->thunk.this_adjusting
- && bitmap_bit_p (args_to_skip, 0))
+ && bitmap_bit_p (node->clone.args_to_skip, 0))
return node;
- new_decl = build_function_decl_skip_args (thunk->decl, args_to_skip,
+ new_decl = build_function_decl_skip_args (thunk->decl,
+ node->clone.args_to_skip,
false);
}
gcc_checking_assert (!DECL_STRUCT_FUNCTION (new_decl));
@@ -347,6 +347,8 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node,
new_thunk->thunk = thunk->thunk;
new_thunk->unique_name = in_lto_p;
new_thunk->former_clone_of = thunk->decl;
+ new_thunk->clone.args_to_skip = node->clone.args_to_skip;
+ new_thunk->clone.combined_args_to_skip = node->clone.combined_args_to_skip;
struct cgraph_edge *e = cgraph_create_edge (new_thunk, node, NULL, 0,
CGRAPH_FREQ_BASE);
@@ -363,12 +365,11 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node,
chain. */
void
-redirect_edge_duplicating_thunks (struct cgraph_edge *e, struct cgraph_node *n,
- bitmap args_to_skip)
+redirect_edge_duplicating_thunks (struct cgraph_edge *e, struct cgraph_node *n)
{
cgraph_node *orig_to = cgraph_function_or_thunk_node (e->callee);
if (orig_to->thunk.thunk_p)
- n = duplicate_thunk_for_node (orig_to, n, args_to_skip);
+ n = duplicate_thunk_for_node (orig_to, n);
cgraph_redirect_edge_callee (e, n);
}
@@ -421,9 +422,21 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
new_node->rtl = n->rtl;
new_node->count = count;
new_node->frequency = n->frequency;
- new_node->clone = n->clone;
- new_node->clone.tree_map = NULL;
new_node->tp_first_run = n->tp_first_run;
+
+ new_node->clone.tree_map = NULL;
+ new_node->clone.args_to_skip = args_to_skip;
+ if (!args_to_skip)
+ new_node->clone.combined_args_to_skip = n->clone.combined_args_to_skip;
+ else if (n->clone.combined_args_to_skip)
+ {
+ new_node->clone.combined_args_to_skip = BITMAP_GGC_ALLOC ();
+ bitmap_ior (new_node->clone.combined_args_to_skip,
+ n->clone.combined_args_to_skip, args_to_skip);
+ }
+ else
+ new_node->clone.combined_args_to_skip = args_to_skip;
+
if (n->count)
{
if (new_node->count > n->count)
@@ -448,10 +461,9 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq,
if (!e->callee
|| DECL_BUILT_IN_CLASS (e->callee->decl) != BUILT_IN_NORMAL
|| DECL_FUNCTION_CODE (e->callee->decl) != BUILT_IN_UNREACHABLE)
- redirect_edge_duplicating_thunks (e, new_node, args_to_skip);
+ redirect_edge_duplicating_thunks (e, new_node);
}
-
for (e = n->callees;e; e=e->next_callee)
cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid,
count_scale, freq, update_original);
@@ -558,7 +570,6 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
ABI support for this. */
set_new_clone_decl_and_node_flags (new_node);
new_node->clone.tree_map = tree_map;
- new_node->clone.args_to_skip = args_to_skip;
/* Clones of global symbols or symbols with unique names are unique. */
if ((TREE_PUBLIC (old_decl)
@@ -569,32 +580,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
new_node->unique_name = true;
FOR_EACH_VEC_SAFE_ELT (tree_map, i, map)
new_node->maybe_add_reference (map->new_tree, IPA_REF_ADDR, NULL);
- if (!args_to_skip)
- new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip;
- else if (old_node->clone.combined_args_to_skip)
- {
- int newi = 0, oldi = 0;
- tree arg;
- bitmap new_args_to_skip = BITMAP_GGC_ALLOC ();
- struct cgraph_node *orig_node;
- for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of)
- ;
- for (arg = DECL_ARGUMENTS (orig_node->decl);
- arg; arg = DECL_CHAIN (arg), oldi++)
- {
- if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi))
- {
- bitmap_set_bit (new_args_to_skip, oldi);
- continue;
- }
- if (bitmap_bit_p (args_to_skip, newi))
- bitmap_set_bit (new_args_to_skip, oldi);
- newi++;
- }
- new_node->clone.combined_args_to_skip = new_args_to_skip;
- }
- else
- new_node->clone.combined_args_to_skip = args_to_skip;
+
if (old_node->ipa_transforms_to_apply.exists ())
new_node->ipa_transforms_to_apply
= old_node->ipa_transforms_to_apply.copy ();
new file mode 100644
@@ -0,0 +1,43 @@
+/* { dg-do run } */
+/* { dg-options "-O3 --param ipa-cp-eval-threshold=1" } */
+
+extern "C" void abort (void);
+
+struct CBase {
+ virtual void BaseFunc () {}
+};
+
+struct MMixin {
+ virtual void * MixinFunc (int, void *) = 0;
+};
+
+struct CExample: CBase, public MMixin
+{
+ int stuff, magic, more_stuff;
+
+ CExample ()
+ {
+ stuff = 0;
+ magic = 0xbeef;
+ more_stuff = 0;
+ }
+ void *MixinFunc (int arg, void *arg2)
+ {
+ if (arg != 1 || arg2)
+ return 0;
+ if (magic != 0xbeef)
+ abort();
+ return this;
+ }
+};
+
+void *test (MMixin & anExample)
+{
+ return anExample.MixinFunc (1, 0);
+}
+
+int main ()
+{
+ CExample c;
+ return (test (c) != &c);
+}
new file mode 100644
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O3" } */
+
+struct A {
+ void *p;
+ A (void *q) : p (q) {}
+ A (const A &) : p () {}
+};
+
+struct CBase {
+ virtual void BaseFunc () {}
+};
+
+struct MMixin {
+ virtual A MixinFunc (int, A) = 0;
+};
+
+struct CExample: CBase, public MMixin
+{
+ A MixinFunc (int arg, A arg2)
+ {
+ if (arg != 1 || arg2.p)
+ return 0;
+ return this;
+ }
+};
+
+void *test (MMixin & anExample)
+{
+ return anExample.MixinFunc (1, (0)).p;
+}
+
+int main ()
+{
+ CExample c;
+ return (test (c) != &c);
+}