From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x32d.google.com (mail-wm1-x32d.google.com [IPv6:2a00:1450:4864:20::32d]) by sourceware.org (Postfix) with ESMTPS id 5971C3858D1E; Mon, 18 Apr 2022 19:18:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5971C3858D1E Received: by mail-wm1-x32d.google.com with SMTP id x3so9272667wmj.5; Mon, 18 Apr 2022 12:18:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=sx5bK8P17hKZ5+lmd/yG99qom+IVwL+IzEcQNMPXXko=; b=pwUafQd7y6hEa70zev70Zd7pm96cF+G7FLDTcfKglIq4wEjO34FhXi4+qhcWeC/2K5 BW3ns0Wj1NhPHUDHp3hhEskyb+SlBKNo4boOatKgkd1nbSbNnpVsvgQdN3AKdB4PFvHf ThQUSVPd/3Fz498Ajlp+IQB2x7CuQFPysfWc2lpnHXG/8fCf0tnBgfbxNMC4Zz1WV49f 2i2aiZvAOcJWOSToOavjYgpitv2RDZTL4zBqsu2SJfkhqdiKVX0a/D8MkCjwlCKH0899 Dx3NgfxYM7WTojcinhy9oq0MFF+kJGYXkGXbm1oijvZZdnj5Mn7XTWWW6Bt1iSOtD9bB g84Q== X-Gm-Message-State: AOAM530+hzXfzfNuQxYPUbxSdaaW5V0uFuO1qEUwpAumRVSofPS9C1k/ YJt/IwdfrMtrIBRxZKWKzdcYZKPLz+P9IonnciY= X-Google-Smtp-Source: ABdhPJzz9Z2OKWLVk0Fiu0Aa7IwBubDja4G5gul87LTeB2xii2eoOJeXDeA1xuUn4IirbY1a7nLqDzdQ1wHBJoewaUM= X-Received: by 2002:a05:600c:3492:b0:392:97ba:9581 with SMTP id a18-20020a05600c349200b0039297ba9581mr4959107wmq.163.1650309481047; Mon, 18 Apr 2022 12:18:01 -0700 (PDT) MIME-Version: 1.0 References: <20220418143825.596190-1-ppalka@redhat.com> In-Reply-To: <20220418143825.596190-1-ppalka@redhat.com> From: Jonathan Wakely Date: Mon, 18 Apr 2022 20:17:46 +0100 Message-ID: Subject: Re: [PATCH] libstdc++: Micro-optimize __from_chars_pow2_base To: Patrick Palka Cc: gcc-patches , "libstdc++" X-Spam-Status: No, score=-7.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.29 X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Apr 2022 19:18:04 -0000 On Mon, 18 Apr 2022, 15:39 Patrick Palka via Libstdc++, < libstdc++@gcc.gnu.org> wrote: > At the first iteration of __from_chars_pow2_base's main loop, we need > to remember the value of the leading significant digit for sake of the > overflow check at the end of the function (for bases other than 2). > > This patch manually unrolls this first iteration so as to not encumber > the entire loop with logic that only the first iteration needs. This > seems to significantly improve performance: > Great, I was going to suggest looking into that change. > Base Before After (seconds, lower is better) > 2 9.36 9.37 > 8 3.66 2.93 > 16 2.93 1.91 > 32 2.39 2.24 > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk? > OK, thanks! > libstdc++-v3/ChangeLog: > > * include/std/charconv (__from_chars_pow2_base): Manually > unroll the first iteration of the main loop and simplify > accordingly. > --- > libstdc++-v3/include/std/charconv | 30 +++++++++++++++++++++--------- > 1 file changed, 21 insertions(+), 9 deletions(-) > > diff --git a/libstdc++-v3/include/std/charconv > b/libstdc++-v3/include/std/charconv > index dda4ec87779..cd7f52e2195 100644 > --- a/libstdc++-v3/include/std/charconv > +++ b/libstdc++-v3/include/std/charconv > @@ -469,25 +469,37 @@ namespace __detail > while (__i < __len && __first[__i] == '0') > ++__i; > const ptrdiff_t __leading_zeroes = __i; > + if (__i >= __len) [[__unlikely__]] > + { > + __first += __i; > + return true; > + } > + > + // Remember the leading significant digit value if necessary. > + unsigned char __leading_c; > + if (__base != 2) > + { > + __leading_c = __from_chars_alnum_to_val<_DecOnly>(__first[__i]); > + // __glibcxx_assert(__leading_c != 0); > + if (__leading_c >= __base) [[__unlikely__]] > + { > + __first += __i; > + return true; > + } > + __val = __leading_c; > + ++__i; > + } > > - unsigned char __leading_c = 0; > for (; __i < __len; ++__i) > { > const unsigned char __c = > __from_chars_alnum_to_val<_DecOnly>(__first[__i]); > if (__c >= __base) > break; > __val = (__val << __log2_base) | __c; > - > - if (__i == __leading_zeroes) > - { > - // At the first iteration, remember the leading significant > digit. > - // __glibcxx_assert(__leading_c == 0 && __c != 0); > - __leading_c = __c; > - } > } > __first += __i; > auto __significant_bits = (__i - __leading_zeroes) * __log2_base; > - if (__base != 2 && __leading_c != 0) > + if (__base != 2) > // Compensate for a leading significant digit that didn't use all > // of its available bits. > __significant_bits -= __log2_base - __bit_width(__leading_c); > -- > 2.36.0.rc2.10.g1ac7422e39 > >