Fix to PR41012
From-SVN: r150703
This commit is contained in:
parent
e8e76230ed
commit
6eb29714e4
7 changed files with 91 additions and 35 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
36
gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
Normal file
36
gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C
Normal 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" } } */
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue