[PR 77333] Fixup fntypes of gimple calls of clones

2017-03-30  Martin Jambor  <mjambor@suse.cz>

	PR ipa/77333
	* cgraph.h (cgraph_build_function_type_skip_args): Declare.
	* cgraph.c (redirect_call_stmt_to_callee): Set gimple fntype so that
	it reflects the signature changes performed at the callee side.
	* cgraphclones.c (build_function_type_skip_args): Make public, renamed
	to cgraph_build_function_type_skip_args.
	(build_function_decl_skip_args): Adjust call to the above function.

testsuite/
	* g++.dg/ipa/pr77333.C: New test.

From-SVN: r246589
This commit is contained in:
Martin Jambor 2017-03-30 15:51:02 +02:00 committed by Martin Jambor
parent de008ec4d6
commit b0fd4d7e32
6 changed files with 103 additions and 5 deletions

View File

@ -1,3 +1,13 @@
2017-03-30 Martin Jambor <mjambor@suse.cz>
PR ipa/77333
* cgraph.h (cgraph_build_function_type_skip_args): Declare.
* cgraph.c (redirect_call_stmt_to_callee): Set gimple fntype so that
it reflects the signature changes performed at the callee side.
* cgraphclones.c (build_function_type_skip_args): Make public, renamed
to cgraph_build_function_type_skip_args.
(build_function_decl_skip_args): Adjust call to the above function.
2017-03-30 Jakub Jelinek <jakub@redhat.com>
PR target/80206

View File

@ -1424,8 +1424,23 @@ cgraph_edge::redirect_call_stmt_to_callee (void)
if (skip_bounds)
new_stmt = chkp_copy_call_skip_bounds (new_stmt);
tree old_fntype = gimple_call_fntype (e->call_stmt);
gimple_call_set_fndecl (new_stmt, e->callee->decl);
gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt));
cgraph_node *origin = e->callee;
while (origin->clone_of)
origin = origin->clone_of;
if ((origin->former_clone_of
&& old_fntype == TREE_TYPE (origin->former_clone_of))
|| old_fntype == TREE_TYPE (origin->decl))
gimple_call_set_fntype (new_stmt, TREE_TYPE (e->callee->decl));
else
{
bitmap skip = e->callee->clone.combined_args_to_skip;
tree t = cgraph_build_function_type_skip_args (old_fntype, skip,
false);
gimple_call_set_fntype (new_stmt, t);
}
if (gimple_vdef (new_stmt)
&& TREE_CODE (gimple_vdef (new_stmt)) == SSA_NAME)

View File

@ -2326,6 +2326,8 @@ void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
void dump_callgraph_transformation (const cgraph_node *original,
const cgraph_node *clone,
const char *suffix);
tree cgraph_build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
bool skip_return);
/* In cgraphbuild.c */
int compute_call_stmt_bb_frequency (tree, basic_block bb);

View File

@ -152,9 +152,9 @@ cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the
return value if SKIP_RETURN is true. */
static tree
build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
bool skip_return)
tree
cgraph_build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
bool skip_return)
{
tree new_type = NULL;
tree args, new_args = NULL;
@ -219,7 +219,8 @@ build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip,
if (prototype_p (new_type)
|| (skip_return && !VOID_TYPE_P (TREE_TYPE (new_type))))
new_type
= build_function_type_skip_args (new_type, args_to_skip, skip_return);
= cgraph_build_function_type_skip_args (new_type, args_to_skip,
skip_return);
TREE_TYPE (new_decl) = new_type;
/* For declarations setting DECL_VINDEX (i.e. methods)

View File

@ -1,3 +1,8 @@
2017-03-30 Martin Jambor <mjambor@suse.cz>
PR ipa/77333
* g++.dg/ipa/pr77333.C: New test.
2017-03-30 Jakub Jelinek <jakub@redhat.com>
PR target/80206

View File

@ -0,0 +1,65 @@
// { dg-do run }
// { dg-options "-O2 -fno-ipa-sra" }
volatile int global;
int __attribute__((noinline, noclone))
get_data (int i)
{
global = i;
return i;
}
typedef int array[32];
namespace {
char buf[512];
class A
{
public:
int field;
char *s;
A() : field(223344)
{
s = buf;
}
int __attribute__((noinline))
foo (int a, int b, int c, int d, int e, int f, int g, int h, int i, int j,
int k, int l, int m, int n, int o, int p, int q, int r, int s, int t)
{
global = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+r+s+t;
return global;
}
int __attribute__((noinline))
bar()
{
int r = foo (get_data (1), get_data (1), get_data (1), get_data (1),
get_data (1), get_data (1), get_data (1), get_data (1),
get_data (1), get_data (1), get_data (1), get_data (1),
get_data (1), get_data (1), get_data (1), get_data (1),
get_data (1), get_data (1), get_data (1), get_data (1));
if (field != 223344)
__builtin_abort ();
return 0;
}
};
}
int main (int argc, char **argv)
{
A a;
int r = a.bar();
r = a.bar ();
if (a.field != 223344)
__builtin_abort ();
if (global != 20)
__builtin_abort ();
return r;
}