OSDN Git Service

2010-11-02 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2011 08:46:08 +0000 (08:46 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 2 Nov 2011 08:46:08 +0000 (08:46 +0000)
PR tree-optimization/50890
* gimple.h (gimple_fold_call): Remove.
* gimple-fold.c (fold_stmt_1): Move all call related code to ...
(gimple_fold_call): ... here.  Make static.  Update the
cannot-inline flag on direct calls.
* ipa-inline.c (early_inliner): Copy the cannot-inline flag
from the statements to the edges.

* gcc.dg/torture/pr50890.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180763 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/gimple-fold.c
gcc/gimple.h
gcc/ipa-inline.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/pr50890.c [new file with mode: 0644]

index fc8704d..87e0240 100644 (file)
@@ -1,3 +1,13 @@
+2010-11-02  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/50890
+       * gimple.h (gimple_fold_call): Remove.
+       * gimple-fold.c (fold_stmt_1): Move all call related code to ...
+       (gimple_fold_call): ... here.  Make static.  Update the
+       cannot-inline flag on direct calls.
+       * ipa-inline.c (early_inliner): Copy the cannot-inline flag
+       from the statements to the edges.
+
 2011-11-01  Ian Lance Taylor  <iant@google.com>
 
        * godump.c (struct macro_hash_value): Define.
index aa67d24..53bfb96 100644 (file)
@@ -1057,53 +1057,82 @@ gimple_extract_devirt_binfo_from_cst (tree cst)
    simplifies to a constant value. Return true if any changes were made.
    It is assumed that the operands have been previously folded.  */
 
-bool
+static bool
 gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
 {
   gimple stmt = gsi_stmt (*gsi);
   tree callee;
+  bool changed = false;
+  unsigned i;
 
-  /* Check for builtins that CCP can handle using information not
-     available in the generic fold routines.  */
-  callee = gimple_call_fndecl (stmt);
-  if (!inplace && callee && DECL_BUILT_IN (callee))
-    {
-      tree result = gimple_fold_builtin (stmt);
-
-      if (result)
-       {
-          if (!update_call_from_tree (gsi, result))
-           gimplify_and_update_call_from_tree (gsi, result);
-         return true;
-       }
-    }
+  /* Fold *& in call arguments.  */
+  for (i = 0; i < gimple_call_num_args (stmt); ++i)
+    if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
+      {
+       tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
+       if (tmp)
+         {
+           gimple_call_set_arg (stmt, i, tmp);
+           changed = true;
+         }
+      }
 
   /* Check for virtual calls that became direct calls.  */
   callee = gimple_call_fn (stmt);
   if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
     {
-      tree binfo, fndecl, obj;
-      HOST_WIDE_INT token;
-
       if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) != NULL_TREE)
        {
          gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
-         return true;
+         changed = true;
        }
+      else
+       {
+         tree obj = OBJ_TYPE_REF_OBJECT (callee);
+         tree binfo = gimple_extract_devirt_binfo_from_cst (obj);
+         if (binfo)
+           {
+             HOST_WIDE_INT token
+               = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
+             tree fndecl = gimple_get_virt_method_for_binfo (token, binfo);
+             if (fndecl)
+               {
+                 gimple_call_set_fndecl (stmt, fndecl);
+                 changed = true;
+               }
+           }
+       }
+    }
 
-      obj = OBJ_TYPE_REF_OBJECT (callee);
-      binfo = gimple_extract_devirt_binfo_from_cst (obj);
-      if (!binfo)
-       return false;
-      token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
-      fndecl = gimple_get_virt_method_for_binfo (token, binfo);
-      if (!fndecl)
-       return false;
-      gimple_call_set_fndecl (stmt, fndecl);
-      return true;
+  /* Check whether propagating into the function address made the
+     call direct, and thus possibly non-inlineable.
+     ???  This asks for a more conservative setting of the non-inlinable
+     flag, namely true for all indirect calls.  But that would require
+     that we can re-compute the flag conservatively, thus it isn't
+     ever initialized from something else than return/argument type
+     checks .  */
+  callee = gimple_call_fndecl (stmt);
+  if (callee
+      && !gimple_check_call_matching_types (stmt, callee))
+    gimple_call_set_cannot_inline (stmt, true);
+
+  if (inplace)
+    return changed;
+
+  /* Check for builtins that CCP can handle using information not
+     available in the generic fold routines.  */
+  if (callee && DECL_BUILT_IN (callee))
+    {
+      tree result = gimple_fold_builtin (stmt);
+      if (result)
+       {
+          if (!update_call_from_tree (gsi, result))
+           gimplify_and_update_call_from_tree (gsi, result);
+         changed = true;
+       }
     }
 
-  return false;
+  return changed;
 }
 
 /* Worker for both fold_stmt and fold_stmt_inplace.  The INPLACE argument
@@ -1162,17 +1191,6 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace)
       break;
 
     case GIMPLE_CALL:
-      /* Fold *& in call arguments.  */
-      for (i = 0; i < gimple_call_num_args (stmt); ++i)
-       if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
-         {
-           tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
-           if (tmp)
-             {
-               gimple_call_set_arg (stmt, i, tmp);
-               changed = true;
-             }
-         }
       changed |= gimple_fold_call (gsi, inplace);
       break;
 
index 75e19a7..666c44c 100644 (file)
@@ -909,7 +909,6 @@ unsigned get_gimple_rhs_num_ops (enum tree_code);
 #define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
 gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
 const char *gimple_decl_printable_name (tree, int);
-bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace);
 tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
 void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
 tree gimple_extract_devirt_binfo_from_cst (tree);
index 662c6b3..31c88e5 100644 (file)
@@ -1949,6 +1949,8 @@ early_inliner (void)
                = estimate_num_insns (edge->call_stmt, &eni_size_weights);
              es->call_stmt_time
                = estimate_num_insns (edge->call_stmt, &eni_time_weights);
+             edge->call_stmt_cannot_inline_p
+               = gimple_call_cannot_inline_p (edge->call_stmt);
            }
          timevar_pop (TV_INTEGRATION);
          iterations++;
index bdbdb8e..bf7c366 100644 (file)
@@ -1,3 +1,8 @@
+2010-11-02  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/50890
+       * gcc.dg/torture/pr50890.c: New testcase.
+
 2011-11-01  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/44277
diff --git a/gcc/testsuite/gcc.dg/torture/pr50890.c b/gcc/testsuite/gcc.dg/torture/pr50890.c
new file mode 100644 (file)
index 0000000..17240d4
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+static float make_insn_raw (void)
+{
+    return 0;
+}
+
+static int emit_pattern_after_noloc (int (make_raw) ()) 
+{
+    return make_raw ();
+}
+
+void emit_insn_after_noloc (void) 
+{
+    emit_pattern_after_noloc ((void *) make_insn_raw);
+}
+