summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2017-03-30 13:51:02 +0000
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2017-03-30 13:51:02 +0000
commit61896fab9e29af44ffe56d448bd4e62aef5d9ad2 (patch)
tree0d0aa00b6327fc3693098541fb8b4b3c966bfa64 /gcc
parent555ca48ca1266b75e0d65df3c20c3233b25897a4 (diff)
downloadgcc-61896fab9e29af44ffe56d448bd4e62aef5d9ad2.tar.gz
[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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@246589 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cgraph.c17
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/cgraphclones.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr77333.C65
6 files changed, 103 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 99256af1cff..44e48ec9df9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 839388496ee..92ae0910c60 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -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)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 3889a3e1701..62cebd9e55a 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -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);
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index c2337e84553..69572b926c4 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c1b6566033a..89ade94f213 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/ipa/pr77333.C b/gcc/testsuite/g++.dg/ipa/pr77333.C
new file mode 100644
index 00000000000..1ef997f7a54
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr77333.C
@@ -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;
+}