Fix to PR41012

From-SVN: r150703
This commit is contained in:
Xinliang David Li 2009-08-12 16:51:41 +00:00 committed by Xinliang David Li
parent e8e76230ed
commit 6eb29714e4
7 changed files with 91 additions and 35 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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" } } */

View File

@ -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 */

View File

@ -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;
}

View File

@ -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);