This is a couple of regressions present on the mainline. For the first
testcase at O2 -gnatn:
+===GNAT BUG DETECTED==+
| 4.7.0 20120102 (experimental) [trunk revision 182780] (i586-suse-linux) GCC
error:|
| in assign_stack_temp_for_type, at function.c:796 |
| Error detected around p1.adb:3:4
For the second testcase:
+===GNAT BUG DETECTED==+
| 4.7.0 20120102 (experimental) [trunk revision 182780] (i586-suse-linux) GCC
error:|
| in declare_return_variable, at tree-inline.c:2904|
| Error detected around p2.adb:3:4
Both are caused by the fnsplit IPA pass being run on a function returning a
variable-sized array. In both cases, the part that isn't inlined is made
up of a single raise statement, i.e. a no-return call. So fnsplit rewrites
the call statement into just:
f.part (arguments);
In the first case, the compilation aborts when the RTL expander attempts to
create a temporary for the return value (which would have variable size)
while, in the second case, it aborts on the assertion:
gcc_assert (TREE_CODE (TYPE_SIZE_UNIT (callee_type)) == INTEGER_CST);
when the inliner attemps to inline the part that wasn't inlined(!).
The proposed fix is to turn the part that isn't inlined into a function that
returns void. This involves straightforward adjustments to the two versioning
machineries (cgraph and tree).
Tested on i586-suse-linux, OK for the mainline?
2012-01-10 Eric Botcazou ebotca...@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): Likewise 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-10 Eric Botcazou ebotca...@adacore.com
* gnat.dg/opt23.ad[sb]: New test.
* gnat.dg/opt23_pkg.ad[sb]: New helper.
* gnat.dg/opt24.ad[sb]: New test.
--
Eric Botcazou
Index: tree.h
===
--- tree.h (revision 182780)
+++ tree.h (working copy)
@@ -4386,8 +4386,7 @@ extern tree build_nonshared_array_type (
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 *);
Index: tree.c
===
--- tree.c (revision 182780)
+++ tree.c (working copy)
@@ -7556,10 +7556,12 @@ build_function_type (tree value_type, tr
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;
@@ -7599,11 +7601,15 @@ build_function_type_skip_args (tree orig
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 =