diff mbox

[Ada] Use out-of-line string concatenation at library level

Message ID 20170425094307.GA130752@adacore.com
State New
Headers show

Commit Message

Arnaud Charlet April 25, 2017, 9:43 a.m. UTC
String concatenation can be implemented either in-line or out-of-line by the
compiler, depending on the optimization level and other factors.  But doing
in-line concatenation at library level is undesirable in general and the
compiler already avoids it for simple declarations:

  S : String := S1 & S2;  -- out-of-line at all optimization levels

but not for slightly more complex ones:

  S : String := Ada.Characters.Handling.To_Upper (S1 & S2);

which are implemented in-line for -O1 and above.

This patch changes the second case to using out-of-line concatenation at all
optimization levels which, among other things, generates more compact code.

The following package must always use out-of-line concatenation:

with Ada.Characters.Handling;

package P is

  Scope: constant String := Ada.Characters.Handling.To_Upper ("P");

  function Full_String return String;

end P;

package body P is

  Full_Scope : constant String
    := Ada.Characters.Handling.To_Upper (Scope & ".body");

  function Full_String return String is (Full_Scope);

end P;

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

2017-04-25  Eric Botcazou  <ebotcazou@adacore.com>

	* exp_ch4.adb (Library_Level_Target): New function.
	(Expand_Concatenate): When optimization is enabled, also expand
	the operation out-of-line if the concatenation is present within
	the expression of the declaration of a library-level object and
	not only if it is the expression of the declaration.
diff mbox

Patch

Index: exp_ch4.adb
===================================================================
--- exp_ch4.adb	(revision 247135)
+++ exp_ch4.adb	(working copy)
@@ -2767,6 +2767,10 @@ 
       --  Set True during generation of the assignments of operands into
       --  result once an operand known to be non-null has been seen.
 
+      function Library_Level_Target return Boolean;
+      --  Return True if the concatenation is within the expression of the
+      --  declaration of a library-level object.
+
       function Make_Artyp_Literal (Val : Nat) return Node_Id;
       --  This function makes an N_Integer_Literal node that is returned in
       --  analyzed form with the type set to Artyp. Importantly this literal
@@ -2782,6 +2786,30 @@ 
       function To_Ityp (X : Node_Id) return Node_Id;
       --  The inverse function (uses Val in the case of enumeration types)
 
+      --------------------------
+      -- Library_Level_Target --
+      --------------------------
+
+      function Library_Level_Target return Boolean is
+         P : Node_Id := Parent (Cnode);
+
+      begin
+         while Present (P) loop
+            if Nkind (P) = N_Object_Declaration then
+               return Is_Library_Level_Entity (Defining_Identifier (P));
+
+            --  Prevent the search from going too far
+
+            elsif Is_Body_Or_Package_Declaration (P) then
+               return False;
+            end if;
+
+            P := Parent (P);
+         end loop;
+
+         return False;
+      end Library_Level_Target;
+
       ------------------------
       -- Make_Artyp_Literal --
       ------------------------
@@ -2842,16 +2870,6 @@ 
 
       --  Local Declarations
 
-      Lib_Level_Target : constant Boolean :=
-        Nkind (Parent (Cnode)) = N_Object_Declaration
-          and then
-            Is_Library_Level_Entity (Defining_Identifier (Parent (Cnode)));
-
-      --  If the concatenation declares a library level entity, we call the
-      --  built-in concatenation routines to prevent code bloat, regardless
-      --  of optimization level. This is space-efficient, and prevent linking
-      --  problems when units are compiled with different optimizations.
-
       Opnd_Typ : Entity_Id;
       Ent      : Entity_Id;
       Len      : Uint;
@@ -3372,22 +3390,27 @@ 
 
       --    There are nine or fewer retained (non-null) operands
 
-      --    The optimization level is -O0
+      --    The optimization level is -O0 or the debug flag gnatd.C is set,
+      --    and the debug flag gnatd.c is not set.
 
       --    The corresponding System.Concat_n.Str_Concat_n routine is
       --    available in the run time.
 
-      --    The debug flag gnatd.c is not set
-
       --  If all these conditions are met then we generate a call to the
       --  relevant concatenation routine. The purpose of this is to avoid
       --  undesirable code bloat at -O0.
 
+      --  If the concatenation is within the declaration of a library-level
+      --  object, we call the built-in concatenation routines to prevent code
+      --  bloat, regardless of the optimization level. This is space efficient
+      --  and prevents linking problems when units are compiled with different
+      --  optimization levels.
+
       if Atyp = Standard_String
         and then NN in 2 .. 9
-        and then (Lib_Level_Target
-          or else ((Optimization_Level = 0 or else Debug_Flag_Dot_CC)
-                     and then not Debug_Flag_Dot_C))
+        and then (((Optimization_Level = 0 or else Debug_Flag_Dot_CC)
+                     and then not Debug_Flag_Dot_C)
+                  or else Library_Level_Target)
       then
          declare
             RR : constant array (Nat range 2 .. 9) of RE_Id :=