https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80813

--- Comment #3 from Jan Hubicka <hubicka at gcc dot gnu.org> ---
OK, so the horrid codegen is because bvector's [] operator is imlemented using
iterator:
  return begin()[__n];
iterator's [] operator is implemented using:

    _GLIBCXX20_CONSTEXPR
    void
    _M_incr(ptrdiff_t __i)
    {
      _M_assume_normalized();
      difference_type __n = __i + _M_offset;
      _M_p += __n / int(_S_word_bit);
      __n = __n % int(_S_word_bit);
      if (__n < 0)
        {
          __n += int(_S_word_bit);
          --_M_p;
        }
      _M_offset = static_cast<unsigned int>(__n);
    }


So the conditional is a check for negative __n which makes sense for iterator's
[], but not for vector's [].  We could add __builtin_unreachable hint that __n
is at most max_size, but since [] is such a common operation on vectors, I
think it makes sense to make life of compiler easier and micro-optimize it in
the array.

diff --git a/libstdc++-v3/include/bits/stl_bvector.h
b/libstdc++-v3/include/bits/stl_bvector.h
index 341eee33b21..43a07bc3e55 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -1132,7 +1141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       operator[](size_type __n)
       {
        __glibcxx_requires_subscript(__n);
-       return begin()[__n];
+       return _Bit_reference (this->_M_impl._M_start._M_p
+                              + __n / int(_S_word_bit),
+                              __n % int(_S_word_bit));
       }

       _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
@@ -1140,7 +1151,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
       operator[](size_type __n) const
       {
        __glibcxx_requires_subscript(__n);
-       return begin()[__n];
+       return _Bit_reference (this->_M_impl._M_start._M_p
+                              + __n / int(_S_word_bit),
+                              __n % int(_S_word_bit));
       }

     protected:

With this I now get:
.LFB1248:
        .cfi_startproc
        movq    (%rdi), %rax
        movq    %rsi, %rdx
        shrq    $6, %rdx
        andq    (%rax,%rdx,8), %rsi
        andl    $63, %esi
        setne   %al
        ret
that is certainly better. Still does not use BT.
Not sure if _M_incr can be tweaked for less horrid codegen.

Reply via email to