From patchwork Mon Jul 22 16:55:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 1135101 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-505465-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="UzEua0U6"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 45snmF6kWCz9s7T for ; Tue, 23 Jul 2019 02:55:25 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=Xtsw+I5WcG9dUmD4jCpeTEKeOVj++oLUe46BpMwXXJG8nO4Ic2Fw6 gOgC22+Iyt0xrSOiv8DkWlji82z9umaC60XZqj+KEACAkYtpniDXEY4juWNXL3s/ GQysb6Ga3w0EhncuWlTgfUnPm0SwcFwbIqh86BeP2F/lZHN/DmHWYg= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=yWBOY1Srv936fxbnJgyGtpEfoAY=; b=UzEua0U6tupzJxbmHJV9 NoiYVGeZF6le/CEk7G6j0bv/Bo6Zjy8DcafI1fShNeTKntgYkOsObeDirEGYcSAy FvpjPkrOc51AGqRyMTpa7jr9AUlSWwdZOPHBTS2N277onZ4y9A3v0Mz7kG1Rod3i HcI22ZhEyoz68UNuN4MyBxA= Received: (qmail 106810 invoked by alias); 22 Jul 2019 16:55:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 106659 invoked by uid 89); 22 Jul 2019 16:55:14 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.1 spammy=Integral, powers X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 22 Jul 2019 16:55:12 +0000 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id BBB0EC065121; Mon, 22 Jul 2019 16:55:11 +0000 (UTC) Received: from localhost (unknown [10.33.36.26]) by smtp.corp.redhat.com (Postfix) with ESMTP id 638E760600; Mon, 22 Jul 2019 16:55:11 +0000 (UTC) Date: Mon, 22 Jul 2019 17:55:10 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [PATCH] Adjust std::rotl, std::rotr etc to match final P0553R4 proposal Message-ID: <20190722165510.GA25149@redhat.com> MIME-Version: 1.0 Content-Disposition: inline X-Clacks-Overhead: GNU Terry Pratchett User-Agent: Mutt/1.12.0 (2019-05-25) This proposal has now been accepted for C++20, with a few changes. This patch adjusts std::rotl and std::rotr to match the final specification and declares the additions for C++2a mode even when __STRICT_ANSI__ is defined. * include/std/bit (__rotl, __rotr): Change second parameter from unsigned int to int and handle negative values. (rotl, rotr): Remove check for __STRICT_ANSI__. Change second parameter from unsigned int to int. Add nodiscard attribute. * testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative shifts. * testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative shifts. Tested x86_64-linux, committed to trunk. I'll backport this to gcc-9-branch too. commit b58d3908b4fcf83343f93bba8c4f5e49e982b894 Author: redi Date: Mon Jul 22 16:53:36 2019 +0000 Adjust std::rotl, std::rotr etc to match final P0553R4 proposal This proposal has now been accepted for C++20, with a few changes. This patch adjusts std::rotl and std::rotr to match the final specification and declares the additions for C++2a mode even when __STRICT_ANSI__ is defined. * include/std/bit (__rotl, __rotr): Change second parameter from unsigned int to int and handle negative values. (rotl, rotr): Remove check for __STRICT_ANSI__. Change second parameter from unsigned int to int. Add nodiscard attribute. * testsuite/26_numerics/bit/bitops.rot/rotl.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotl.cc: Here. Test negative shifts. * testsuite/26_numerics/bit/bitops.rot/rotr.cc: Rename to ... * testsuite/26_numerics/bit/bit.rotate/rotr.cc: Here. Test negative shifts. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@273706 138bc75d-0d04-0410-961f-82ee72b054a4 +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc @@ -20,12 +20,27 @@ #include +template +constexpr bool +test_negative_shifts() +{ + constexpr unsigned digits = std::numeric_limits::digits; + + UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 }; + int sarr[] = { 1, 4, 5, digits - 1, digits }; + for (UInt x : xarr) + for (int s : sarr) + if (std::rotr(x, -s) != std::rotl(x, s)) + return false; + return true; +} + template constexpr auto test(UInt x) --> decltype(std::rotr(x, 0u)) +-> decltype(std::rotr(x, 0)) { - static_assert( noexcept(std::rotr(x, 0u)) ); + static_assert( noexcept(std::rotr(x, 0)) ); constexpr unsigned digits = std::numeric_limits::digits; @@ -65,6 +80,8 @@ test(UInt x) == (0b1010 | ((UInt)0b0101 << digits - 4)) ); } + static_assert( test_negative_shifts() ); + return true; } diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit index d019b1ee600..f17d2f1bd59 100644 --- a/libstdc++-v3/include/std/bit +++ b/libstdc++-v3/include/std/bit @@ -42,20 +42,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template constexpr _Tp - __rotl(_Tp __x, unsigned int __s) noexcept + __rotl(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; - const unsigned __sN = __s % _Nd; - return (__x << __sN) | (__x >> ((_Nd - __sN) % _Nd)); + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); + else + return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) } template constexpr _Tp - __rotr(_Tp __x, unsigned int __s) noexcept + __rotr(_Tp __x, int __s) noexcept { constexpr auto _Nd = numeric_limits<_Tp>::digits; - const unsigned __sN = __s % _Nd; - return (__x >> __sN) | (__x << ((_Nd - __sN) % _Nd)); + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); + else + return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) } template @@ -244,20 +254,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using _If_is_unsigned_integer = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; -#if ! __STRICT_ANSI__ - // [bitops.rot], rotating + // [bit.rot], rotating template - constexpr _If_is_unsigned_integer<_Tp> - rotl(_Tp __x, unsigned int __s) noexcept + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotl(_Tp __x, int __s) noexcept { return std::__rotl(__x, __s); } template - constexpr _If_is_unsigned_integer<_Tp> - rotr(_Tp __x, unsigned int __s) noexcept + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotr(_Tp __x, int __s) noexcept { return std::__rotr(__x, __s); } - // [bitops.count], counting + // [bit.count], counting template constexpr _If_is_unsigned_integer<_Tp, int> @@ -283,9 +292,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION constexpr _If_is_unsigned_integer<_Tp, int> popcount(_Tp __x) noexcept { return std::__popcount(__x); } -#endif - // Integral power-of-two operations + // [bit.pow.two], integral powers of 2 template constexpr _If_is_unsigned_integer<_Tp, bool> diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc similarity index 89% rename from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotl.cc rename to libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc +++ b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotl.cc @@ -20,12 +20,27 @@ #include +template +constexpr bool +test_negative_shifts() +{ + constexpr unsigned digits = std::numeric_limits::digits; + + UInt xarr[] = { (UInt)-1, 0, 1, 3, 6, 7, 0x10, 0x11, 0x22, 0x44, 0x80 }; + int sarr[] = { 1, 4, 5, digits - 1, digits }; + for (UInt x : xarr) + for (int s : sarr) + if (std::rotl(x, -s) != std::rotr(x, s)) + return false; + return true; +} + template constexpr auto test(UInt x) --> decltype(std::rotl(x, 0u)) +-> decltype(std::rotl(x, 0)) { - static_assert( noexcept(std::rotl(x, 0u)) ); + static_assert( noexcept(std::rotl(x, 0)) ); constexpr unsigned digits = std::numeric_limits::digits; @@ -63,6 +78,8 @@ test(UInt x) static_assert( std::rotl((UInt)0b1010'0101, 4) == 0b1010'0101'0000 ); } + static_assert( test_negative_shifts() ); + return true; } diff --git a/libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc b/libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc similarity index 89% rename from libstdc++-v3/testsuite/26_numerics/bit/bitops.rot/rotr.cc rename to libstdc++-v3/testsuite/26_numerics/bit/bit.rotate/rotr.cc