mirror of git://gcc.gnu.org/git/gcc.git
parent
e8e76230ed
commit
6eb29714e4
|
@ -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>
|
2009-08-12 Richard Sandiford <rdsandiford@googlemail.com>
|
||||||
|
|
||||||
PR tree-optimization/41031
|
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
|
/* Verify if the type of the argument matches that of the function
|
||||||
declaration. If we cannot verify this or there is a mismatch,
|
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
|
bool
|
||||||
check_call_args (gimple stmt)
|
gimple_check_call_args (gimple stmt)
|
||||||
{
|
{
|
||||||
tree fndecl, parms, p;
|
tree fndecl, parms, p;
|
||||||
unsigned int i, nargs;
|
unsigned int i, nargs;
|
||||||
|
|
||||||
if (gimple_call_cannot_inline_p (stmt))
|
|
||||||
return;
|
|
||||||
|
|
||||||
nargs = gimple_call_num_args (stmt);
|
nargs = gimple_call_num_args (stmt);
|
||||||
|
|
||||||
/* Get argument types for verification. */
|
/* 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
|
/* Verify if the type of the argument matches that of the function
|
||||||
declaration. If we cannot verify this or there is a mismatch,
|
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))
|
if (fndecl && DECL_ARGUMENTS (fndecl))
|
||||||
{
|
{
|
||||||
for (i = 0, p = 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
|
|| gimple_call_arg (stmt, i) == error_mark_node
|
||||||
|| !fold_convertible_p (DECL_ARG_TYPE (p),
|
|| !fold_convertible_p (DECL_ARG_TYPE (p),
|
||||||
gimple_call_arg (stmt, i)))
|
gimple_call_arg (stmt, i)))
|
||||||
{
|
return false;
|
||||||
gimple_call_set_cannot_inline (stmt, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (parms)
|
else if (parms)
|
||||||
|
@ -279,17 +273,15 @@ check_call_args (gimple stmt)
|
||||||
|| TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
|
|| TREE_CODE (TREE_VALUE (p)) == VOID_TYPE
|
||||||
|| !fold_convertible_p (TREE_VALUE (p),
|
|| !fold_convertible_p (TREE_VALUE (p),
|
||||||
gimple_call_arg (stmt, i)))
|
gimple_call_arg (stmt, i)))
|
||||||
{
|
return false;
|
||||||
gimple_call_set_cannot_inline (stmt, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (nargs != 0)
|
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);
|
lower_builtin_setjmp (gsi);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
check_call_args (stmt);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -1006,10 +1006,8 @@ cgraph_decide_inlining_of_small_functions (void)
|
||||||
}
|
}
|
||||||
continue;
|
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)
|
if (dump_file)
|
||||||
fprintf (dump_file, " inline_failed:%s.\n",
|
fprintf (dump_file, " inline_failed:%s.\n",
|
||||||
cgraph_inline_failed_string (edge->inline_failed));
|
cgraph_inline_failed_string (edge->inline_failed));
|
||||||
|
@ -1184,11 +1182,8 @@ cgraph_decide_inlining (void)
|
||||||
if (cgraph_recursive_inlining_p (e->caller, e->callee,
|
if (cgraph_recursive_inlining_p (e->caller, e->callee,
|
||||||
&e->inline_failed))
|
&e->inline_failed))
|
||||||
continue;
|
continue;
|
||||||
if (!tree_can_inline_p (e->caller->decl, e->callee->decl))
|
if (!tree_can_inline_p (e))
|
||||||
{
|
continue;
|
||||||
gimple_call_set_cannot_inline (e->call_stmt, true);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (cgraph_mark_inline_edge (e, true, NULL))
|
if (cgraph_mark_inline_edge (e, true, NULL))
|
||||||
redo_always_inline = true;
|
redo_always_inline = true;
|
||||||
if (dump_file)
|
if (dump_file)
|
||||||
|
@ -1440,14 +1435,14 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
|
||||||
}
|
}
|
||||||
continue;
|
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)
|
if (dump_file)
|
||||||
{
|
{
|
||||||
indent_to (dump_file, depth);
|
indent_to (dump_file, depth);
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"Not inlining: Target specific option mismatch.\n");
|
"Not inlining: %s",
|
||||||
|
cgraph_inline_failed_string (e->inline_failed));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1553,14 +1548,14 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
|
||||||
}
|
}
|
||||||
continue;
|
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)
|
if (dump_file)
|
||||||
{
|
{
|
||||||
indent_to (dump_file, depth);
|
indent_to (dump_file, depth);
|
||||||
fprintf (dump_file,
|
fprintf (dump_file,
|
||||||
"Not inlining: Target specific option mismatch.\n");
|
"Not inlining: %s.",
|
||||||
|
cgraph_inline_failed_string (e->inline_failed));
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 block_may_fallthru (const_tree);
|
||||||
extern bool gimple_seq_may_fallthru (gimple_seq);
|
extern bool gimple_seq_may_fallthru (gimple_seq);
|
||||||
extern bool gimple_stmt_may_fallthru (gimple);
|
extern bool gimple_stmt_may_fallthru (gimple);
|
||||||
|
extern bool gimple_check_call_args (gimple);
|
||||||
|
|
||||||
|
|
||||||
/* In tree-ssa.c */
|
/* 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
|
/* 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
|
bool
|
||||||
tree_can_inline_p (tree caller, tree callee)
|
tree_can_inline_p (struct cgraph_edge *e)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
/* This causes a regression in SPEC in that it prevents a cold function from
|
/* 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;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
tree caller, callee;
|
||||||
|
|
||||||
|
caller = e->caller->decl;
|
||||||
|
callee = e->callee->decl;
|
||||||
|
|
||||||
/* Allow the backend to decide if inlining is ok. */
|
/* 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"
|
#include "pointer-set.h"
|
||||||
|
|
||||||
|
struct cgraph_edge;
|
||||||
|
|
||||||
/* Indicate the desired behavior wrt call graph edges. We can either
|
/* Indicate the desired behavior wrt call graph edges. We can either
|
||||||
duplicate the edge (inlining, cloning), move the edge (versioning,
|
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 estimate_num_insns_fn (tree, eni_weights *);
|
||||||
int count_insns_seq (gimple_seq, eni_weights *);
|
int count_insns_seq (gimple_seq, eni_weights *);
|
||||||
bool tree_versionable_function_p (tree);
|
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 gimple_seq remap_gimple_seq (gimple_seq, copy_body_data *);
|
||||||
extern tree remap_decl (tree decl, copy_body_data *id);
|
extern tree remap_decl (tree decl, copy_body_data *id);
|
||||||
|
|
Loading…
Reference in New Issue