From patchwork Mon Nov 4 16:11:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Marc_Poulhi=C3=A8s?= X-Patchwork-Id: 2006329 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (2048-bit key; secure) header.d=adacore.com header.i=@adacore.com header.a=rsa-sha256 header.s=google header.b=J2eUVmzO; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XhxYK4xFzz1xxN for ; Tue, 5 Nov 2024 03:21:25 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D23CD3857000 for ; Mon, 4 Nov 2024 16:21:23 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by sourceware.org (Postfix) with ESMTPS id C405F3857000 for ; Mon, 4 Nov 2024 16:11:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C405F3857000 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=adacore.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=adacore.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org C405F3857000 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2a00:1450:4864:20::329 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730736759; cv=none; b=cYoRFPR1k4GqlIg7IGksNuiHzBujRBo+SwO6xZlOSLXxlBQs1GcHTgWnLcp7mTReMYqSekSjZ1+9NsZ9M9xzLfNMxvCTeE5ZOXobNtuhVBWs+SyxszXvgvJtaBBKzxvAL3bwHL5xRuzOnV2yhertjkLLr2mEL/zNyTqlXAEhKGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730736759; c=relaxed/simple; bh=UrBZdkOZt+CQZoYslYXmeNwBJxFxwxjX/wktuIKh5Xc=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=TXCm//hyQFMax6rKQ1BfRx+LqkZgaxwjs6RRv07v2uyU+VFSsLgQHwpIlVJhWQpWdiKOK3lBMwqeVVTHjwrC6y/KTUM5I9bH5AbPPprQgJui/BeC8zi7JQh+JoxKntxaFP5ObJiKjQxdbKobtRMAbjxGKxp/v+rmvPcuCvwBCIA= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-wm1-x329.google.com with SMTP id 5b1f17b1804b1-43158625112so38171645e9.3 for ; Mon, 04 Nov 2024 08:11:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=adacore.com; s=google; t=1730736713; x=1731341513; darn=gcc.gnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EBGDB6b5rEvSov1mRC7os/7pZYIek2iJwymyA/az2aQ=; b=J2eUVmzOVX2bOR3sSqyBn4Rkh1GYAEzsH/LzuublAXN8EmJNj0T9/IiFaZ2zEguOeY D3h39mT4s17oKVY+35ITQxvFKKAKWOH4XChMApQy+TdCLuSQ7HdB5t6HhYvDI5zKuN7o XRfR2OvYxEiv4OhggEhT6S8Zg1UZ0cM7deCmvC5ZUv152wAv7BCwweWb9YNSgQRPcLF5 EGwtnATWc/pow/HZJanvAs7mN4ytxItZnZxBQKiH1zz7jqoN7gKXm7RqBFDW6q9d7z9m j/DZiKo0FN7QW7pDXY2JCqHrtZwnmMsCgRCjlvAyqswCDrFRAMtLNzgoL4W4QK39EZL4 tVaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730736713; x=1731341513; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EBGDB6b5rEvSov1mRC7os/7pZYIek2iJwymyA/az2aQ=; b=eCEpq4rgJl/kKhBJTRwF2t6C3d3AUXKSnDzZNjFzkJ/pxezcPs95QgI7YpzeDpJcXA hHM3OL/oFxgiyJ7OVtFKcMgmd+n3EuHQjduWqGLT4riVnPBldJd3h/5o+RHrC6Y8SGD0 /1G1ASbyAQHE5Wiqq7HqUrD9hsfyKZp2ptVBEqrARAc1BRBL0QcI6T7ebl6BcempNkm0 H48wSz130brxgatU6XEqw0RgCgoO87kViIrZ14ot9qBwkKwnlkkYeTrRMzyoOjRIO6I4 Wd8E2DbJ/jO8p/9bkYiThy91EK/ule+TlIcA8ZUjeb45Hjp+3CKE+f0rhW9+Jc4UcgrS 4FPQ== X-Gm-Message-State: AOJu0YyHce+L5mtmkJe0gE8ECkj3QVGB3oaQ3qrndJk2wAat5o8D5fFG 0LOuVJ0IfnUlOg2H0Lff+IjiuBgONGBKtz0zg8D0luLXXIMoz9y37WRQ9BHPmkzOf+dk6A+9G10 = X-Google-Smtp-Source: AGHT+IERf2zgV8mcJbdRQeQ7WSwGA9o5Et1p/I+27m9paYpKJALcZ8h9CfYL34K9pVpR5De2pf9EWQ== X-Received: by 2002:a5d:64c7:0:b0:37d:415c:f27c with SMTP id ffacd0b85a97d-381c7aa4846mr9070014f8f.38.1730736713380; Mon, 04 Nov 2024 08:11:53 -0800 (PST) Received: from poulhies-Precision-5550.telnowedge.local (lmontsouris-659-1-24-67.w81-250.abo.wanadoo.fr. [81.250.175.67]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-381c10e747csm13574463f8f.64.2024.11.04.08.11.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Nov 2024 08:11:52 -0800 (PST) From: =?utf-8?q?Marc_Poulhi=C3=A8s?= To: gcc-patches@gcc.gnu.org Cc: Nicolas Roche Subject: [COMMITTED 34/38] ada: Improve Unbounded_Wide_String performance Date: Mon, 4 Nov 2024 17:11:09 +0100 Message-ID: <20241104161116.1431659-34-poulhies@adacore.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20241104161116.1431659-1-poulhies@adacore.com> References: <20241104161116.1431659-1-poulhies@adacore.com> MIME-Version: 1.0 X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org From: Nicolas Roche Improve performance of iteration using Element function. Improve performance of Append. gcc/ada/ChangeLog: * libgnat/a-stwiun__shared.adb: Restructure code to inline only the most common cases. Remove whenever possible runtime checks. * libgnat/a-stwiun__shared.ads: Add Inline => True to Append variants and Element. Tested on x86_64-pc-linux-gnu, committed on master. --- gcc/ada/libgnat/a-stwiun__shared.adb | 164 ++++++++++++++++++++------- gcc/ada/libgnat/a-stwiun__shared.ads | 9 +- 2 files changed, 127 insertions(+), 46 deletions(-) diff --git a/gcc/ada/libgnat/a-stwiun__shared.adb b/gcc/ada/libgnat/a-stwiun__shared.adb index 26b4f8ec85f..d3f20f0af20 100644 --- a/gcc/ada/libgnat/a-stwiun__shared.adb +++ b/gcc/ada/libgnat/a-stwiun__shared.adb @@ -36,7 +36,24 @@ package body Ada.Strings.Wide_Unbounded is use Ada.Strings.Wide_Maps; - Growth_Factor : constant := 32; + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Unbounded_Wide_String); + + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Wide_String); + + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Wide_Character); + -- Non_Inlined_Append are part of the respective Append method that + -- should not be inlined. The idea is that the code of Append is inlined. + -- In order to make inlining efficient it is better to have the inlined + -- code as small as possible. Thus most common cases are inlined and less + -- common cases are deferred in these functions. + + Growth_Factor : constant := 2; -- The growth factor controls how much extra space is allocated when -- we have to increase the size of an allocated unbounded string. By -- allocating extra space, we avoid the need to reallocate on every @@ -525,10 +542,12 @@ package body Ada.Strings.Wide_Unbounded is (Source : in out Unbounded_Wide_String; New_Item : Unbounded_Wide_String) is + pragma Suppress (All_Checks); + -- Suppress checks as they are redundant with the checks done in that + -- function. + SR : constant Shared_Wide_String_Access := Source.Reference; NR : constant Shared_Wide_String_Access := New_Item.Reference; - DL : constant Natural := SR.Last + NR.Last; - DR : Shared_Wide_String_Access; begin -- Source is an empty string, reuse New_Item data @@ -545,19 +564,17 @@ package body Ada.Strings.Wide_Unbounded is -- Try to reuse existent shared string - elsif Can_Be_Reused (SR, DL) then - SR.Data (SR.Last + 1 .. DL) := NR.Data (1 .. NR.Last); - SR.Last := DL; + elsif System.Atomic_Counters.Is_One (SR.Counter) + and then NR.Last <= SR.Max_Length + and then SR.Max_Length - NR.Last >= SR.Last + then + SR.Data (SR.Last + 1 .. SR.Last + NR.Last) := NR.Data (1 .. NR.Last); + SR.Last := SR.Last + NR.Last; -- Otherwise, allocate new one and fill it else - DR := Allocate (DL + DL / Growth_Factor); - DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); - DR.Data (SR.Last + 1 .. DL) := NR.Data (1 .. NR.Last); - DR.Last := DL; - Source.Reference := DR; - Unreference (SR); + Non_Inlined_Append (Source, New_Item); end if; end Append; @@ -565,31 +582,34 @@ package body Ada.Strings.Wide_Unbounded is (Source : in out Unbounded_Wide_String; New_Item : Wide_String) is - SR : constant Shared_Wide_String_Access := Source.Reference; - DL : constant Natural := SR.Last + New_Item'Length; - DR : Shared_Wide_String_Access; + pragma Suppress (All_Checks); + -- Suppress checks as they are redundant with the checks done in that + -- function. + New_Item_Length : constant Natural := New_Item'Length; + SR : constant Shared_Wide_String_Access := Source.Reference; begin - -- New_Item is an empty string, nothing to do if New_Item'Length = 0 then + -- New_Item is an empty string, nothing to do null; - -- Try to reuse existing shared string - - elsif Can_Be_Reused (SR, DL) then - SR.Data (SR.Last + 1 .. DL) := New_Item; - SR.Last := DL; - - -- Otherwise, allocate new one and fill it + elsif System.Atomic_Counters.Is_One (SR.Counter) + -- The following test checks in fact that + -- SR.Max_Length >= SR.Last + New_Item_Length without causing + -- overflow. + and then New_Item_Length <= SR.Max_Length + and then SR.Max_Length - New_Item_Length >= SR.Last + then + -- Try to reuse existing shared string + SR.Data (SR.Last + 1 .. SR.Last + New_Item_Length) := New_Item; + SR.Last := SR.Last + New_Item_Length; else - DR := Allocate (DL + DL / Growth_Factor); - DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); - DR.Data (SR.Last + 1 .. DL) := New_Item; - DR.Last := DL; - Source.Reference := DR; - Unreference (SR); + -- Otherwise, allocate new one and fill it. Deferring the worst case + -- into a separate non-inlined function ensure that inlined Append + -- code size remains short and thus efficient. + Non_Inlined_Append (Source, New_Item); end if; end Append; @@ -597,26 +617,24 @@ package body Ada.Strings.Wide_Unbounded is (Source : in out Unbounded_Wide_String; New_Item : Wide_Character) is - SR : constant Shared_Wide_String_Access := Source.Reference; - DL : constant Natural := SR.Last + 1; - DR : Shared_Wide_String_Access; + pragma Suppress (All_Checks); + -- Suppress checks as they are redundant with the checks done in that + -- function. + SR : constant Shared_Wide_String_Access := Source.Reference; begin - -- Try to reuse existing shared string - - if Can_Be_Reused (SR, SR.Last + 1) then + if System.Atomic_Counters.Is_One (SR.Counter) + and then SR.Max_Length > SR.Last + then + -- Try to reuse existing shared string SR.Data (SR.Last + 1) := New_Item; SR.Last := SR.Last + 1; - -- Otherwise, allocate new one and fill it - else - DR := Allocate (DL + DL / Growth_Factor); - DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); - DR.Data (DL) := New_Item; - DR.Last := DL; - Source.Reference := DR; - Unreference (SR); + -- Otherwise, allocate new one and fill it. Deferring the worst case + -- into a separate non-inlined function ensure that inlined Append + -- code size remains short and thus efficient. + Non_Inlined_Append (Source, New_Item); end if; end Append; @@ -1178,6 +1196,66 @@ package body Ada.Strings.Wide_Unbounded is return Source.Reference.Last; end Length; + ------------------------ + -- Non_Inlined_Append -- + ------------------------ + + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Unbounded_Wide_String) + is + SR : constant Shared_Wide_String_Access := Source.Reference; + NR : constant Shared_Wide_String_Access := New_Item.Reference; + DL : constant Natural := SR.Last + NR.Last; + DR : Shared_Wide_String_Access; + begin + DR := Allocate (DL + DL / Growth_Factor); + DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); + DR.Data (SR.Last + 1 .. DL) := NR.Data (1 .. NR.Last); + DR.Last := DL; + Source.Reference := DR; + Unreference (SR); + end Non_Inlined_Append; + + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Wide_String) + is + SR : constant Shared_Wide_String_Access := Source.Reference; + DL : constant Natural := SR.Last + New_Item'Length; + DR : Shared_Wide_String_Access; + begin + DR := Allocate (DL + DL / Growth_Factor); + DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); + DR.Data (SR.Last + 1 .. DL) := New_Item; + DR.Last := DL; + Source.Reference := DR; + Unreference (SR); + end Non_Inlined_Append; + + procedure Non_Inlined_Append + (Source : in out Unbounded_Wide_String; + New_Item : Wide_Character) + is + SR : constant Shared_Wide_String_Access := Source.Reference; + begin + if SR.Last = Natural'Last then + raise Constraint_Error; + else + declare + DL : constant Natural := SR.Last + 1; + DR : Shared_Wide_String_Access; + begin + DR := Allocate (DL + DL / Growth_Factor); + DR.Data (1 .. SR.Last) := SR.Data (1 .. SR.Last); + DR.Data (DL) := New_Item; + DR.Last := DL; + Source.Reference := DR; + Unreference (SR); + end; + end if; + end Non_Inlined_Append; + --------------- -- Overwrite -- --------------- diff --git a/gcc/ada/libgnat/a-stwiun__shared.ads b/gcc/ada/libgnat/a-stwiun__shared.ads index 865970f052c..19ccebf7186 100644 --- a/gcc/ada/libgnat/a-stwiun__shared.ads +++ b/gcc/ada/libgnat/a-stwiun__shared.ads @@ -79,15 +79,18 @@ package Ada.Strings.Wide_Unbounded is procedure Append (Source : in out Unbounded_Wide_String; - New_Item : Unbounded_Wide_String); + New_Item : Unbounded_Wide_String) + with Inline => True; procedure Append (Source : in out Unbounded_Wide_String; - New_Item : Wide_String); + New_Item : Wide_String) + with Inline => True; procedure Append (Source : in out Unbounded_Wide_String; - New_Item : Wide_Character); + New_Item : Wide_Character) + with Inline => True; function "&" (Left : Unbounded_Wide_String;