http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51926

             Bug #: 51926
           Summary: libstdc++ iterator store bigendian bitfield related
    Classification: Unclassified
           Product: gcc
           Version: 4.7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: middle-end
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: amo...@gmail.com


A powerpc64-linux-gcc bootstrap and testsuite run configured for a default
64-bit output has 74 more testsuite failures in 64-bit libstdc++ compared to a
compiler configured for a default 32-bit output.  The difference turns out to
be due to MULTILIB_EXTRA_OPTS containing -mstrict-align, and MULTILIB_EXTRA_OPT
is not used on the default multilib.  So the failing libstdc++ is compiled
without -mstrict-align.

Looking at the first failure, 22_locale/money_get/get/char/13.cc, I find this
code from libstdc++-v3/include/bits/locale_facets_nonio.tcc

  template<typename _CharT, typename _InIter>
    _InIter
    money_get<_CharT, _InIter>::
    do_get(iter_type __beg, iter_type __end, bool __intl, ios_base& __io,
       ios_base::iostate& __err, long double& __units) const
    {
      string __str;
      __beg = __intl ? _M_extract<true>(__beg, __end, __io, __err, __str)
                 : _M_extract<false>(__beg, __end, __io, __err, __str);
      std::__convert_to_v(__str.c_str(), __units, __err, _S_get_c_locale());
      return __beg;
    }

loads __beg into a TImode reg and stores it back to a stack slot.  The iterator
storage (much simplified) looks like a C struct iter { void *p; int c }; 'p'
sits in the first 8 bytes, 'c' follows immediately after in the next 4 bytes.

bb4 starts with
;; MEM[(struct iter_type *)&__beg] = MEM[(struct iter_type *)&D.24297];

resulting in this horrible code
   0fffb7eddcb4 <+104>:    ld      r8,8(r29)    #c in 0:31
   0fffb7eddcb8 <+108>:    ld      r9,160(r1)    #p in 0:63
   0fffb7eddcbc <+112>:    rldicl  r10,r8,32,32    #c in 32:63
   0fffb7eddcc0 <+116>:    ld      r26,136(r1)
   0fffb7eddcc4 <+120>:    rldicr  r7,r9,32,31    #p(32:63) in 0:31
   0fffb7eddcc8 <+124>:    or      r10,r10,r7    #p(32:63) in 0:31, c in 32:63
The above (minus the uncommented line) is from expr.c:9810 extract_bit_field
call, so we've pulled out the iterator value and shifted it into the low bits
of a TImode reg.

   0fffb7eddccc <+128>:    rldicl  r8,r10,32,32    #p(32:63) in 32:63
   0fffb7eddcd0 <+132>:    rldicr  r9,r9,0,31    #p(0:31) in 0:31
   0fffb7eddcd4 <+136>:    rldicr  r10,r10,32,31    #c in 0:31
   0fffb7eddcd8 <+140>:    or      r9,r8,r9    #p in 0:63
And the above shifts it back by the expand_shift after this comment.
        /* If the result is a record type and BITSIZE is narrower than
           the mode of OP0, an integral mode, and this is a big endian
           machine, we must put the field into the high-order bits.  */

   0fffb7eddcdc <+144>:    rldimi  r30,r10,32,0    #0 <--------
   0fffb7eddce0 <+148>:    std     r9,160(r1)    #
   0fffb7eddce4 <+152>:    std     r30,168(r1)    #
And now store, but the rldimi wrongly stores the low 32 bits of r10 rather than
the high 32 bits.  Of course, all of the code above is quite useless.  We've
pulled a 12 byte value out of a 16 btye stack slot and stored it back again
(r29 = r1+160).

Reply via email to