This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/52394] SH Target: SH2A defunct bitops
- From: "kkojima at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 28 Feb 2012 00:37:56 +0000
- Subject: [Bug target/52394] SH Target: SH2A defunct bitops
- Auto-submitted: auto-generated
- References: <bug-52394-4@http.gcc.gnu.org/bugzilla/>
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52394
--- Comment #1 from Kazumoto Kojima <kkojima at gcc dot gnu.org> 2012-02-28 00:37:56 UTC ---
I guess that now these tests require -fno-strict-volatile-bitfields,
though it isn't enough to avoid failures. It looks that something
wrong happens in expmed.c:{store, extract}_bit_field_1 and they decide
to use slow fallback {store, extract}_fixed_bit_field instead of
generating insv/extv.
Here is suspicious part of {store, extract}_bit_field_1:
/* Now convert from counting within UNIT to counting in EXT_MODE. */
if (BYTES_BIG_ENDIAN && !MEM_P (xop0))
xbitpos += GET_MODE_BITSIZE (ext_mode) - unit;
unit = GET_MODE_BITSIZE (ext_mode);
/* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count
"backwards" from the size of the unit we are extracting from.
Otherwise, we count bits from the most significant on a
BYTES/BITS_BIG_ENDIAN machine. */
if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
xbitpos = unit - bitsize - xbitpos;
In the problematic cases, xop0 is a QImode memory and ext_mode is SImode.
The initial value of unit is 8. When starting xbitops is 3 and bitsize is
1 for example, these lines set xbitspos to 28! There is no insv/extv which
inserts/extracts such bit position for QImode memory and maybe_expand_insn
for CODE_FOR_{insv, extv} fails. Perhaps, these parts should be something
like
/* We have been counting XBITPOS within UNIT.
Count instead within the size of the register. */
if (BYTES_BIG_ENDIAN && !MEM_P (xop0))
xbitpos += GET_MODE_BITSIZE (op_mode) - unit;
/* If BITS_BIG_ENDIAN is zero on a BYTES_BIG_ENDIAN machine, we count
"backwards" from the size of the unit we are inserting into.
Otherwise, we count bits from the most significant on a
BYTES/BITS_BIG_ENDIAN machine. */
if (BITS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
{
if (!MEM_P (xop0))
xbitpos = GET_MODE_BITSIZE (op_mode) - bitsize - xbitpos;
else
xbitpos = unit - bitsize - xbitpos;
}
unit = GET_MODE_BITSIZE (op_mode);
though I don't understand these routines well.