PR middle-end/52979
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Apr 2012 14:27:08 +0000 (14:27 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 25 Apr 2012 14:27:08 +0000 (14:27 +0000)
* stor-layout.c (get_best_mode): Don't return mode with bitsize
larger than maxbits.  Don't compute maxbits modulo align.
Also check that unit bytes long store at bitpos / unit * unit
doesn't affect bits beyond bitregion_end.
* expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM
would not fit into bitregion_start ... bitregion_end + 1 bit
region.
(store_split_bit_field): Decrease unit close to end of bitregion_end
if access is restricted in order to avoid mutual recursion.

* gcc.c-torture/compile/pr52979-1.c: New test.
* gcc.c-torture/execute/pr52979-1.c: New test.
* gcc.c-torture/execute/pr52979-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186819 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expmed.c
gcc/stor-layout.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/compile/pr52979-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr52979-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr52979-2.c [new file with mode: 0644]

index 9edaf93..d5154ec 100644 (file)
@@ -1,5 +1,16 @@
 2012-04-25  Jakub Jelinek  <jakub@redhat.com>
 
+       PR middle-end/52979
+       * stor-layout.c (get_best_mode): Don't return mode with bitsize
+       larger than maxbits.  Don't compute maxbits modulo align.
+       Also check that unit bytes long store at bitpos / unit * unit
+       doesn't affect bits beyond bitregion_end.
+       * expmed.c (store_bit_field_1): Avoid trying insv if OP_MODE MEM
+       would not fit into bitregion_start ... bitregion_end + 1 bit
+       region.
+       (store_split_bit_field): Decrease unit close to end of bitregion_end
+       if access is restricted in order to avoid mutual recursion.
+
        PR tree-optimization/53058
        * double-int.h (double_int_max_value, double_int_min_value): New
        prototypes.
index aa24fbf..a0a0960 100644 (file)
@@ -640,7 +640,13 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       && !(MEM_P (op0) && MEM_VOLATILE_P (op0)
           && flag_strict_volatile_bitfields > 0)
       && ! ((REG_P (op0) || GET_CODE (op0) == SUBREG)
-           && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode))))
+           && (bitsize + bitpos > GET_MODE_BITSIZE (op_mode)))
+      /* Do not use insv if the bit region is restricted and
+        op_mode integer at offset doesn't fit into the
+        restricted region.  */
+      && !(MEM_P (op0) && bitregion_end
+          && bitnum - bitpos + GET_MODE_BITSIZE (op_mode)
+             > bitregion_end + 1))
     {
       struct expand_operand ops[4];
       int xbitpos = bitpos;
@@ -760,7 +766,7 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
          || GET_MODE_BITSIZE (GET_MODE (op0)) > maxbits
          || (op_mode != MAX_MACHINE_MODE
              && GET_MODE_SIZE (GET_MODE (op0)) > GET_MODE_SIZE (op_mode)))
-       bestmode = get_best_mode  (bitsize, bitnum,
+       bestmode = get_best_mode (bitsize, bitnum,
                                  bitregion_start, bitregion_end,
                                  MEM_ALIGN (op0),
                                  (op_mode == MAX_MACHINE_MODE
@@ -1096,6 +1102,16 @@ store_split_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize,
       offset = (bitpos + bitsdone) / unit;
       thispos = (bitpos + bitsdone) % unit;
 
+      /* When region of bytes we can touch is restricted, decrease
+        UNIT close to the end of the region as needed.  */
+      if (bitregion_end
+         && unit > BITS_PER_UNIT
+         && bitpos + bitsdone - thispos + unit > bitregion_end + 1)
+       {
+         unit = unit / 2;
+         continue;
+       }
+
       /* THISSIZE must not overrun a word boundary.  Otherwise,
         store_fixed_bit_field will call us again, and we will mutually
         recurse forever.  */
index d79be14..e72e7f3 100644 (file)
@@ -2624,7 +2624,7 @@ get_best_mode (int bitsize, int bitpos,
   if (!bitregion_end)
     maxbits = MAX_FIXED_MODE_SIZE;
   else
-    maxbits = (bitregion_end - bitregion_start) % align + 1;
+    maxbits = bitregion_end - bitregion_start + 1;
 
   /* Find the narrowest integer mode that contains the bit field.  */
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode;
@@ -2645,7 +2645,10 @@ get_best_mode (int bitsize, int bitpos,
         (Though at least one Unix compiler ignores this problem:
         that on the Sequent 386 machine.  */
       || MIN (unit, BIGGEST_ALIGNMENT) > align
-      || (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode)))
+      || (largest_mode != VOIDmode && unit > GET_MODE_BITSIZE (largest_mode))
+      || unit > maxbits
+      || (bitregion_end
+         && bitpos - (bitpos % unit) + unit > bitregion_end + 1))
     return VOIDmode;
 
   if ((SLOW_BYTE_ACCESS && ! volatilep)
@@ -2663,7 +2666,9 @@ get_best_mode (int bitsize, int bitpos,
              && unit <= MIN (align, BIGGEST_ALIGNMENT)
              && unit <= maxbits
              && (largest_mode == VOIDmode
-                 || unit <= GET_MODE_BITSIZE (largest_mode)))
+                 || unit <= GET_MODE_BITSIZE (largest_mode))
+             && (bitregion_end == 0
+                 || bitpos - (bitpos % unit) + unit <= bitregion_end + 1))
            wide_mode = tmode;
        }
 
index d479cd6..b7fe632 100644 (file)
@@ -1,3 +1,10 @@
+2012-04-25  Jakub Jelinek  <jakub@redhat.com>
+
+       PR middle-end/52979
+       * gcc.c-torture/compile/pr52979-1.c: New test.
+       * gcc.c-torture/execute/pr52979-1.c: New test.
+       * gcc.c-torture/execute/pr52979-2.c: New test.
+
 2012-04-25  Richard Guenther  <rguenther@suse.de>
 
        * gcc.target/i386/l_fma_float_5.c: Adjust.
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr52979-1.c b/gcc/testsuite/gcc.c-torture/compile/pr52979-1.c
new file mode 100644 (file)
index 0000000..c703073
--- /dev/null
@@ -0,0 +1,15 @@
+/* PR middle-end/52979 */
+
+struct S
+{
+  unsigned int a : 16, b : 16, c : 16, d : 16, e : 14;
+  unsigned int f : 4, g : 14, h : 8;
+  char i;
+  int j;
+};
+
+void
+foo (struct S *s)
+{
+  s->f = 1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr52979-1.c b/gcc/testsuite/gcc.c-torture/execute/pr52979-1.c
new file mode 100644 (file)
index 0000000..246b1fd
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR middle-end/52979 */
+
+extern void abort (void);
+int c, d, e;
+
+void
+foo (void)
+{
+}
+
+struct __attribute__((packed)) S { int g : 31; int h : 6; };
+struct S a = { 1 };
+static struct S b = { 1 };
+
+void
+bar (void)
+{
+  a.h = 1;
+  struct S f = { };
+  b = f;
+  e = 0;
+  if (d)
+    c = a.g;
+}
+
+void
+baz (void)
+{
+  bar ();
+  a = b;
+}
+
+int
+main ()
+{
+  baz ();
+  if (a.g)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr52979-2.c b/gcc/testsuite/gcc.c-torture/execute/pr52979-2.c
new file mode 100644 (file)
index 0000000..52f5bb8
--- /dev/null
@@ -0,0 +1,40 @@
+/* PR middle-end/52979 */
+
+extern void abort (void);
+int c, d, e;
+
+void
+foo (void)
+{
+}
+
+struct __attribute__((packed)) S { int g : 31; int h : 6; };
+static struct S b = { 1 };
+struct S a = { 1 };
+
+void
+bar (void)
+{
+  a.h = 1;
+  struct S f = { };
+  b = f;
+  e = 0;
+  if (d)
+    c = a.g;
+}
+
+void
+baz (void)
+{
+  bar ();
+  a = b;
+}
+
+int
+main ()
+{
+  baz ();
+  if (a.g)
+    abort ();
+  return 0;
+}