From: davidxl Date: Wed, 12 Aug 2009 16:51:41 +0000 (+0000) Subject: Fix to PR41012 X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=19bcf5214614bfc4322ffbe3d93c2fbcf6c22c26 Fix to PR41012 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150703 138bc75d-0d04-0410-961f-82ee72b054a4 --- 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 + + 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 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);