Optimize ToLower() and ToUpper() #17811

pull kristapsk wants to merge 1 commits into bitcoin:master from kristapsk:strcase-bithack changing 1 files +4 −4
  1. kristapsk commented at 2:58 AM on December 28, 2019: contributor

    Not the most important optimization, as these functions aren't used much, but came across this when reviewing #17808 and as I had this already implemented years ago when developing my own embedded / real-time libc, decided why not to send a PR here.

    ASCII was designed clever enough so that you can convert from lowercase to uppercase and vice versa by just flipping a single bit instead of doing addition and subtraction. Maybe some comment could be added about this, but I think it's a well known bit hack. In addition, adding const to parameter will not hurt, at least in my tests it made code smaller.

    Also noticed that ToUpper() is only used in unit tests and nowhere else, but it makes sense to keep both functions, probably it will be useful someday in future.

  2. Optimize ToLower() and ToUpper()
    Flipping 6th bit instead of adding and subtraction to switch from
    lowercase to uppercase and vice versa in ASCII is a well known bit hack.
    ba860c7b2a
  3. fanquake added the label Utils/log/libs on Dec 28, 2019
  4. hebasto commented at 6:08 AM on December 28, 2019: member

    The related discussion: #13671 (review)

  5. practicalswift commented at 8:20 AM on December 28, 2019: contributor

    I prefer the existing version: simple is better than clever :)

  6. sipa commented at 8:42 AM on December 28, 2019: member

    I would be very surprised if this leads to more performant compiled code.

  7. promag commented at 10:49 AM on December 28, 2019: member

    Agree with @practicalswift.

  8. sanjaykdragon commented at 3:35 PM on December 28, 2019: contributor

    I would be very surprised if this leads to more performant compiled code.

    This is what I'm thinking, I would expect the compiler to optimize that

  9. fanquake commented at 10:34 PM on December 28, 2019: member

    If anyone's interested, below is the diff of master (b931f61b9ab098ea4ea8fbe4cbf0b03c566c3f63) vs this PR. Regardless, I agree with the other commenters.

    >>> [do_build] Performing basic analysis pass...
    root@1d574f1fd618:/bitcoin# shasum /tmp/compare/*.stripped /tmp/17811/*.stripped
    b35adfc68b1639b03300b8b16456befaa8a67edf  /tmp/compare/bitcoind.b931f61b9ab098ea4ea8fbe4cbf0b03c566c3f63.stripped
    ff04b2378a77c3fcd06a939e33b14f923c24911e  /tmp/17811/bitcoind.ba860c7b2af7fd9cd4b3d314f2d9cd393fcde655.stripped
    root@1d574f1fd618:/bitcoin# diffoscope /tmp/compare/bitcoind.b931f61b9ab098ea4ea8fbe4cbf0b03c566c3f63.stripped /tmp/17811/bitcoind.ba860c7b2af7fd9cd4b3d314f2d9cd393fcde655.stripped
    
    --- /tmp/compare/bitcoind.b931f61b9ab098ea4ea8fbe4cbf0b03c566c3f63.stripped
    +++ /tmp/17811/bitcoind.ba860c7b2af7fd9cd4b3d314f2d9cd393fcde655.stripped
    @@ -29178,15 +29178,15 @@
        4750b:	48 8d 95 50 fc ff ff 	lea    -0x3b0(%rbp),%rdx
        47512:	48 8d 8d c0 fe ff ff 	lea    -0x140(%rbp),%rcx
        47519:	48 8d 71 20          	lea    0x20(%rcx),%rsi
        4751d:	48 89 d1             	mov    %rdx,%rcx
        47520:	48 8d 15 71 dd 4a 00 	lea    0x4add71(%rip),%rdx        # 4f5298 <std::istreambuf_iterator<char, std::char_traits<char> >::operator++()@@Base+0xd205c>
        47527:	48 89 c7             	mov    %rax,%rdi
        4752a:	e8 85 0f 01 00       	callq  584b4 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x23e>
    -   4752f:	c7 45 a8 e4 07 00 00 	movl   $0x7e4,-0x58(%rbp)
    +   4752f:	c7 45 a8 e3 07 00 00 	movl   $0x7e3,-0x58(%rbp)
        47536:	c7 45 ac d9 07 00 00 	movl   $0x7d9,-0x54(%rbp)
        4753d:	48 8d 45 b0          	lea    -0x50(%rbp),%rax
        47541:	48 8d 35 5d dd 4a 00 	lea    0x4add5d(%rip),%rsi        # 4f52a5 <std::istreambuf_iterator<char, std::char_traits<char> >::operator++()@@Base+0xd2069>
        47548:	48 89 c7             	mov    %rax,%rdi
        4754b:	e8 d5 73 ff ff       	callq  3e925 <std::terminate()@plt+0x11b65>
        47550:	48 8d 45 80          	lea    -0x80(%rbp),%rax
        47554:	48 8d 4d a8          	lea    -0x58(%rbp),%rcx
    @@ -1143663,29 +1143663,29 @@
       417901:	89 f8                	mov    %edi,%eax
       417903:	40 88 7d fc          	mov    %dil,-0x4(%rbp)
       417907:	80 7d fc 40          	cmpb   $0x40,-0x4(%rbp)
       41790b:	7e 0f                	jle    41791c <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5bb>
       41790d:	80 7d fc 5a          	cmpb   $0x5a,-0x4(%rbp)
       417911:	7f 09                	jg     41791c <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5bb>
       417913:	0f b6 45 fc          	movzbl -0x4(%rbp),%eax
    -  417917:	83 c0 20             	add    $0x20,%eax
    +  417917:	83 c8 20             	or     $0x20,%eax
       41791a:	eb 04                	jmp    417920 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5bf>
       41791c:	0f b6 45 fc          	movzbl -0x4(%rbp),%eax
       417920:	5d                   	pop    %rbp
       417921:	c3                   	retq   
       417922:	55                   	push   %rbp
       417923:	48 89 e5             	mov    %rsp,%rbp
       417926:	89 f8                	mov    %edi,%eax
       417928:	40 88 7d fc          	mov    %dil,-0x4(%rbp)
       41792c:	80 7d fc 60          	cmpb   $0x60,-0x4(%rbp)
       417930:	7e 0f                	jle    417941 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5e0>
       417932:	80 7d fc 7a          	cmpb   $0x7a,-0x4(%rbp)
       417936:	7f 09                	jg     417941 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5e0>
       417938:	0f b6 45 fc          	movzbl -0x4(%rbp),%eax
    -  41793c:	83 e8 20             	sub    $0x20,%eax
    +  41793c:	83 e0 df             	and    $0xffffffdf,%eax
       41793f:	eb 04                	jmp    417945 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)@@Base+0x1f5e4>
       417941:	0f b6 45 fc          	movzbl -0x4(%rbp),%eax
       417945:	5d                   	pop    %rbp
       417946:	c3                   	retq   
       417947:	55                   	push   %rbp
       417948:	48 89 e5             	mov    %rsp,%rbp
       41794b:	53                   	push   %rbx
    
  10. fanquake closed this on Dec 28, 2019

  11. kristapsk commented at 7:08 PM on January 3, 2020: contributor

    Just to note that OR / AND are faster and simpler operations than ADD / SUB, but if most think it's not so important, so be it, as I said in first comment, these functions aren't used much.

  12. MarcoFalke commented at 7:13 PM on January 3, 2020: member

    Performance improvements need to be benchmarked to show that they actually have an effect on performance.

  13. DrahtBot locked this on Feb 15, 2022

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:14 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me