[Ada] Inlining subprogram instances

Arnaud Charlet charlet@adacore.com
Fri Aug 1 08:20:00 GMT 2008


The back-end can only inline calls if the unit containing the body to inline
is presented to it before any calls. If a generic subprogram carries an
inline pragma, we generate the instance of the body even when the instance is
not in the main unit, because an inlined call to it might be. This processing
now extends to the case where the pragma applies to the instance itself rather
than to the original generic.

The following must compile quietly:

gcc -c -gnatn -O2 -Winline set_readonly_test.adb

with System_Types;
procedure Set_Readonly_Test is
  I1, I2 : constant System_Types.Integer_T := 1;
  B2 : constant Boolean := System_Types.Compare (I1, I2);
  B3 : constant Boolean := System_Types.Compare2 (I1, I2);
  pragma Unreferenced (B2, B3);
begin
  null;
end Set_Readonly_Test;
---
function Compare_G (Left,Right : Discrete_T) return Boolean is
begin
  if Left = Right then
    return True;
  else
    return False;
  end if;
end;
---
generic
  type Discrete_T is (<>);
function Compare_G (Left,Right : Discrete_T) return Boolean;
---
package body System_Types is
  function Compare2 (Left, Right : Integer_T) return Boolean is
  begin
    if Left = Right then
      return True;
    else
      return False;
    end if;
  end;
end;
---
with Compare_G;
package System_Types is
  type Integer_T is range -2 ** 31 .. 2 ** 31 - 1;
  for Integer_T'Size use 32;
  function Compare is new Compare_G (Integer_T);
  pragma Inline (Compare);
  function Compare2 (Left, Right : Integer_T) return Boolean;
  pragma Inline (Compare2);
end System_Types;

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

2008-08-01  Ed Schonberg  <schonberg@adacore.com>

	* sem_ch12.ads (Need_Subprogram_Instance_Body): new function, to create
	a pending instantiation for the body of a subprogram that is to be
	inlined.

	* sem_ch12.adb:
	(Analyze_Subprogram_Instantiation): use Need_Subprogram_Instance_Body.

	* sem_prag.adb (Make_Inline): If the pragma applies to an instance,
	create a pending instance for its body, so that calls to the subprogram
	can be inlined by the back-end.

-------------- next part --------------
Index: sem_prag.adb
===================================================================
--- sem_prag.adb	(revision 138473)
+++ sem_prag.adb	(working copy)
@@ -53,6 +53,7 @@ with Sem_Aux;  use Sem_Aux;
 with Sem_Ch3;  use Sem_Ch3;
 with Sem_Ch6;  use Sem_Ch6;
 with Sem_Ch8;  use Sem_Ch8;
+with Sem_Ch12; use Sem_Ch12;
 with Sem_Ch13; use Sem_Ch13;
 with Sem_Dist; use Sem_Dist;
 with Sem_Elim; use Sem_Elim;
@@ -3752,6 +3753,22 @@ package body Sem_Prag is
                     and then Present (Corresponding_Body (Decl))
                   then
                      Set_Inline_Flags (Corresponding_Body (Decl));
+
+                  elsif Is_Generic_Instance (Subp) then
+
+                     --  Indicate that the body needs to be created for
+                     --  inlining subsequent calls. The instantiation
+                     --  node follows the declaration of the wrapper
+                     --  package created for it.
+
+                     if Scope (Subp) /= Standard_Standard
+                       and then
+                         Need_Subprogram_Instance_Body
+                          (Next (Unit_Declaration_Node (Scope (Alias (Subp)))),
+                              Subp)
+                     then
+                        null;
+                     end if;
                   end if;
                end if;
 
Index: sem_ch12.adb
===================================================================
--- sem_ch12.adb	(revision 138451)
+++ sem_ch12.adb	(working copy)
@@ -3753,6 +3753,38 @@ package body Sem_Ch12 is
       Analyze_Subprogram_Instantiation (N, E_Procedure);
    end Analyze_Procedure_Instantiation;
 
+   -----------------------------------
+   -- Need_Subprogram_Instance_Body --
+   -----------------------------------
+
+   function Need_Subprogram_Instance_Body
+     (N    : Node_Id;
+      Subp : Entity_Id) return Boolean
+   is
+   begin
+      if (Is_In_Main_Unit (N)
+            or else Is_Inlined (Subp)
+            or else Is_Inlined (Alias (Subp)))
+        and then (Operating_Mode = Generate_Code
+                    or else (Operating_Mode = Check_Semantics
+                               and then ASIS_Mode))
+        and then (Expander_Active or else ASIS_Mode)
+        and then not ABE_Is_Certain (N)
+        and then not Is_Eliminated (Subp)
+      then
+         Pending_Instantiations.Append
+           ((Inst_Node                => N,
+             Act_Decl                 => Unit_Declaration_Node (Subp),
+             Expander_Status          => Expander_Active,
+             Current_Sem_Unit         => Current_Sem_Unit,
+             Scope_Suppress           => Scope_Suppress,
+             Local_Suppress_Stack_Top => Local_Suppress_Stack_Top));
+         return True;
+      else
+         return False;
+      end if;
+   end Need_Subprogram_Instance_Body;
+
    --------------------------------------
    -- Analyze_Subprogram_Instantiation --
    --------------------------------------
@@ -4144,22 +4176,7 @@ package body Sem_Ch12 is
             --  If the context requires a full instantiation, mark node for
             --  subsequent construction of the body.
 
-            if (Is_In_Main_Unit (N)
-                  or else Is_Inlined (Act_Decl_Id))
-              and then (Operating_Mode = Generate_Code
-                          or else (Operating_Mode = Check_Semantics
-                                     and then ASIS_Mode))
-              and then (Expander_Active or else ASIS_Mode)
-              and then not ABE_Is_Certain (N)
-              and then not Is_Eliminated (Act_Decl_Id)
-            then
-               Pending_Instantiations.Append
-                 ((Inst_Node                => N,
-                   Act_Decl                 => Act_Decl,
-                   Expander_Status          => Expander_Active,
-                   Current_Sem_Unit         => Current_Sem_Unit,
-                   Scope_Suppress           => Scope_Suppress,
-                   Local_Suppress_Stack_Top => Local_Suppress_Stack_Top));
+            if Need_Subprogram_Instance_Body (N, Act_Decl_Id) then
 
                Check_Forward_Instantiation (Gen_Decl);
 
@@ -8699,6 +8716,13 @@ package body Sem_Ch12 is
    begin
       Gen_Body_Id := Corresponding_Body (Gen_Decl);
 
+      --  Subprogram body may have been created already because of
+      --  an inline pragma.
+
+      if Present (Corresponding_Body (Act_Decl)) then
+         return;
+      end if;
+
       Expander_Mode_Save_And_Set (Body_Info.Expander_Status);
 
       --  Re-establish the state of information on which checks are suppressed.
Index: sem_ch12.ads
===================================================================
--- sem_ch12.ads	(revision 138451)
+++ sem_ch12.ads	(working copy)
@@ -106,6 +106,16 @@ package Sem_Ch12 is
    --  function and procedure instances. The flag Body_Optional has the
    --  same purpose as described for Instantiate_Package_Body.
 
+   function Need_Subprogram_Instance_Body
+     (N    : Node_Id;
+      Subp : Entity_Id) return Boolean;
+
+   --  If a subprogram instance is inlined, indicate that the body of it
+   --  must be created, to be used in inlined calls by the back-end. The
+   --  subprogram may be inlined because the generic itself carries the
+   --  pragma, or because a pragma appears for the instance in the scope.
+   --  of the instance.
+
    procedure Save_Global_References (N : Node_Id);
    --  Traverse the original generic unit, and capture all references to
    --  entities that are defined outside of the generic in the analyzed


More information about the Gcc-patches mailing list