PR middle-end/57344
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 May 2013 09:17:34 +0000 (09:17 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 23 May 2013 09:17:34 +0000 (09:17 +0000)
* 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

gcc/ChangeLog
gcc/expmed.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr57344-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr57344-2.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr57344-3.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr57344-4.c [new file with mode: 0644]

index 503215a..a4bf07a 100644 (file)
@@ -1,3 +1,10 @@
+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
index c85e68c..daadd3d 100644 (file)
@@ -1094,10 +1094,14 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
       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;
@@ -1147,14 +1151,15 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
         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))
        {
@@ -1162,8 +1167,9 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
          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;
index d1c0dda..6485a5c 100644 (file)
@@ -1,3 +1,11 @@
+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
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-1.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-1.c
new file mode 100644 (file)
index 0000000..6689326
--- /dev/null
@@ -0,0 +1,32 @@
+/* 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;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-2.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-2.c
new file mode 100644 (file)
index 0000000..9bf60ca
--- /dev/null
@@ -0,0 +1,32 @@
+/* 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;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-3.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-3.c
new file mode 100644 (file)
index 0000000..f9daea6
--- /dev/null
@@ -0,0 +1,28 @@
+/* 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;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57344-4.c b/gcc/testsuite/gcc.c-torture/execute/pr57344-4.c
new file mode 100644 (file)
index 0000000..0b2bf15
--- /dev/null
@@ -0,0 +1,28 @@
+/* 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;
+}