Re: [Ada] Fix unexpectedly large frame with calls manipulating strings

2016-03-01 Thread Eric Botcazou
> This new test fails for me with -m32.

Thanks for the heads up, fixed thusly, applied.


2016-03-01  Eric Botcazou  

* gnat.dg/stack_usage3.adb: Robustify and enable for all targets.


-- 
Eric BotcazouIndex: gnat.dg/stack_usage3.adb
===
--- gnat.dg/stack_usage3.adb	(revision 233840)
+++ gnat.dg/stack_usage3.adb	(working copy)
@@ -5,9 +5,7 @@ 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"));
@@ -22,7 +20,13 @@ begin
Put_Line (Diag ("Diag line 12"));
Put_Line (Diag ("Diag line 13"));
Put_Line (Diag ("Diag line 14"));
+   Put_Line (Diag ("Diag line 15"));
+   Put_Line (Diag ("Diag line 16"));
+   Put_Line (Diag ("Diag line 17"));
+   Put_Line (Diag ("Diag line 18"));
+   Put_Line (Diag ("Diag line 19"));
+   Put_Line (Diag ("Diag line 20"));
 end;
 
--- { dg-final { scan-stack-usage "\t\[0-9\]\[0-9\]\t" { target i?86-*-* x86_64-*-* } } }
+-- { dg-final { scan-stack-usage-not "\t\[0-9\]\[0-9\]\[0-9\]\[0-9\]\t" } }
 -- { dg-final { cleanup-stack-usage } }


Re: [Ada] Fix unexpectedly large frame with calls manipulating strings

2016-03-01 Thread Tom de Vries

On 29-02-16 10:17, Eric Botcazou wrote:

Another long-standing regression present in the compiler (dating back to the
Tree-SSA merge): the compiler generates code that has an unexpectedly large
stack usage for nested calls on strings, because the gimplifier creates
temporaries in the outermost scope that have overlapping live ranges.

Tested on x86_64-suse-linux, applied on the mainline.


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  

* gnat.dg/stack_usage3.adb: New test.
* gnat.dg/stack_usage3_pkg.ads: New helper.


Hi,

This new test fails for me with -m32.

Thanks,
- Tom



[Ada] Fix unexpectedly large frame with calls manipulating strings

2016-02-29 Thread Eric Botcazou
Another long-standing regression present in the compiler (dating back to the 
Tree-SSA merge): the compiler generates code that has an unexpectedly large 
stack usage for nested calls on strings, because the gimplifier creates 
temporaries in the outermost scope that have overlapping live ranges.

Tested on x86_64-suse-linux, applied on the mainline.


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  

* gnat.dg/stack_usage3.adb: New test.
* gnat.dg/stack_usage3_pkg.ads: New helper.

-- 
Eric Botcazou-- { 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 } }
package Stack_Usage3_Pkg is

   subtype Small_String is String (1..80);

   function Diag (S : String) return Small_String;

end Stack_Usage3_Pkg;
Index: gcc-interface/trans.c
===
--- gcc-interface/trans.c	(revision 233804)
+++ gcc-interface/trans.c	(working copy)
@@ -3330,32 +3330,14 @@ finalize_nrv_r (tree *tp, int *walk_subt
   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 re
 	  && 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 *gn
 	  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