[Ada] Avoid use of secondary stack

2015-05-28 Thread Arnaud Charlet
This patch avoids the use of the secondary stack, and the corresponding cleanup
handlers, in many cases. For example, access discriminants no longer force
functions to return on the secondary stack. This is a speed improvement.
It is particularly relevant to the Ada.Containers.

Tested on x86_64-pc-linux-gnu, committed on trunk

2015-05-28  Bob Duff  d...@adacore.com

* sem_util.adb (Requires_Transient_Scope): Avoid returning
function results on the secondary stack in so many cases.

Index: sem_util.adb
===
--- sem_util.adb(revision 223813)
+++ sem_util.adb(working copy)
@@ -16951,14 +16951,50 @@
--
 
--  A transient scope is required when variable-sized temporaries are
-   --  allocated in the primary or secondary stack, or when finalization
-   --  actions must be generated before the next instruction.
+   --  allocated on the secondary stack, or when finalization actions must be
+   --  generated before the next instruction.
 
+   function Old_Requires_Transient_Scope (Id : Entity_Id) return Boolean;
+   function New_Requires_Transient_Scope (Id : Entity_Id) return Boolean;
+   --  ???We retain the old and new algorithms for Requires_Transient_Scope for
+   --  the time being. New_Requires_Transient_Scope is used by default; the
+   --  debug switch -gnatdQ can be used to do Old_Requires_Transient_Scope
+   --  instead. The intent is to use this temporarily to measure before/after
+   --  efficiency. Note: when this temporary code is removed, the documentation
+   --  of dQ in debug.adb should be removed.
+
function Requires_Transient_Scope (Id : Entity_Id) return Boolean is
+  Old_Result : constant Boolean := Old_Requires_Transient_Scope (Id);
+
+   begin
+  if Debug_Flag_QQ then
+ return Old_Result;
+  end if;
+
+  declare
+ New_Result : constant Boolean := New_Requires_Transient_Scope (Id);
+
+  begin
+ --  Assert that we're not putting things on the secondary stack if we
+ --  didn't before; we are trying to AVOID secondary stack when
+ --  possible.
+
+ if not Old_Result then
+pragma Assert (not New_Result);
+null;
+ end if;
+
+ return New_Result;
+  end;
+   end Requires_Transient_Scope;
+
+   --
+   -- Old_Requires_Transient_Scope --
+   --
+
+   function Old_Requires_Transient_Scope (Id : Entity_Id) return Boolean is
   Typ : constant Entity_Id := Underlying_Type (Id);
 
-   --  Start of processing for Requires_Transient_Scope
-
begin
   --  This is a private type which is not completed yet. This can only
   --  happen in a default expression (of a formal parameter or of a
@@ -16989,9 +17025,7 @@
   --  returned value is allocated on the secondary stack. Controlled
   --  type temporaries need finalization.
 
-  elsif Is_Tagged_Type (Typ)
-or else Has_Controlled_Component (Typ)
-  then
+  elsif Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then
  return not Is_Value_Type (Typ);
 
   --  Record type
@@ -16999,18 +17033,20 @@
   elsif Is_Record_Type (Typ) then
  declare
 Comp : Entity_Id;
+
  begin
 Comp := First_Entity (Typ);
 while Present (Comp) loop
if Ekind (Comp) = E_Component then
+
   --  ???It's not clear we need a full recursive call to
-  --  Requires_Transient_Scope here. Note that the following
-  --  can't happen.
+  --  Old_Requires_Transient_Scope here. Note that the
+  --  following can't happen.
 
   pragma Assert (Is_Definite_Subtype (Etype (Comp)));
   pragma Assert (not Has_Controlled_Component (Etype (Comp)));
 
-  if Requires_Transient_Scope (Etype (Comp)) then
+  if Old_Requires_Transient_Scope (Etype (Comp)) then
  return True;
   end if;
end if;
@@ -17033,7 +17069,7 @@
 
  --  If component type requires a transient scope, the array does too
 
- if Requires_Transient_Scope (Component_Type (Typ)) then
+ if Old_Requires_Transient_Scope (Component_Type (Typ)) then
 return True;
 
  --  Otherwise, we only need a transient scope if the size depends on
@@ -17049,8 +17085,133 @@
  pragma Assert (Is_Protected_Type (Typ) or else Is_Task_Type (Typ));
  return False;
   end if;
-   end Requires_Transient_Scope;
+   end Old_Requires_Transient_Scope;
 
+   --
+   -- New_Requires_Transient_Scope --
+   --
+
+   function New_Requires_Transient_Scope (Id : Entity_Id) return Boolean is
+
+  function 

[Ada] Avoid use of secondary stack

2015-05-28 Thread Arnaud Charlet
This patch avoids the use of the secondary stack, and the corresponding cleanup
handlers, in many cases. For example, access discriminants no longer force
functions to return on the secondary stack. This is a speed improvement.
It is particularly relevant to the Ada.Containers.

Tested on x86_64-pc-linux-gnu, committed on trunk

2015-05-28  Bob Duff  d...@adacore.com

* sem_util.adb (Requires_Transient_Scope): For definite untagged
subtypes, we should never have to use the secondary stack. This moves
toward that goal. But there are still cases that don't work.
Here, we move the check for Is_Definite first, but add a
special-purpose check for Has_Discrim_Dep_Array.

Index: sem_util.adb
===
--- sem_util.adb(revision 223814)
+++ sem_util.adb(working copy)
@@ -17103,6 +17103,11 @@
   --  could be nested inside some other record that is constrained by
   --  nondiscriminants). That is, the recursive calls are too conservative.
 
+  function Has_Discrim_Dep_Array (Typ : Entity_Id) return Boolean;
+  --  True if we find certain discriminant-dependent array
+  --  subcomponents. This shouldn't be necessary, but without this check,
+  --  we crash in gimplify. ???
+
   function Caller_Known_Size_Record (Typ : Entity_Id) return Boolean is
  pragma Assert (Typ = Underlying_Type (Typ));
 
@@ -17150,8 +17155,50 @@
  return True;
   end Caller_Known_Size_Record;
 
-  --  Local deeclarations
+  function Has_Discrim_Dep_Array (Typ : Entity_Id) return Boolean is
+ pragma Assert (Typ = Underlying_Type (Typ));
 
+  begin
+ if Is_Array_Type (Typ) then
+return Size_Depends_On_Discriminant (Typ);
+ end if;
+
+ if Is_Record_Type (Typ)
+   or else
+   Is_Protected_Type (Typ)
+ then
+declare
+   Comp : Entity_Id := First_Entity (Typ);
+
+begin
+   while Present (Comp) loop
+
+  --  Only look at E_Component entities. No need to look at
+  --  E_Discriminant entities, and we must ignore internal
+  --  subtypes generated for constrained components.
+
+  if Ekind (Comp) = E_Component then
+ declare
+Comp_Type : constant Entity_Id :=
+  Underlying_Type (Etype (Comp));
+
+ begin
+if Has_Discrim_Dep_Array (Comp_Type) then
+   return True;
+end if;
+ end;
+  end if;
+
+  Next_Entity (Comp);
+   end loop;
+end;
+ end if;
+
+ return False;
+  end Has_Discrim_Dep_Array;
+
+  --  Local declarations
+
   Typ : constant Entity_Id := Underlying_Type (Id);
 
--  Start of processing for New_Requires_Transient_Scope
@@ -17184,26 +17231,26 @@
   elsif Is_Tagged_Type (Typ) or else Has_Controlled_Component (Typ) then
  return not Is_Value_Type (Typ);
 
-  --  Indefinite (discriminated) untagged record or protected type
-
-  elsif Is_Record_Type (Typ) or else Is_Protected_Type (Typ) then
- return not Caller_Known_Size_Record (Typ);
- --  ???Should come after Is_Definite_Subtype below
-
   --  Untagged definite subtypes are known size. This includes all
   --  elementary [sub]types. Tasks are known size even if they have
   --  discriminants.
 
   elsif Is_Definite_Subtype (Typ) or else Is_Task_Type (Typ) then
- if Is_Array_Type (Typ) -- ???Shouldn't be necessary
-   and then New_Requires_Transient_Scope
-  (Underlying_Type (Component_Type (Typ)))
- then
-return True;
+ if Is_Record_Type (Typ) or else Is_Protected_Type (Typ) then
+if not Has_Discriminants (Typ) then
+   if Has_Discrim_Dep_Array (Typ) then
+  return True; -- ???Shouldn't be necessary
+   end if;
+end if;
  end if;
 
  return False;
 
+  --  Indefinite (discriminated) untagged record or protected type
+
+  elsif Is_Record_Type (Typ) or else Is_Protected_Type (Typ) then
+ return not Caller_Known_Size_Record (Typ);
+
   --  Unconstrained array
 
   else


Re: [Ada] Avoid use of secondary stack

2015-05-28 Thread Eric Botcazou
 This patch avoids the use of the secondary stack, and the corresponding
 cleanup handlers, in many cases. For example, access discriminants no
 longer force functions to return on the secondary stack. This is a speed
 improvement. It is particularly relevant to the Ada.Containers.

It also uncovered a buglet in gigi, fixed thusly, applied on the mainline.


2015-05-28  Eric Botcazou  ebotca...@adacore.com

* gcc-interface/decl.c (gnat_to_gnu_entity) E_Subprogram_Type: Do
not error out on a return type which has a size that overflows if the
return is done by invisible reference.


-- 
Eric BotcazouIndex: gcc-interface/decl.c
===
--- gcc-interface/decl.c	(revision 223834)
+++ gcc-interface/decl.c	(working copy)
@@ -4224,7 +4224,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entit
 	/* If the return type has a size that overflows, we cannot have
 	   a function that returns that type.  This usage doesn't make
 	   sense anyway, so give an error here.  */
-	if (TYPE_SIZE_UNIT (gnu_return_type)
+	if (!return_by_invisi_ref_p
+		 TYPE_SIZE_UNIT (gnu_return_type)
 		 TREE_CODE (TYPE_SIZE_UNIT (gnu_return_type)) == INTEGER_CST
 		 !valid_constant_size_p (TYPE_SIZE_UNIT (gnu_return_type)))
 	  {