OSDN Git Service

Fix to PR41012
authordavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 12 Aug 2009 16:51:41 +0000 (16:51 +0000)
committerdavidxl <davidxl@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 12 Aug 2009 16:51:41 +0000 (16:51 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150703 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple-low.c
gcc/ipa-inline.c
gcc/testsuite/g++.dg/tree-prof/inline_mismatch_args.C [new file with mode: 0644]
gcc/tree-flow.h
gcc/tree-inline.c
gcc/tree-inline.h

index 9af6c71..2bfd318 100644 (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
index 8d7ead6..eba8672 100644 (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;
 
index dde8181..79de363 100644 (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;
          }
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 (file)
index 0000000..a0d4882
--- /dev/null
@@ -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" } } */
index 1d2e69a..ff2b52b 100644 (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  */
index 3b07aaa..97c9261 100644 (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;
 }
index 542eb72..76ac17a 100644 (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);