OSDN Git Service

Add vcond/vcondu patterns to sparc backend.
[pf3gnuchains/gcc-fork.git] / gcc / ipa-split.c
index 1dde723..7e0769f 100644 (file)
@@ -92,6 +92,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "fibheap.h"
 #include "params.h"
 #include "gimple-pretty-print.h"
+#include "ipa-inline.h"
 
 /* Per basic block info.  */
 
@@ -944,10 +945,10 @@ static void
 split_function (struct split_point *split_point)
 {
   VEC (tree, heap) *args_to_pass = NULL;
-  bitmap args_to_skip = BITMAP_ALLOC (NULL);
+  bitmap args_to_skip;
   tree parm;
   int num = 0;
-  struct cgraph_node *node;
+  struct cgraph_node *node, *cur_node = cgraph_get_node (current_function_decl);
   basic_block return_bb = find_return_bb ();
   basic_block call_bb;
   gimple_stmt_iterator gsi;
@@ -957,7 +958,6 @@ split_function (struct split_point *split_point)
   tree retval = NULL, real_retval = NULL;
   bool split_part_return_p = false;
   gimple last_stmt = NULL;
-  bool conv_needed = false;
   unsigned int i;
   tree arg;
 
@@ -967,23 +967,40 @@ split_function (struct split_point *split_point)
       dump_split_point (dump_file, split_point);
     }
 
+  if (cur_node->local.can_change_signature)
+    args_to_skip = BITMAP_ALLOC (NULL);
+  else
+    args_to_skip = NULL;
+
   /* Collect the parameters of new function and args_to_skip bitmap.  */
   for (parm = DECL_ARGUMENTS (current_function_decl);
        parm; parm = DECL_CHAIN (parm), num++)
-    if (!is_gimple_reg (parm)
-       || !gimple_default_def (cfun, parm)
-       || !bitmap_bit_p (split_point->ssa_names_to_pass,
-                         SSA_NAME_VERSION (gimple_default_def (cfun, parm))))
+    if (args_to_skip
+       && (!is_gimple_reg (parm)
+           || !gimple_default_def (cfun, parm)
+           || !bitmap_bit_p (split_point->ssa_names_to_pass,
+                             SSA_NAME_VERSION (gimple_default_def (cfun,
+                                                                   parm)))))
       bitmap_set_bit (args_to_skip, num);
     else
       {
-       arg = gimple_default_def (cfun, parm);
-       if (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm))
-           != TYPE_MAIN_VARIANT (TREE_TYPE (arg)))
+       /* This parm might not have been used up to now, but is going to be
+          used, hence register it.  */
+       add_referenced_var (parm);
+       if (is_gimple_reg (parm))
          {
-           conv_needed = true;
-           arg = fold_convert (DECL_ARG_TYPE (parm), arg);
+           arg = gimple_default_def (cfun, parm);
+           if (!arg)
+             {
+               arg = make_ssa_name (parm, gimple_build_nop ());
+               set_default_def (parm, arg);
+             }
          }
+       else
+         arg = parm;
+
+       if (!useless_type_conversion_p (DECL_ARG_TYPE (parm), TREE_TYPE (arg)))
+         arg = fold_convert (DECL_ARG_TYPE (parm), arg);
        VEC_safe_push (tree, heap, args_to_pass, arg);
       }
 
@@ -1080,9 +1097,7 @@ split_function (struct split_point *split_point)
 
   /* Now create the actual clone.  */
   rebuild_cgraph_edges ();
-  node = cgraph_function_versioning (cgraph_node (current_function_decl),
-                                    NULL, NULL,
-                                    args_to_skip,
+  node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip,
                                     split_point->split_bbs,
                                     split_point->entry_bb, "part");
   /* For usual cloning it is enough to clear builtin only when signature
@@ -1093,7 +1108,7 @@ split_function (struct split_point *split_point)
       DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN;
       DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0;
     }
-  cgraph_node_remove_callees (cgraph_node (current_function_decl));
+  cgraph_node_remove_callees (cur_node);
   if (!split_part_return_p)
     TREE_THIS_VOLATILE (node->decl) = 1;
   if (dump_file)
@@ -1115,14 +1130,13 @@ split_function (struct split_point *split_point)
 
   /* Produce the call statement.  */
   gsi = gsi_last_bb (call_bb);
-  if (conv_needed)
-    FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
-      if (!is_gimple_val (arg))
-       {
-         arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
-                                         false, GSI_NEW_STMT);
-         VEC_replace (tree, args_to_pass, i, arg);
-       }
+  FOR_EACH_VEC_ELT (tree, args_to_pass, i, arg)
+    if (!is_gimple_val (arg))
+      {
+       arg = force_gimple_operand_gsi (&gsi, arg, true, NULL_TREE,
+                                       false, GSI_CONTINUE_LINKING);
+       VEC_replace (tree, args_to_pass, i, arg);
+      }
   call = gimple_build_call_vec (node->decl, args_to_pass);
   gimple_set_block (call, DECL_INITIAL (current_function_decl));
 
@@ -1195,11 +1209,31 @@ split_function (struct split_point *split_point)
                    }
                }
              if (DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
-               gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+               {
+                 gimple_call_set_lhs (call, build_simple_mem_ref (retval));
+                 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+               }
              else
-               gimple_call_set_lhs (call, retval);
+               {
+                 tree restype;
+                 restype = TREE_TYPE (DECL_RESULT (current_function_decl));
+                 gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+                 if (!useless_type_conversion_p (TREE_TYPE (retval), restype))
+                   {
+                     gimple cpy;
+                     tree tem = create_tmp_reg (restype, NULL);
+                     tem = make_ssa_name (tem, call);
+                     cpy = gimple_build_assign_with_ops (NOP_EXPR, retval,
+                                                         tem, NULL_TREE);
+                     gsi_insert_after (&gsi, cpy, GSI_NEW_STMT);
+                     retval = tem;
+                   }
+                 gimple_call_set_lhs (call, retval);
+                 update_stmt (call);
+               }
            }
-          gsi_insert_after (&gsi, call, GSI_NEW_STMT);
+         else
+           gsi_insert_after (&gsi, call, GSI_NEW_STMT);
        }
       /* We don't use return block (there is either no return in function or
         multiple of them).  So create new basic block with return statement.
@@ -1253,7 +1287,7 @@ split_function (struct split_point *split_point)
     }
   free_dominance_info (CDI_DOMINATORS);
   free_dominance_info (CDI_POST_DOMINATORS);
-  compute_inline_parameters (node);
+  compute_inline_parameters (node, true);
 }
 
 /* Execute function splitting pass.  */
@@ -1265,7 +1299,7 @@ execute_split_functions (void)
   basic_block bb;
   int overall_time = 0, overall_size = 0;
   int todo = 0;
-  struct cgraph_node *node = cgraph_node (current_function_decl);
+  struct cgraph_node *node = cgraph_get_node (current_function_decl);
 
   if (flags_from_decl_or_type (current_function_decl) & ECF_NORETURN)
     {
@@ -1281,13 +1315,13 @@ execute_split_functions (void)
     }
   /* This can be relaxed; function might become inlinable after splitting
      away the uninlinable part.  */
-  if (!node->local.inlinable)
+  if (!inline_summary (node)->inlinable)
     {
       if (dump_file)
        fprintf (dump_file, "Not splitting: not inlinable.\n");
       return 0;
     }
-  if (node->local.disregard_inline_limits)
+  if (DECL_DISREGARD_INLINE_LIMITS (node->decl))
     {
       if (dump_file)
        fprintf (dump_file, "Not splitting: disregarding inline limits.\n");
@@ -1411,7 +1445,7 @@ struct gimple_opt_pass pass_split_functions =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
+  TODO_verify_all                              /* todo_flags_finish */
  }
 };
 
@@ -1452,6 +1486,6 @@ struct gimple_opt_pass pass_feedback_split_functions =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func                       /* todo_flags_finish */
+  TODO_verify_all                              /* todo_flags_finish */
  }
 };