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

--- Comment #8 from H.J. Lu <hjl.tools at gmail dot com> ---
Another testcase:

[hjl@gnu-tools-1 pr68991]$ cat add.cc
typedef unsigned int size_type;

#define _GLIBCXX_BITSET_BITS_PER_WORD  (__CHAR_BIT__ * __SIZEOF_INT__)
#define _GLIBCXX_BITSET_WORDS(__n) \
  ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \
   ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1))

namespace std
{
  template<size_type _Nw>
    struct _Base_bitset
    {
      typedef unsigned int _WordT;
      _WordT            _M_w[_Nw];

      _WordT&
      _M_hiword()
      { return _M_w[_Nw - 1]; }

      void
      _M_do_and(const _Base_bitset<_Nw>& __x)
      {
        for (size_type __i = 0; __i < _Nw; __i++)
          _M_w[__i] += __x._M_w[__i];
      }

      void
      _M_do_flip()
      {
        for (size_type __i = 0; __i < _Nw; __i++)
          _M_w[__i] = ~_M_w[__i];
      }

      bool
      _M_is_equal(const _Base_bitset<_Nw>& __x) const
      {
        for (size_type __i = 0; __i < _Nw; ++__i)
          if (_M_w[__i] != __x._M_w[__i])
            return false;
        return true;
      }

      bool
      _M_is_any() const
      {
        for (size_type __i = 0; __i < _Nw; __i++)
          if (_M_w[__i] != static_cast<_WordT>(0))
            return true;
        return false;
      }
    };

  template<size_type _Extrabits>
    struct _Sanitize
    {
      typedef unsigned int _WordT;

      static void
      _S_do_sanitize(_WordT& __val)
      { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); }
    };

  template<size_type _Nb>
    class bitset
    : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)>
    {
    private:
      typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base;
      typedef unsigned int _WordT;

      void
      _M_do_sanitize()
      { 
        typedef _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD> __sanitize_type;
        __sanitize_type::_S_do_sanitize(this->_M_hiword());
      }

    public:
      class reference
      {
        friend class bitset;

        _WordT* _M_wp;
        size_type       _M_bpos;

      public:
        reference&
        flip()
        {
          *_M_wp ^= _Base::_S_maskbit(_M_bpos);
          return *this;
        }
      };

      bitset<_Nb>&
      operator&=(const bitset<_Nb>& __rhs)
      {
        this->_M_do_and(__rhs);
        return *this;
      }

      bitset<_Nb>&
      flip() 
      {
        this->_M_do_flip();
        this->_M_do_sanitize();
        return *this;
      }

      bitset<_Nb>
      operator~() const 
      { return bitset<_Nb>(*this).flip(); }

      bool
      operator==(const bitset<_Nb>& __rhs) const 
      { return this->_M_is_equal(__rhs); }

      bool
      any() const 
      { return this->_M_is_any(); }
    };

  template<size_type _Nb>
    inline bitset<_Nb>
    operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) 
    {
      bitset<_Nb> __result(__x);
      __result &= __y;
      return __result;
    }
}
template<typename T>
class ArrayRef {
public:
    typedef const T *iterator;

private:
    const T *Data;
    size_type Length;

public:
    iterator begin() const { return Data; }
    iterator end() const { return Data + Length; }
};

const unsigned MAX_SUBTARGET_FEATURES = 128;
class FeatureBitset : public std::bitset<MAX_SUBTARGET_FEATURES> {
};

struct SubtargetFeatureKV {
  FeatureBitset Value;
  FeatureBitset Implies;
};

struct SubtargetInfoKV {
  const void *Value;
};
class SubtargetFeatures {
public:
    FeatureBitset ToggleFeature(FeatureBitset Bits,
                                const SubtargetFeatureKV *,
                                ArrayRef<SubtargetFeatureKV> FeatureTable);
};

static
void ClearImpliedBits(FeatureBitset &Bits,
                      const SubtargetFeatureKV *FeatureEntry,
                      ArrayRef<SubtargetFeatureKV> FeatureTable) {
  for (auto &FE : FeatureTable) {
    if ((FE.Implies & FeatureEntry->Value).any()) {
      Bits &= ~FE.Value;
      ClearImpliedBits(Bits, &FE, FeatureTable);
    }
  }
}

FeatureBitset
SubtargetFeatures::ToggleFeature(FeatureBitset Bits,
                                 const SubtargetFeatureKV *FeatureEntry,
                                 ArrayRef<SubtargetFeatureKV> FeatureTable) {
    if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
      Bits &= ~FeatureEntry->Value;
      ClearImpliedBits(Bits, FeatureEntry, FeatureTable);
    }
  return Bits;
}
[hjl@gnu-tools-1 pr68991]$
/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/xgcc
-B/export/build/gnu/gcc-x32/build-x86_64-linux/gcc/ -m64 -O3 -fno-exceptions
-fno-rtti -da -S -o add.s add.cc
[hjl@gnu-tools-1 pr68991]$ 

LRA turns

(insn 17 15 109 2 (set (reg:V4SI 122 [ vect__19.94 ])
        (plus:V4SI (mem/c:V4SI (plus:DI (reg/f:DI 20 frame)
                    (const_int -32 [0xffffffffffffffe0])) [6 MEM[(const struct
bitset &)&Bits]+0 S16 A32])
            (subreg:V4SI (reg:V16QI 121) 0))) add.cc:24 2960 {*addv4si3}
     (expr_list:REG_DEAD (reg:V16QI 121)
        (expr_list:REG_EQUIV (mem/c:V4SI (plus:DI (reg/f:DI 20 frame)
                    (const_int -16 [0xfffffffffffffff0])) [3 MEM[(unsigned int
*)&__result]+0 S16 A128])
            (nil))))

into

(insn 17 15 109 2 (set (reg:V4SI 21 xmm0 [orig:122 vect__19.94 ] [122])
        (plus:V4SI (reg:V4SI 21 xmm0 [121])
            (mem/c:V4SI (reg/f:DI 7 sp) [6 MEM[(const struct bitset &)&Bits]+0
S16 A32]))) add.cc:24 2960 {*addv4si3}
     (expr_list:REG_EQUIV (mem/c:V4SI (plus:DI (reg/f:DI 20 frame)
                (const_int -16 [0xfffffffffffffff0])) [3 MEM[(unsigned int
*)&__result]+0 S16 A128])
        (nil)))

Reply via email to