From patchwork Tue Oct 29 13:19:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Palka X-Patchwork-Id: 99768 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9CDE6385842A for ; Tue, 29 Oct 2024 13:20:19 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id 657233858C98 for ; Tue, 29 Oct 2024 13:19:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 657233858C98 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 657233858C98 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730207991; cv=none; b=qkCxCznzlKx53uZaJV/wflPlUPVfA7WK1U9C7XkC+fvDCG5iM6AaxZNWU4ClA6GKVjsBaIO/9+kFACZgpuvsPwRJ7HI6wxCINNGdODhbgoKGViyxOL2l+K+7HzzX+bwyNYN0YIIYtY/FexgFG4R3x25+aI4ysMcVeC2scV01Fzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1730207991; c=relaxed/simple; bh=ycZ5gch/KxQDkyDiM2mFAQA2aJxcWDVSYrWQLFyGtC4=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=WYfWisKJ503vmtepoG+K1B8+CR6owa/GmgNvI+vBmg8KUWhb1naYaFWJdAz9zh17EHG3hFyaI9LbNHQyEIHQhFERoGh8zovtDec7mfgnnaA8J+lrjEdXagX0DKl96LnURmiKp9bTzHTBzZa0WZo0ntPoGhPUnignfO+AQXk8TaU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1730207981; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=TPu8yRlZoQS+TEuN08apyCb0je64+8Fokcm25+vUux0=; b=KvU9cGY8oTuBM+8Rn+0nbvMi0CAXOfoP7dRmLAjUb1XHIt44ds/8IgxED5CHe+mTcIK6Uj fsjG/IbXhGJvefJ25Tc90IpihMSVw6uhxIqSJuMXLmRORQaAGviJXndbOji8CP9l0kpqM0 yl1Brky0fWnIBK3cYoU0Y7KeSsXfBLQ= Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-303-u2YQyQy2MheorHMVpcKSzw-1; Tue, 29 Oct 2024 09:19:39 -0400 X-MC-Unique: u2YQyQy2MheorHMVpcKSzw-1 Received: by mail-qv1-f70.google.com with SMTP id 6a1803df08f44-6cbccc4fa08so13175766d6.2 for ; Tue, 29 Oct 2024 06:19:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1730207979; x=1730812779; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=TPu8yRlZoQS+TEuN08apyCb0je64+8Fokcm25+vUux0=; b=e+0TjgiShJXEXX/ABSjztOK5kEV2VAt+1rn1nsW6ZH64CYtlYGoXjurOzPe4kKJ5/E 7Q3KYSxIGdDNKMSwSbaxgHWV5nYnUSEPcMBPZ694VGDlM2vppLR2TgfRlhB+HZ/MUa0l Rui7ucPe66skY3U6xxJbVSVHLrZNvOPOe5eTAR30d9oNQ0Dxnr9RWKdVbMhOw3dVauFE lDo7zsTmLNso4RgI7zjQY6t80SjR66cL+r0ne2CygYBupqR+OkN72/0tgvFNclBidMOi OXlTgGtNq3ySQpkFT3oX1wOC/oQkXIMF5uxnWkqTsXffAmqbrMVm41GEYEdwWtMCOeCj v50w== X-Gm-Message-State: AOJu0Yxa6fK4lOZ0NrDu+WHTv1gqX2rFuf0U1Q0D0eE4DCNcT3SGhpQa CCfrpQJxtPw5/sCPwie6DEgnX7vfALVrMnzlvdJ4ZzO5WjcE2rVvKDODRu2KewmtTLp6rufYMGq FhuNW1Lqmm9QBQ+gdLal0ewnt9Sj8Oi7/zVDRMpLZDL9oGBJ9oRH/35GZsRMB+sN2VcJ/KqmqZY cWJmfSdXOSuaZyy3FE+Z1Rm2oxsjZ3bWh6Aw7h X-Received: by 2002:ad4:5c8e:0:b0:6cb:e6c8:2ad0 with SMTP id 6a1803df08f44-6d185693ff5mr93527436d6.5.1730207978961; Tue, 29 Oct 2024 06:19:38 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGCA+f4In8vzGWWS0fYVo0b0xcMvmMbJW/HSWBmyZvqC0cJu9W8Wx6A2xXhyivR0zV4FDPOVQ== X-Received: by 2002:ad4:5c8e:0:b0:6cb:e6c8:2ad0 with SMTP id 6a1803df08f44-6d185693ff5mr93527236d6.5.1730207978576; Tue, 29 Oct 2024 06:19:38 -0700 (PDT) Received: from localhost.localdomain (ool-18bb2a2e.dyn.optonline.net. [24.187.42.46]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-6d179a2d157sm41925646d6.123.2024.10.29.06.19.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 29 Oct 2024 06:19:37 -0700 (PDT) From: Patrick Palka To: gcc-patches@gcc.gnu.org Cc: libstdc++@gcc.gnu.org, Patrick Palka Subject: [PATCH] libstdc++: Avoid unnecessary copies in ranges::min/max [PR112349] Date: Tue, 29 Oct 2024 09:19:35 -0400 Message-ID: <20241029131935.85441-1-ppalka@redhat.com> X-Mailer: git-send-email 2.47.0.148.g6a11438f43 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-13.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org 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~patchwork=sourceware.org@gcc.gnu.org Tested on x86_64-pc-linux-gnu, does this look OK for trunk and perhaps 14? -- >8 -- Use a local reference for the (now possibly lifetime extended) result of *__first to avoid making unnecessary copies of it. PR libstdc++/112349 libstdc++-v3/ChangeLog: * include/bits/ranges_algo.h (__min_fn::operator()): Turn local object __tmp into a reference. * include/bits/ranges_util.h (__max_fn::operator()): Likewise. * testsuite/25_algorithms/max/constrained.cc (test04): New test. * testsuite/25_algorithms/min/constrained.cc (test04): New test. --- libstdc++-v3/include/bits/ranges_algo.h | 4 +-- libstdc++-v3/include/bits/ranges_util.h | 4 +-- .../25_algorithms/max/constrained.cc | 25 +++++++++++++++++++ .../25_algorithms/min/constrained.cc | 25 +++++++++++++++++++ 4 files changed, 54 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index bae36637b3e..e1aba256241 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -2945,11 +2945,11 @@ namespace ranges auto __result = *__first; while (++__first != __last) { - auto __tmp = *__first; + auto&& __tmp = *__first; if (std::__invoke(__comp, std::__invoke(__proj, __result), std::__invoke(__proj, __tmp))) - __result = std::move(__tmp); + __result = std::forward(__tmp); } return __result; } diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h index 3f191e6d446..4a5349ae92a 100644 --- a/libstdc++-v3/include/bits/ranges_util.h +++ b/libstdc++-v3/include/bits/ranges_util.h @@ -754,11 +754,11 @@ namespace ranges auto __result = *__first; while (++__first != __last) { - auto __tmp = *__first; + auto&& __tmp = *__first; if (std::__invoke(__comp, std::__invoke(__proj, __tmp), std::__invoke(__proj, __result))) - __result = std::move(__tmp); + __result = std::forward(__tmp); } return __result; } diff --git a/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc index e7269e1b734..717900656bd 100644 --- a/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc @@ -73,10 +73,35 @@ test03() VERIFY( ranges::max({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 4 ); } +void +test04() +{ + // PR libstdc++/112349 - ranges::max/min make unnecessary copies + static int copies, moves; + struct A { + A(int m) : m(m) { } + A(const A& other) : m(other.m) { ++copies; } + A(A&& other) : m(other.m) { ++moves; } + A& operator=(const A& other) { m = other.m; ++copies; return *this; } + A& operator=(A&& other) { m = other.m; ++moves; return *this; } + int m; + }; + A r[5] = {5, 4, 3, 2, 1}; + ranges::max(r, std::less{}, &A::m); + VERIFY( copies == 1 ); + VERIFY( moves == 0 ); + copies = moves = 0; + A s[5] = {1, 2, 3, 4, 5}; + ranges::max(s, std::less{}, &A::m); + VERIFY( copies == 5 ); + VERIFY( moves == 0 ); +} + int main() { test01(); test02(); test03(); + test04(); } diff --git a/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc index 7198df69adf..d338a86f186 100644 --- a/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc +++ b/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc @@ -73,10 +73,35 @@ test03() VERIFY( ranges::min({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 1 ); } +void +test04() +{ + // PR libstdc++/112349 - ranges::max/min make unnecessary copies + static int copies, moves; + struct A { + A(int m) : m(m) { } + A(const A& other) : m(other.m) { ++copies; } + A(A&& other) : m(other.m) { ++moves; } + A& operator=(const A& other) { m = other.m; ++copies; return *this; } + A& operator=(A&& other) { m = other.m; ++moves; return *this; } + int m; + }; + A r[5] = {5, 4, 3, 2, 1}; + ranges::min(r, std::less{}, &A::m); + VERIFY( copies == 5 ); + VERIFY( moves == 0 ); + copies = moves = 0; + A s[5] = {1, 2, 3, 4, 5}; + ranges::min(s, std::less{}, &A::m); + VERIFY( copies == 1 ); + VERIFY( moves == 0 ); +} + int main() { test01(); test02(); test03(); + test04(); }