[Ada] Single-element Append performance improvement

Message ID 20220905072613.GA1174821@poulhies-Precision-5550
State New, archived
Headers
Series [Ada] Single-element Append performance improvement |

Commit Message

Marc Poulhiès Sept. 5, 2022, 7:26 a.m. UTC
  Ada.Containers.Vectors has two Append procedures that take an
Element value; one takes a Count parameter and one does not
(the count is implicitly one for the latter). For the former version,
there was code that took a faster path if certain conditions were met
and otherwise took a slower path; one of the prerequisite conditions
for this was Count = 1. For the latter version, no such special-case
detection was performed; the more general code was always executed.
Move the special-case detection/handling code from the former version into
the latter and change the former version to simply call the latter version
if Count = 1. Also apply same change to Ada.Containers.Indefinite_Vectors.

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

gcc/ada/

	* libgnat/a-coinve.adb, libgnat/a-convec.adb
	(Append): If the Append that takes an Element and a Count is
	called with Count = 1, then call the Append that does not take a
	Count parameter; otherwise call the code that handles the general
	case. Move the special case detection/handling code that was
	formerly in that version of Append into the version that does not
	take a Count parameter, so that now both versions get the
	performance benefit.
  

Patch

diff --git a/gcc/ada/libgnat/a-coinve.adb b/gcc/ada/libgnat/a-coinve.adb
--- a/gcc/ada/libgnat/a-coinve.adb
+++ b/gcc/ada/libgnat/a-coinve.adb
@@ -197,12 +197,29 @@  is
       Count     : Count_Type)
    is
    begin
-      --  In the general case, we pass the buck to Insert, but for efficiency,
-      --  we check for the usual case where Count = 1 and the vector has enough
-      --  room for at least one more element.
+      --  In the general case, we take the slow path; for efficiency,
+      --  we check for the common case where Count = 1 .
 
-      if Count = 1
-        and then Container.Elements /= null
+      if Count = 1 then
+         Append (Container, New_Item);
+      else
+         Append_Slow_Path (Container, New_Item, Count);
+      end if;
+   end Append;
+
+   ------------
+   -- Append --
+   ------------
+
+   procedure Append (Container : in out Vector;
+                     New_Item  :        Element_Type)
+   is
+   begin
+      --  For performance, check for the common special case where the
+      --  container already has room for at least one more element.
+      --  In the general case, pass the buck to Insert.
+
+      if Container.Elements /= null
         and then Container.Last /= Container.Elements.Last
       then
          TC_Check (Container.TC);
@@ -223,23 +240,11 @@  is
             Container.Elements.EA (New_Last) := new Element_Type'(New_Item);
             Container.Last := New_Last;
          end;
-
       else
-         Append_Slow_Path (Container, New_Item, Count);
+         Insert (Container, Last_Index (Container) + 1, New_Item, 1);
       end if;
    end Append;
 
-   ------------
-   -- Append --
-   ------------
-
-   procedure Append (Container : in out Vector;
-                        New_Item   :        Element_Type)
-   is
-   begin
-      Insert (Container, Last_Index (Container) + 1, New_Item, 1);
-   end Append;
-
    ----------------------
    -- Append_Slow_Path --
    ----------------------


diff --git a/gcc/ada/libgnat/a-convec.adb b/gcc/ada/libgnat/a-convec.adb
--- a/gcc/ada/libgnat/a-convec.adb
+++ b/gcc/ada/libgnat/a-convec.adb
@@ -173,27 +173,11 @@  is
       Count     : Count_Type)
    is
    begin
-      --  In the general case, we pass the buck to Insert, but for efficiency,
-      --  we check for the usual case where Count = 1 and the vector has enough
-      --  room for at least one more element.
-
-      if Count = 1
-        and then Container.Elements /= null
-        and then Container.Last /= Container.Elements.Last
-      then
-         TC_Check (Container.TC);
-
-         --  Increment Container.Last after assigning the New_Item, so we
-         --  leave the Container unmodified in case Finalize/Adjust raises
-         --  an exception.
-
-         declare
-            New_Last : constant Index_Type := Container.Last + 1;
-         begin
-            Container.Elements.EA (New_Last) := New_Item;
-            Container.Last := New_Last;
-         end;
+      --  In the general case, we take the slow path; for efficiency,
+      --  we check for the common case where Count = 1 .
 
+      if Count = 1 then
+         Append (Container, New_Item);
       else
          Append_Slow_Path (Container, New_Item, Count);
       end if;
@@ -222,7 +206,28 @@  is
                      New_Item  :        Element_Type)
    is
    begin
-      Insert (Container, Last_Index (Container) + 1, New_Item, 1);
+      --  For performance, check for the common special case where the
+      --  container already has room for at least one more element.
+      --  In the general case, pass the buck to Insert.
+
+      if Container.Elements /= null
+        and then Container.Last /= Container.Elements.Last
+      then
+         TC_Check (Container.TC);
+
+         --  Increment Container.Last after assigning the New_Item, so we
+         --  leave the Container unmodified in case Finalize/Adjust raises
+         --  an exception.
+
+         declare
+            New_Last : constant Index_Type := Container.Last + 1;
+         begin
+            Container.Elements.EA (New_Last) := New_Item;
+            Container.Last := New_Last;
+         end;
+      else
+         Insert (Container, Last_Index (Container) + 1, New_Item, 1);
+      end if;
    end Append;
 
    ----------------------