From: Eric Botcazou Date: Mon, 29 Feb 2016 09:16:57 +0000 (+0000) Subject: trans.c (finalize_nrv_r): Remove obsolete code. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5d2a63dc7bb7942ba287323d89cdf622015c1e39;p=gcc.git trans.c (finalize_nrv_r): Remove obsolete code. * gcc-interface/trans.c (finalize_nrv_r): Remove obsolete code. (build_return_expr): Likewise. (Call_to_gnu): If this is a function call and there is no target, create a temporary for the return value for all aggregate types, but never create it for a return statement. Push a binding level around the call in more cases. Remove obsolete code. From-SVN: r233805 --- diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 49c0632ef04..9fcf75ccf6e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,12 @@ +2016-02-29 Eric Botcazou + + * gcc-interface/trans.c (finalize_nrv_r): Remove obsolete code. + (build_return_expr): Likewise. + (Call_to_gnu): If this is a function call and there is no target, + create a temporary for the return value for all aggregate types, + but never create it for a return statement. Push a binding level + around the call in more cases. Remove obsolete code. + 2016-02-29 Eric Botcazou * gcc-interface/ada-tree.h (DECL_RETURN_VALUE_P): New macro. diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index f830a3d2490..c78b01b177a 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -3330,32 +3330,14 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data) else if (TREE_CODE (t) == RETURN_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == INIT_EXPR) { - tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1), init_expr; - - /* If this is the temporary created for a return value with variable - size in Call_to_gnu, we replace the RHS with the init expression. */ - if (TREE_CODE (ret_val) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR - && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0) - == TREE_OPERAND (ret_val, 1)) - { - init_expr = TREE_OPERAND (TREE_OPERAND (ret_val, 0), 1); - ret_val = TREE_OPERAND (ret_val, 1); - } - else - init_expr = NULL_TREE; + tree ret_val = TREE_OPERAND (TREE_OPERAND (t, 0), 1); /* Strip useless conversions around the return value. */ if (gnat_useless_type_conversion (ret_val)) ret_val = TREE_OPERAND (ret_val, 0); if (is_nrv_p (dp->nrv, ret_val)) - { - if (init_expr) - TREE_OPERAND (TREE_OPERAND (t, 0), 1) = init_expr; - else - TREE_OPERAND (t, 0) = dp->result; - } + TREE_OPERAND (t, 0) = dp->result; } /* Replace the DECL_EXPR of NRVs with an initialization of the RESULT_DECL, @@ -3659,14 +3641,6 @@ build_return_expr (tree ret_obj, tree ret_val) && TYPE_MODE (operation_type) == BLKmode && aggregate_value_p (operation_type, current_function_decl)) { - /* Recognize the temporary created for a return value with variable - size in Call_to_gnu. We want to eliminate it if possible. */ - if (TREE_CODE (ret_val) == COMPOUND_EXPR - && TREE_CODE (TREE_OPERAND (ret_val, 0)) == INIT_EXPR - && TREE_OPERAND (TREE_OPERAND (ret_val, 0), 0) - == TREE_OPERAND (ret_val, 1)) - ret_val = TREE_OPERAND (ret_val, 1); - /* Strip useless conversions around the return value. */ if (gnat_useless_type_conversion (ret_val)) ret_val = TREE_OPERAND (ret_val, 0); @@ -4314,14 +4288,22 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, because we need to preserve the return value before copying back the parameters. - 2. There is no target and this is neither an object nor a renaming - declaration, and the return type has variable size, because in - these cases the gimplifier cannot create the temporary. + 2. There is no target and the call is made for neither an object nor a + renaming declaration, nor a return statement, and the return type has + variable size, because in this case the gimplifier cannot create the + temporary, or more generally is simply an aggregate type, because the + gimplifier would create the temporary in the outermost scope instead + of locally. 3. There is a target and it is a slice or an array with fixed size, and the return type has variable size, because the gimplifier doesn't handle these cases. + 4. There is no target and we have misaligned In Out or Out parameters + passed by reference, because we need to preserve the return value + before copying back the parameters. However, in this case, we'll + defer creating the temporary, see below. + This must be done before we push a binding level around the call, since we will pop it before copying the return value. */ if (function_call @@ -4329,7 +4311,9 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, || (!gnu_target && Nkind (Parent (gnat_node)) != N_Object_Declaration && Nkind (Parent (gnat_node)) != N_Object_Renaming_Declaration - && TREE_CODE (TYPE_SIZE (gnu_result_type)) != INTEGER_CST) + && Nkind (Parent (gnat_node)) != N_Simple_Return_Statement + && AGGREGATE_TYPE_P (gnu_result_type) + && !TYPE_IS_FAT_POINTER_P (gnu_result_type)) || (gnu_target && (TREE_CODE (gnu_target) == ARRAY_RANGE_REF || (TREE_CODE (TREE_TYPE (gnu_target)) == ARRAY_TYPE @@ -4341,6 +4325,16 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, DECL_RETURN_VALUE_P (gnu_retval) = 1; } + /* If we don't need a value or have already created it, push a binding level + around the call. This will narrow the lifetime of the temporaries we may + need to make when translating the parameters as much as possible. */ + if (!returning_value || gnu_retval) + { + start_stmt_group (); + gnat_pushlevel (); + pushed_binding_level = true; + } + /* Create the list of the actual parameters as GCC expects it, namely a chain of TREE_LIST nodes in which the TREE_VALUE field of each node is an expression and the TREE_PURPOSE field is null. But skip Out @@ -4469,12 +4463,10 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, DECL_RETURN_VALUE_P (gnu_retval) = 1; } - /* If we haven't pushed a binding level, push a new one. This will - narrow the lifetime of the temporary we are about to make as much - as possible. The drawback is that we'd need to create a temporary - for the return value, if any (see comment before the loop). So do - it only when this temporary was already created just above. */ - if (!pushed_binding_level && !(in_param && returning_value)) + /* If we haven't pushed a binding level, push it now. This will + narrow the lifetime of the temporary we are about to make as + much as possible. */ + if (!pushed_binding_level && (!returning_value || gnu_retval)) { start_stmt_group (); gnat_pushlevel (); @@ -4705,15 +4697,6 @@ Call_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p, tree gnu_target, if (!gnu_retval) { tree gnu_stmt; - /* If we haven't pushed a binding level, push a new one. This - will narrow the lifetime of the temporary we are about to - make as much as possible. */ - if (!pushed_binding_level) - { - start_stmt_group (); - gnat_pushlevel (); - pushed_binding_level = true; - } gnu_call = create_init_temporary ("P", gnu_call, &gnu_stmt, gnat_node); append_to_statement_list (gnu_stmt, &gnu_stmt_list); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d6803dabd74..4e85314e00b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2016-02-29 Eric Botcazou + + * gnat.dg/stack_usage3.adb: New test. + * gnat.dg/stack_usage3_pkg.ads: New helper. + 2016-02-29 Eric Botcazou * gnat.dg/renaming8.adb: New test. diff --git a/gcc/testsuite/gnat.dg/stack_usage3.adb b/gcc/testsuite/gnat.dg/stack_usage3.adb new file mode 100644 index 00000000000..fcc5cacf707 --- /dev/null +++ b/gcc/testsuite/gnat.dg/stack_usage3.adb @@ -0,0 +1,28 @@ +-- { dg-do compile } +-- { dg-options "-O -fstack-usage" } + +with Ada.Text_IO; use Ada.Text_IO; +with Stack_Usage3_Pkg; use Stack_Usage3_Pkg; + +procedure Stack_Usage3 is + +begin + Put_Line (Diag ("Diag line 0")); + Put_Line (Diag ("Diag line 1")); + Put_Line (Diag ("Diag line 2")); + Put_Line (Diag ("Diag line 3")); + Put_Line (Diag ("Diag line 4")); + Put_Line (Diag ("Diag line 5")); + Put_Line (Diag ("Diag line 6")); + Put_Line (Diag ("Diag line 7")); + Put_Line (Diag ("Diag line 8")); + Put_Line (Diag ("Diag line 9")); + Put_Line (Diag ("Diag line 10")); + Put_Line (Diag ("Diag line 11")); + Put_Line (Diag ("Diag line 12")); + Put_Line (Diag ("Diag line 13")); + Put_Line (Diag ("Diag line 14")); +end; + +-- { dg-final { scan-stack-usage "\t\[0-9\]\[0-9\]\t" { target i?86-*-* x86_64-*-* } } } +-- { dg-final { cleanup-stack-usage } } diff --git a/gcc/testsuite/gnat.dg/stack_usage3_pkg.ads b/gcc/testsuite/gnat.dg/stack_usage3_pkg.ads new file mode 100644 index 00000000000..e4a80c3ff71 --- /dev/null +++ b/gcc/testsuite/gnat.dg/stack_usage3_pkg.ads @@ -0,0 +1,7 @@ +package Stack_Usage3_Pkg is + + subtype Small_String is String (1..80); + + function Diag (S : String) return Small_String; + +end Stack_Usage3_Pkg;