summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/gimple-low.c25
-rw-r--r--gcc/ipa-inline.c23
-rw-r--r--gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C36
-rw-r--r--gcc/tree-flow.h1
-rw-r--r--gcc/tree-inline.c25
-rw-r--r--gcc/tree-inline.h3
7 files changed, 91 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9af6c7172f6..2bfd318cd8a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2009-08-12 Xinliang David Li <davidxl@google.com>
+
+ PR tree-optimization/41012
+ * tree-flow.h : New external interface.
+ * gimple-low.c (check_call_arg): Change to public function.
+ Remove argument mismatch check in lowering.
+ * tree-inline.h (tree_can_inline_p): Interface change.
+ * tree-inline.c (tree_can_inline_p): Fold argument mismatch check
+ into this function.
+ * ipa-inline.c (cgraph_decide_inlining_of_small_functions):
+ Call change to tree_can_inline_p function.
+ (cgraph_decide_inlining_incrementally): Ditto.
+
2009-08-12 Richard Sandiford <rdsandiford@googlemail.com>
PR tree-optimization/41031
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
index 8d7ead680ce..eba86727a05 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -221,17 +221,14 @@ struct gimple_opt_pass pass_lower_cf =
/* Verify if the type of the argument matches that of the function
declaration. If we cannot verify this or there is a mismatch,
- mark the call expression so it doesn't get inlined later. */
+ return false. */
-static void
-check_call_args (gimple stmt)
+bool
+gimple_check_call_args (gimple stmt)
{
tree fndecl, parms, p;
unsigned int i, nargs;
- if (gimple_call_cannot_inline_p (stmt))
- return;
-
nargs = gimple_call_num_args (stmt);
/* Get argument types for verification. */
@@ -244,7 +241,7 @@ check_call_args (gimple stmt)
/* Verify if the type of the argument matches that of the function
declaration. If we cannot verify this or there is a mismatch,
- mark the call expression so it doesn't get inlined later. */
+ return false. */
if (fndecl && DECL_ARGUMENTS (fndecl))
{
for (i = 0, p = DECL_ARGUMENTS (fndecl);
@@ -260,10 +257,7 @@ check_call_args (gimple stmt)
|| gimple_call_arg (stmt, i) == error_mark_node
|| !fold_convertible_p (DECL_ARG_TYPE (p),
gimple_call_arg (stmt, i)))
- {
- gimple_call_set_cannot_inline (stmt, true);
- break;
- }
+ return false;
}
}
else if (parms)
@@ -279,17 +273,15 @@ check_call_args (gimple stmt)
|| TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
|| !fold_convertible_p (TREE_VALUE (p),
gimple_call_arg (stmt, i)))
- {
- gimple_call_set_cannot_inline (stmt, true);
- break;
- }
+ return false;
}
}
else
{
if (nargs != 0)
- gimple_call_set_cannot_inline (stmt, true);
+ return false;
}
+ return true;
}
@@ -394,7 +386,6 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
lower_builtin_setjmp (gsi);
return;
}
- check_call_args (stmt);
}
break;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index dde8181c86c..79de3634d86 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -1006,10 +1006,8 @@ cgraph_decide_inlining_of_small_functions (void)
}
continue;
}
- if (!tree_can_inline_p (edge->caller->decl, edge->callee->decl))
+ if (!tree_can_inline_p (edge))
{
- gimple_call_set_cannot_inline (edge->call_stmt, true);
- edge->inline_failed = CIF_TARGET_OPTION_MISMATCH;
if (dump_file)
fprintf (dump_file, " inline_failed:%s.\n",
cgraph_inline_failed_string (edge->inline_failed));
@@ -1184,11 +1182,8 @@ cgraph_decide_inlining (void)
if (cgraph_recursive_inlining_p (e->caller, e->callee,
&e->inline_failed))
continue;
- if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
- {
- gimple_call_set_cannot_inline (e->call_stmt, true);
- continue;
- }
+ if (!tree_can_inline_p (e))
+ continue;
if (cgraph_mark_inline_edge (e, true, NULL))
redo_always_inline = true;
if (dump_file)
@@ -1440,14 +1435,14 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
- if (!tree_can_inline_p (node->decl, e->callee->decl))
+ if (!tree_can_inline_p (e))
{
- gimple_call_set_cannot_inline (e->call_stmt, true);
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
- "Not inlining: Target specific option mismatch.\n");
+ "Not inlining: %s",
+ cgraph_inline_failed_string (e->inline_failed));
}
continue;
}
@@ -1553,14 +1548,14 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
- if (!tree_can_inline_p (node->decl, e->callee->decl))
+ if (!tree_can_inline_p (e))
{
- gimple_call_set_cannot_inline (e->call_stmt, true);
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
- "Not inlining: Target specific option mismatch.\n");
+ "Not inlining: %s.",
+ cgraph_inline_failed_string (e->inline_failed));
}
continue;
}
diff --git a/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C b/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
new file mode 100644
index 00000000000..a0d488284b9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
@@ -0,0 +1,36 @@
+/* { dg-options "-O2 -fdump-tree-einline2" } */
+class DocId {
+ public:
+ DocId() { }
+ DocId(const DocId &other) { }
+};
+
+int g;
+class Base {
+ public:
+ virtual void Foo(DocId id) { g++; }
+};
+
+class Super: public Base {
+ public:
+ void Foo(DocId id) { }
+ void Bar(Base *base, DocId id) __attribute__((noinline));
+};
+
+void Super::Bar(Base *base, DocId id) {
+ Super::Foo(id); // direct call is inlined
+ base->Foo(id); // indirect call is marked do not inline
+}
+
+int main(void)
+{
+ Base bah;
+ Super baz;
+ DocId gid;
+
+ baz.Bar(&baz, gid);
+ return 0;
+}
+/* { dg-final-use { scan-tree-dump "Inlining virtual void Super::Foo" "einline2"} } */
+/* { dg-final-use { scan-tree-dump-not "mismatched arguments" "einline2"} } */
+/* { dg-final-use { cleanup-tree-dump "einline2" } } */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 1d2e69a4d1a..ff2b52bd8c0 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -597,6 +597,7 @@ extern void record_vars (tree);
extern bool block_may_fallthru (const_tree);
extern bool gimple_seq_may_fallthru (gimple_seq);
extern bool gimple_stmt_may_fallthru (gimple);
+extern bool gimple_check_call_args (gimple);
/* In tree-ssa.c */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 3b07aaa36ba..97c9261b469 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4754,9 +4754,10 @@ build_duplicate_type (tree type)
}
/* Return whether it is safe to inline a function because it used different
- target specific options or different optimization options. */
+ target specific options or call site actual types mismatch parameter types.
+ E is the call edge to be checked. */
bool
-tree_can_inline_p (tree caller, tree callee)
+tree_can_inline_p (struct cgraph_edge *e)
{
#if 0
/* This causes a regression in SPEC in that it prevents a cold function from
@@ -4785,7 +4786,25 @@ tree_can_inline_p (tree caller, tree callee)
return false;
}
#endif
+ tree caller, callee;
+
+ caller = e->caller->decl;
+ callee = e->callee->decl;
/* Allow the backend to decide if inlining is ok. */
- return targetm.target_option.can_inline_p (caller, callee);
+ if (!targetm.target_option.can_inline_p (caller, callee))
+ {
+ e->inline_failed = CIF_TARGET_OPTION_MISMATCH;
+ gimple_call_set_cannot_inline (e->call_stmt, true);
+ return false;
+ }
+
+ if (!gimple_check_call_args (e->call_stmt))
+ {
+ e->inline_failed = CIF_MISMATCHED_ARGUMENTS;
+ gimple_call_set_cannot_inline (e->call_stmt, true);
+ return false;
+ }
+
+ return true;
}
diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h
index 542eb729727..76ac17adcee 100644
--- a/gcc/tree-inline.h
+++ b/gcc/tree-inline.h
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "pointer-set.h"
+struct cgraph_edge;
/* Indicate the desired behavior wrt call graph edges. We can either
duplicate the edge (inlining, cloning), move the edge (versioning,
@@ -170,7 +171,7 @@ int estimate_num_insns (gimple, eni_weights *);
int estimate_num_insns_fn (tree, eni_weights *);
int count_insns_seq (gimple_seq, eni_weights *);
bool tree_versionable_function_p (tree);
-bool tree_can_inline_p (tree, tree);
+bool tree_can_inline_p (struct cgraph_edge *e);
extern gimple_seq remap_gimple_seq (gimple_seq, copy_body_data *);
extern tree remap_decl (tree decl, copy_body_data *id);