* expmed.c (store_split_bit_field): If op0 is a REG or
SUBREG of a REG, don't lower unit. Handle unit not being
always BITS_PER_WORD.
* gcc.c-torture/execute/pr57344-1.c: New test.
* gcc.c-torture/execute/pr57344-2.c: New test.
* gcc.c-torture/execute/pr57344-3.c: New test.
* gcc.c-torture/execute/pr57344-4.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@199238
138bc75d-0d04-0410-961f-
82ee72b054a4
+2013-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/57344
+ * expmed.c (store_split_bit_field): If op0 is a REG or
+ SUBREG of a REG, don't lower unit. Handle unit not being
+ always BITS_PER_WORD.
+
2013-05-23 Richard Biener <rguenther@suse.de>
PR rtl-optimization/57341
thispos = (bitpos + bitsdone) % unit;
/* When region of bytes we can touch is restricted, decrease
- UNIT close to the end of the region as needed. */
+ UNIT close to the end of the region as needed. If op0 is a REG
+ or SUBREG of REG, don't do this, as there can't be data races
+ on a register and we can expand shorter code in some cases. */
if (bitregion_end
&& unit > BITS_PER_UNIT
- && bitpos + bitsdone - thispos + unit > bitregion_end + 1)
+ && bitpos + bitsdone - thispos + unit > bitregion_end + 1
+ && !REG_P (op0)
+ && (GET_CODE (op0) != SUBREG || !REG_P (SUBREG_REG (op0))))
{
unit = unit / 2;
continue;
the current word starting from the base register. */
if (GET_CODE (op0) == SUBREG)
{
- int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD) + offset;
+ int word_offset = (SUBREG_BYTE (op0) / UNITS_PER_WORD)
+ + (offset * unit / BITS_PER_WORD);
enum machine_mode sub_mode = GET_MODE (SUBREG_REG (op0));
if (sub_mode != BLKmode && GET_MODE_SIZE (sub_mode) < UNITS_PER_WORD)
word = word_offset ? const0_rtx : op0;
else
word = operand_subword_force (SUBREG_REG (op0), word_offset,
GET_MODE (SUBREG_REG (op0)));
- offset = 0;
+ offset &= BITS_PER_WORD / unit - 1;
}
else if (REG_P (op0))
{
if (op0_mode != BLKmode && GET_MODE_SIZE (op0_mode) < UNITS_PER_WORD)
word = offset ? const0_rtx : op0;
else
- word = operand_subword_force (op0, offset, GET_MODE (op0));
- offset = 0;
+ word = operand_subword_force (op0, offset * unit / BITS_PER_WORD,
+ GET_MODE (op0));
+ offset &= BITS_PER_WORD / unit - 1;
}
else
word = op0;
+2013-05-23 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/57344
+ * gcc.c-torture/execute/pr57344-1.c: New test.
+ * gcc.c-torture/execute/pr57344-2.c: New test.
+ * gcc.c-torture/execute/pr57344-3.c: New test.
+ * gcc.c-torture/execute/pr57344-4.c: New test.
+
2013-05-23 Richard Biener <rguenther@suse.de>
PR rtl-optimization/57341
--- /dev/null
+/* PR middle-end/57344 */
+
+struct __attribute__((packed)) S
+{
+ int a : 11;
+#if __SIZEOF_INT__ * __CHAR_BIT__ >= 32
+ int b : 22;
+#else
+ int b : 13;
+#endif
+ char c;
+ int : 0;
+} s[2];
+int i;
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+ if (x != -3161)
+ __builtin_abort ();
+ asm volatile ("" : : : "memory");
+}
+
+int
+main ()
+{
+ struct S t = { 0, -3161L };
+ s[1] = t;
+ for (; i < 1; i++)
+ foo (s[1].b);
+ return 0;
+}
--- /dev/null
+/* PR middle-end/57344 */
+
+struct __attribute__((packed)) S
+{
+ int a : 27;
+#if __SIZEOF_INT__ * __CHAR_BIT__ >= 32
+ int b : 22;
+#else
+ int b : 13;
+#endif
+ char c;
+ int : 0;
+} s[2];
+int i;
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+ if (x != -3161)
+ __builtin_abort ();
+ asm volatile ("" : : : "memory");
+}
+
+int
+main ()
+{
+ struct S t = { 0, -3161L };
+ s[1] = t;
+ for (; i < 1; i++)
+ foo (s[1].b);
+ return 0;
+}
--- /dev/null
+/* PR middle-end/57344 */
+
+struct __attribute__((packed)) S
+{
+ long long int a : 43;
+ long long int b : 22;
+ char c;
+ long long int : 0;
+} s[2];
+int i;
+
+__attribute__((noinline, noclone)) void
+foo (long long int x)
+{
+ if (x != -3161LL)
+ __builtin_abort ();
+ asm volatile ("" : : : "memory");
+}
+
+int
+main ()
+{
+ struct S t = { 0, -3161LL };
+ s[1] = t;
+ for (; i < 1; i++)
+ foo (s[1].b);
+ return 0;
+}
--- /dev/null
+/* PR middle-end/57344 */
+
+struct __attribute__((packed)) S
+{
+ long long int a : 59;
+ long long int b : 54;
+ char c;
+ long long int : 0;
+} s[2];
+int i;
+
+__attribute__((noinline, noclone)) void
+foo (long long int x)
+{
+ if (x != -1220975898975746LL)
+ __builtin_abort ();
+ asm volatile ("" : : : "memory");
+}
+
+int
+main ()
+{
+ struct S t = { 0, -1220975898975746LL };
+ s[1] = t;
+ for (; i < 1; i++)
+ foo (s[1].b);
+ return 0;
+}