OSDN Git Service

* tree.h (build_function_decl_skip_args): Add boolean parameter.
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Jan 2012 18:47:28 +0000 (18:47 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 11 Jan 2012 18:47:28 +0000 (18:47 +0000)
(build_function_type_skip_args): Delete.
* tree.c (build_function_type_skip_args): Make static and add
SKIP_RETURN parameter.  Fix thinko in the handling of variants.
(build_function_decl_skip_args): Add SKIP_RETURN parameter and
pass it to build_function_type_skip_args.
* cgraph.h (cgraph_function_versioning): Add boolean parameter.
(tree_function_versioning): Likewise.
* cgraph.c (cgraph_create_virtual_clone): Adjust call to
build_function_decl_skip_args.
* cgraphunit.c (cgraph_function_versioning): Add SKIP_RETURN parameter
and pass it to build_function_decl_skip_args/tree_function_versioning.
(cgraph_materialize_clone): Adjust call to tree_function_versioning.
* ipa-inline-transform.c (save_inline_function_body): Likewise.
* trans-mem.c (ipa_tm_create_version): Likewise.
* tree-sra.c (modify_function): Ditto for cgraph_function_versioning.
* tree-inline.c (declare_return_variable): Remove always-true test.
(tree_function_versioning): Add SKIP_RETURN parameter.  If the function
returns non-void and SKIP_RETURN, create a void-typed RESULT_DECL.
* ipa-split.c (split_function): Skip the return value for the split
part if it doesn't return.

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

18 files changed:
gcc/ChangeLog
gcc/cgraph.c
gcc/cgraph.h
gcc/cgraphunit.c
gcc/ipa-inline-transform.c
gcc/ipa-split.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt23.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt23.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt23_pkg.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt23_pkg.ads [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt24.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/opt24.ads [new file with mode: 0644]
gcc/trans-mem.c
gcc/tree-inline.c
gcc/tree-sra.c
gcc/tree.c
gcc/tree.h

index 893eb20..bc8e97a 100644 (file)
@@ -1,3 +1,27 @@
+2012-01-11  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * tree.h (build_function_decl_skip_args): Add boolean parameter.
+       (build_function_type_skip_args): Delete.
+       * tree.c (build_function_type_skip_args): Make static and add
+       SKIP_RETURN parameter.  Fix thinko in the handling of variants.
+       (build_function_decl_skip_args): Add SKIP_RETURN parameter and
+       pass it to build_function_type_skip_args.
+       * cgraph.h (cgraph_function_versioning): Add boolean parameter.
+       (tree_function_versioning): Likewise.
+       * cgraph.c (cgraph_create_virtual_clone): Adjust call to
+       build_function_decl_skip_args.
+       * cgraphunit.c (cgraph_function_versioning): Add SKIP_RETURN parameter
+       and pass it to build_function_decl_skip_args/tree_function_versioning.
+       (cgraph_materialize_clone): Adjust call to tree_function_versioning.
+       * ipa-inline-transform.c (save_inline_function_body): Likewise.
+       * trans-mem.c (ipa_tm_create_version): Likewise.
+       * tree-sra.c (modify_function): Ditto for cgraph_function_versioning.
+       * tree-inline.c (declare_return_variable): Remove always-true test.
+       (tree_function_versioning): Add SKIP_RETURN parameter.  If the function
+       returns non-void and SKIP_RETURN, create a void-typed RESULT_DECL.
+       * ipa-split.c (split_function): Skip the return value for the split
+       part if it doesn't return.
+
 2012-01-11  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        PR tree-optimization/49642
index e65ddef..9cc3690 100644 (file)
@@ -2246,7 +2246,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
   if (!args_to_skip)
     new_decl = copy_node (old_decl);
   else
-    new_decl = build_function_decl_skip_args (old_decl, args_to_skip);
+    new_decl = build_function_decl_skip_args (old_decl, args_to_skip, false);
   DECL_STRUCT_FUNCTION (new_decl) = NULL;
 
   /* Generate a new name for the new version. */
index 78ab3e1..191364c 100644 (file)
@@ -580,10 +580,10 @@ struct cgraph_node * cgraph_copy_node_for_versioning (struct cgraph_node *,
 struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
                                                VEC(cgraph_edge_p,heap)*,
                                                VEC(ipa_replace_map_p,gc)*,
-                                               bitmap, bitmap, basic_block,
-                                               const char *);
-void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*, bool, bitmap,
-                              bitmap, basic_block);
+                                               bitmap, bool, bitmap,
+                                               basic_block, const char *);
+void tree_function_versioning (tree, tree, VEC (ipa_replace_map_p,gc)*,
+                              bool, bitmap, bool, bitmap, basic_block);
 void record_references_in_initializer (tree, bool);
 bool cgraph_process_new_functions (void);
 void cgraph_process_same_body_aliases (void);
index 2c9c8dd..6ea40ce 100644 (file)
@@ -2333,17 +2333,21 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version,
     TREE_MAP is a mapping of tree nodes we want to replace with
     new ones (according to results of prior analysis).
     OLD_VERSION_NODE is the node that is versioned.
-    It returns the new version's cgraph node.
+
     If non-NULL ARGS_TO_SKIP determine function parameters to remove
     from new version.
+    If SKIP_RETURN is true, the new version will return void.
     If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
-    If non_NULL NEW_ENTRY determine new entry BB of the clone.  */
+    If non_NULL NEW_ENTRY determine new entry BB of the clone.
+
+    Return the new version's cgraph node.  */
 
 struct cgraph_node *
 cgraph_function_versioning (struct cgraph_node *old_version_node,
                            VEC(cgraph_edge_p,heap) *redirect_callers,
                            VEC (ipa_replace_map_p,gc)* tree_map,
                            bitmap args_to_skip,
+                           bool skip_return,
                            bitmap bbs_to_copy,
                            basic_block new_entry_block,
                            const char *clone_name)
@@ -2357,12 +2361,12 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
 
   gcc_assert (old_version_node->local.can_change_signature || !args_to_skip);
 
-  /* Make a new FUNCTION_DECL tree node for the
-     new version. */
-  if (!args_to_skip)
+  /* Make a new FUNCTION_DECL tree node for the new version. */
+  if (!args_to_skip && !skip_return)
     new_decl = copy_node (old_decl);
   else
-    new_decl = build_function_decl_skip_args (old_decl, args_to_skip);
+    new_decl
+      = build_function_decl_skip_args (old_decl, args_to_skip, skip_return);
 
   /* Generate a new name for the new version. */
   DECL_NAME (new_decl) = clone_function_name (old_decl, clone_name);
@@ -2381,7 +2385,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node,
 
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
   tree_function_versioning (old_decl, new_decl, tree_map, false, args_to_skip,
-                           bbs_to_copy, new_entry_block);
+                           skip_return, bbs_to_copy, new_entry_block);
 
   /* Update the new version's properties.
      Make The new version visible only within this translation unit.  Make sure
@@ -2412,7 +2416,8 @@ cgraph_materialize_clone (struct cgraph_node *node)
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
   tree_function_versioning (node->clone_of->decl, node->decl,
                            node->clone.tree_map, true,
-                           node->clone.args_to_skip, NULL, NULL);
+                           node->clone.args_to_skip, false,
+                           NULL, NULL);
   if (cgraph_dump_file)
     {
       dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags);
index 6eb8e73..8196a13 100644 (file)
@@ -324,7 +324,7 @@ save_inline_function_body (struct cgraph_node *node)
 
   /* Copy the OLD_VERSION_NODE function tree to the new version.  */
   tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL,
-                           NULL, NULL);
+                           false, NULL, NULL);
 
   /* The function will be short lived and removed after we inline all the clones,
      but make it internal so we won't confuse ourself.  */
index 6195f81..09e04af 100644 (file)
@@ -1191,6 +1191,7 @@ split_function (struct split_point *split_point)
   /* Now create the actual clone.  */
   rebuild_cgraph_edges ();
   node = cgraph_function_versioning (cur_node, NULL, NULL, args_to_skip,
+                                    !split_part_return_p,
                                     split_point->split_bbs,
                                     split_point->entry_bb, "part");
   /* For usual cloning it is enough to clear builtin only when signature
index b0f24a3..9724f75 100644 (file)
@@ -1,3 +1,9 @@
+2012-01-11  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt23.ad[sb]: New test.
+       * gnat.dg/opt23_pkg.ad[sb]: New helper.
+       * gnat.dg/opt24.ad[sb]: New test.
+
 2012-01-11  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
 
        PR tree-optimization/49642
diff --git a/gcc/testsuite/gnat.dg/opt23.adb b/gcc/testsuite/gnat.dg/opt23.adb
new file mode 100644 (file)
index 0000000..e658630
--- /dev/null
@@ -0,0 +1,16 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatn" }
+
+package body Opt23 is
+
+   procedure Proc (Driver : Rec) is
+      R : Path;
+   begin
+      for I in Driver.Step'Range loop
+         R := Get (Driver, 1, Driver.Step (I));
+         R := Get (Driver, 2, Driver.Step (I));
+         R := Get (Driver, 3, Driver.Step (I));
+      end loop;
+   end;
+
+end Opt23;
diff --git a/gcc/testsuite/gnat.dg/opt23.ads b/gcc/testsuite/gnat.dg/opt23.ads
new file mode 100644 (file)
index 0000000..86d1ce6
--- /dev/null
@@ -0,0 +1,7 @@
+with Opt23_Pkg; use Opt23_Pkg;
+
+package Opt23 is
+
+    procedure Proc (Driver : Rec);
+
+end Opt23;
diff --git a/gcc/testsuite/gnat.dg/opt23_pkg.adb b/gcc/testsuite/gnat.dg/opt23_pkg.adb
new file mode 100644 (file)
index 0000000..8a647d5
--- /dev/null
@@ -0,0 +1,8 @@
+package body Opt23_Pkg is
+
+   function Get (R : Rec; I : Positive; M : Natural) return Path is
+   begin
+      return R.Val (I) (M);
+   end;
+
+end Opt23_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt23_pkg.ads b/gcc/testsuite/gnat.dg/opt23_pkg.ads
new file mode 100644 (file)
index 0000000..b4e5f0e
--- /dev/null
@@ -0,0 +1,23 @@
+package Opt23_Pkg is
+
+   function N return Positive;
+   pragma Import (Ada, N);
+
+   type Path is array(1 .. N) of Long_Float;
+   type Path_Vector is array (Positive range <>) of Path;
+   type Path_Vector_P is access all Path_Vector;
+   type Path_Vector_PV is array(Positive range <>) of Path_Vector_P;
+   type Path_Vector_P2 is access all Path_Vector_PV;
+
+   type Vector is array (Positive range <>) of Natural;
+   type Vector_Access is access Vector;
+
+   type Rec is record
+      Val  : Path_Vector_P2;
+      Step : Vector_Access;
+   end record;
+
+   function Get (R : Rec; I : Positive; M : Natural) return Path;
+   pragma Inline (Get);
+
+end Opt23_Pkg;
diff --git a/gcc/testsuite/gnat.dg/opt24.adb b/gcc/testsuite/gnat.dg/opt24.adb
new file mode 100644 (file)
index 0000000..47d7343
--- /dev/null
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-options "-O2 -gnatn" }
+
+package body Opt24 is
+
+   procedure Proc (Driver : Rec) is
+      R : Path;
+   begin
+      for I in Driver.Step'Range loop
+         R := Get (Driver, 1, Driver.Step (I));
+         R := Get (Driver, 2, Driver.Step (I));
+      end loop;
+   end;
+
+end Opt24;
diff --git a/gcc/testsuite/gnat.dg/opt24.ads b/gcc/testsuite/gnat.dg/opt24.ads
new file mode 100644 (file)
index 0000000..093d2d7
--- /dev/null
@@ -0,0 +1,7 @@
+with Opt23_Pkg; use Opt23_Pkg;
+
+package Opt24 is
+
+    procedure Proc (Driver : Rec);
+
+end Opt24;
index 8780825..db1c2ec 100644 (file)
@@ -4311,7 +4311,7 @@ ipa_tm_create_version (struct cgraph_node *old_node)
          DECL_WEAK (new_decl) = 0;
        }
 
-      tree_function_versioning (old_decl, new_decl, NULL, false, NULL,
+      tree_function_versioning (old_decl, new_decl, NULL, false, NULL, false,
                                NULL, NULL);
     }
 
index c6ae65e..a039890 100644 (file)
@@ -2809,9 +2809,8 @@ declare_return_variable (copy_body_data *id, tree return_slot, tree modify_dest,
   else
     caller_type = TREE_TYPE (TREE_TYPE (callee));
 
-  /* We don't need to do anything for functions that don't return
-     anything.  */
-  if (!result || VOID_TYPE_P (callee_type))
+  /* We don't need to do anything for functions that don't return anything.  */
+  if (VOID_TYPE_P (callee_type))
     return NULL_TREE;
 
   /* If there was a return slot, then the return value is the
@@ -5040,6 +5039,7 @@ update_clone_info (copy_body_data * id)
 
    If non-NULL ARGS_TO_SKIP determine function parameters to remove
    from new version.
+   If SKIP_RETURN is true, the new version will return void.
    If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
    If non_NULL NEW_ENTRY determine new entry BB of the clone.
 */
@@ -5047,7 +5047,8 @@ void
 tree_function_versioning (tree old_decl, tree new_decl,
                          VEC(ipa_replace_map_p,gc)* tree_map,
                          bool update_clones, bitmap args_to_skip,
-                         bitmap blocks_to_copy, basic_block new_entry)
+                         bool skip_return, bitmap blocks_to_copy,
+                         basic_block new_entry)
 {
   struct cgraph_node *old_version_node;
   struct cgraph_node *new_version_node;
@@ -5200,7 +5201,18 @@ tree_function_versioning (tree old_decl, tree new_decl,
     /* Add local vars.  */
     add_local_variables (DECL_STRUCT_FUNCTION (old_decl), cfun, &id, false);
 
-  if (DECL_RESULT (old_decl) != NULL_TREE)
+  if (VOID_TYPE_P (TREE_TYPE (DECL_RESULT (old_decl))))
+    ;
+  else if (skip_return)
+    {
+      DECL_RESULT (new_decl)
+       = build_decl (DECL_SOURCE_LOCATION (DECL_RESULT (old_decl)),
+                     RESULT_DECL, NULL_TREE, void_type_node);
+      DECL_CONTEXT (DECL_RESULT (new_decl)) = new_decl;
+      cfun->returns_struct = 0;
+      cfun->returns_pcc_struct = 0;
+    }
+  else
     {
       tree old_name;
       DECL_RESULT (new_decl) = remap_decl (DECL_RESULT (old_decl), &id);
index 600f4d7..9c2d138 100644 (file)
@@ -4700,7 +4700,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments)
   current_function_decl = NULL_TREE;
 
   new_node = cgraph_function_versioning (node, redirect_callers, NULL, NULL,
-                                        NULL, NULL, "isra");
+                                        false, NULL, NULL, "isra");
   current_function_decl = new_node->decl;
   push_cfun (DECL_STRUCT_FUNCTION (new_node->decl));
 
index 76488f7..ec78616 100644 (file)
@@ -7567,10 +7567,12 @@ build_function_type (tree value_type, tree arg_types)
   return t;
 }
 
-/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.  */
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP and the
+   return value if SKIP_RETURN is true.  */
 
-tree
-build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
+static tree
+build_function_type_skip_args (tree orig_type, bitmap args_to_skip,
+                              bool skip_return)
 {
   tree new_type = NULL;
   tree args, new_args = NULL, t;
@@ -7579,7 +7581,7 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
 
   for (args = TYPE_ARG_TYPES (orig_type); args && args != void_list_node;
        args = TREE_CHAIN (args), i++)
-    if (!bitmap_bit_p (args_to_skip, i))
+    if (!args_to_skip || !bitmap_bit_p (args_to_skip, i))
       new_args = tree_cons (NULL_TREE, TREE_VALUE (args), new_args);
 
   new_reversed = nreverse (new_args);
@@ -7597,6 +7599,7 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
      When we are asked to remove it, we need to build new FUNCTION_TYPE
      instead.  */
   if (TREE_CODE (orig_type) != METHOD_TYPE
+      || !args_to_skip
       || !bitmap_bit_p (args_to_skip, 0))
     {
       new_type = build_distinct_type_copy (orig_type);
@@ -7610,11 +7613,15 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
       TYPE_CONTEXT (new_type) = TYPE_CONTEXT (orig_type);
     }
 
+  if (skip_return)
+    TREE_TYPE (new_type) = void_type_node;
+
   /* This is a new type, not a copy of an old type.  Need to reassociate
      variants.  We can handle everything except the main variant lazily.  */
   t = TYPE_MAIN_VARIANT (orig_type);
-  if (orig_type != t)
+  if (t != orig_type)
     {
+      t = build_function_type_skip_args (t, args_to_skip, skip_return);
       TYPE_MAIN_VARIANT (new_type) = t;
       TYPE_NEXT_VARIANT (new_type) = TYPE_NEXT_VARIANT (t);
       TYPE_NEXT_VARIANT (t) = new_type;
@@ -7624,33 +7631,40 @@ build_function_type_skip_args (tree orig_type, bitmap args_to_skip)
       TYPE_MAIN_VARIANT (new_type) = new_type;
       TYPE_NEXT_VARIANT (new_type) = NULL;
     }
+
   return new_type;
 }
 
-/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.
+/* Build variant of function decl ORIG_DECL skipping ARGS_TO_SKIP and the
+   return value if SKIP_RETURN is true.
 
    Arguments from DECL_ARGUMENTS list can't be removed now, since they are
    linked by TREE_CHAIN directly.  The caller is responsible for eliminating
    them when they are being duplicated (i.e. copy_arguments_for_versioning).  */
 
 tree
-build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip)
+build_function_decl_skip_args (tree orig_decl, bitmap args_to_skip,
+                              bool skip_return)
 {
   tree new_decl = copy_node (orig_decl);
   tree new_type;
 
   new_type = TREE_TYPE (orig_decl);
-  if (prototype_p (new_type))
-    new_type = build_function_type_skip_args (new_type, args_to_skip);
+  if (prototype_p (new_type)
+      || (skip_return && !VOID_TYPE_P (TREE_TYPE (new_type))))
+    new_type
+      = build_function_type_skip_args (new_type, args_to_skip, skip_return);
   TREE_TYPE (new_decl) = new_type;
 
   /* For declarations setting DECL_VINDEX (i.e. methods)
      we expect first argument to be THIS pointer.   */
-  if (bitmap_bit_p (args_to_skip, 0))
+  if (args_to_skip && bitmap_bit_p (args_to_skip, 0))
     DECL_VINDEX (new_decl) = NULL_TREE;
 
   /* When signature changes, we need to clear builtin info.  */
-  if (DECL_BUILT_IN (new_decl) && !bitmap_empty_p (args_to_skip))
+  if (DECL_BUILT_IN (new_decl)
+      && args_to_skip
+      && !bitmap_empty_p (args_to_skip))
     {
       DECL_BUILT_IN_CLASS (new_decl) = NOT_BUILT_IN;
       DECL_FUNCTION_CODE (new_decl) = (enum built_in_function) 0;
index 2ea03a0..3f9fdbc 100644 (file)
@@ -4386,8 +4386,7 @@ extern tree build_nonshared_array_type (tree, tree);
 extern tree build_array_type_nelts (tree, unsigned HOST_WIDE_INT);
 extern tree build_function_type (tree, tree);
 extern tree build_function_type_list (tree, ...);
-extern tree build_function_type_skip_args (tree, bitmap);
-extern tree build_function_decl_skip_args (tree, bitmap);
+extern tree build_function_decl_skip_args (tree, bitmap, bool);
 extern tree build_varargs_function_type_list (tree, ...);
 extern tree build_function_type_array (tree, int, tree *);
 extern tree build_varargs_function_type_array (tree, int, tree *);