Re: FIX PR51926, libstdc++ iterator store bigendian bitfield related

2012-01-23 Thread Alan Modra
On Sat, Jan 21, 2012 at 11:07:10AM +1030, Alan Modra wrote:
>   PR middle-end/51926
>   * expmed.c (store_bit_field_1): Properly handle last word of
>   BLKmode value when bigendian.

Blah, I was working on an old tree.  The bug is already fixed.

-- 
Alan Modra
Australia Development Lab, IBM


FIX PR51926, libstdc++ iterator store bigendian bitfield related

2012-01-20 Thread Alan Modra
This patch fixes a wrong-code bug in store_bit_field.  When storing a
multi-word BLKmode value (such as from a RECORD_TYPE), the last word
is trashed on big-endian targets.  See the PR for the gory details.
Bootstrapped and regression tested powerpc64-linux.  Fixes 74
testsuite failures.  OK for mainline?  And earlier versions of gcc?

PR middle-end/51926
* expmed.c (store_bit_field_1): Properly handle last word of
BLKmode value when bigendian.

Index: gcc/expmed.c
===
--- gcc/expmed.c(revision 183228)
+++ gcc/expmed.c(working copy)
@@ -551,19 +551,27 @@ store_bit_field_1 (rtx str_rtx, unsigned
  /* If I is 0, use the low-order word in both field and target;
 if I is 1, use the next to lowest word; and so on.  */
  unsigned int wordnum = (backwards ? nwords - i - 1 : i);
+ unsigned int nbits = (i == nwords - 1
+   ? bitsize - i * BITS_PER_WORD
+   : BITS_PER_WORD);
  unsigned int bit_offset = (backwards
-? MAX ((int) bitsize - ((int) i + 1)
-   * BITS_PER_WORD,
-   0)
-: (int) i * BITS_PER_WORD);
+? bitsize - i * BITS_PER_WORD - nbits
+: i * BITS_PER_WORD);
  rtx value_word = operand_subword_force (value, wordnum, fieldmode);
 
- if (!store_bit_field_1 (op0, MIN (BITS_PER_WORD,
-   bitsize - i * BITS_PER_WORD),
- bitnum + bit_offset,
+ if (WORDS_BIG_ENDIAN && !backwards && nbits != BITS_PER_WORD)
+   {
+ /* Original fieldmode was BLKmode.  The value in this
+case consists of bits in memory order, so any unused
+bits in the last word are in the least significant
+position.  */
+ value_word = expand_shift (RSHIFT_EXPR, word_mode, value_word,
+BITS_PER_WORD - nbits,
+value_word, 1);
+   }
+ if (!store_bit_field_1 (op0, nbits, bitnum + bit_offset,
  bitregion_start, bitregion_end,
- word_mode,
- value_word, fallback_p))
+ word_mode, value_word, fallback_p))
{
  delete_insns_since (last);
  return false;

-- 
Alan Modra
Australia Development Lab, IBM