Re: [patch] Fix ICEs with functions returning variable-sized array

2012-01-11 Thread Richard Guenther
On Tue, Jan 10, 2012 at 8:27 PM, Eric Botcazou ebotca...@adacore.com wrote:
 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?

Ok.

Thanks,
Richard.


 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


[patch] Fix ICEs with functions returning variable-sized array

2012-01-10 Thread Eric Botcazou
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 =