diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-11 18:47:28 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-01-11 18:47:28 +0000 |
commit | 7a3ec97816539146d730f3cd3f0202cafc59684e (patch) | |
tree | f3e48a68df89c7419d086f7a678f0af82c975f18 /gcc | |
parent | aa2edcb90b593dbf9e2123ee4653466ae6823d35 (diff) | |
download | gcc-7a3ec97816539146d730f3cd3f0202cafc59684e.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183102 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 24 | ||||
-rw-r--r-- | gcc/cgraph.c | 2 | ||||
-rw-r--r-- | gcc/cgraph.h | 8 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 21 | ||||
-rw-r--r-- | gcc/ipa-inline-transform.c | 2 | ||||
-rw-r--r-- | gcc/ipa-split.c | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt23.adb | 16 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt23.ads | 7 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt23_pkg.adb | 8 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt23_pkg.ads | 23 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt24.adb | 15 | ||||
-rw-r--r-- | gcc/testsuite/gnat.dg/opt24.ads | 7 | ||||
-rw-r--r-- | gcc/trans-mem.c | 2 | ||||
-rw-r--r-- | gcc/tree-inline.c | 22 | ||||
-rw-r--r-- | gcc/tree-sra.c | 2 | ||||
-rw-r--r-- | gcc/tree.c | 36 | ||||
-rw-r--r-- | gcc/tree.h | 3 |
18 files changed, 171 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 893eb209dbe..bc8e97a023d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index e65ddef8aec..9cc36903a8c 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -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. */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 78ab3e16860..191364ca377 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 2c9c8ddca5a..6ea40ce4e52 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -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); diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index 6eb8e7388cf..8196a137f05 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -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. */ diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 6195f819ec5..09e04af5b88 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b0f24a3fd90..9724f759a67 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 00000000000..e658630a692 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt23.adb @@ -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 index 00000000000..86d1ce65acc --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt23.ads @@ -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 index 00000000000..8a647d507c9 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt23_pkg.adb @@ -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 index 00000000000..b4e5f0ebd6e --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt23_pkg.ads @@ -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 index 00000000000..47d7343e999 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt24.adb @@ -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 index 00000000000..093d2d7ed1a --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt24.ads @@ -0,0 +1,7 @@ +with Opt23_Pkg; use Opt23_Pkg; + +package Opt24 is + + procedure Proc (Driver : Rec); + +end Opt24; diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 8780825c58d..db1c2ec36bc 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -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); } diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index c6ae65e7a42..a0398903834 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -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); diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 600f4d776d1..9c2d13875d9 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -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)); diff --git a/gcc/tree.c b/gcc/tree.c index 76488f7528a..ec78616bd63 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -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; diff --git a/gcc/tree.h b/gcc/tree.h index 2ea03a092f6..3f9fdbceb3f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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 *); |