This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/51926] New: libstdc++ iterator store bigendian bitfield related
- From: "amodra at gmail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sat, 21 Jan 2012 00:02:48 +0000
- Subject: [Bug middle-end/51926] New: libstdc++ iterator store bigendian bitfield related
- Auto-submitted: auto-generated
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: unassigned@gcc.gnu.org
ReportedBy: amodra@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).