fold-const: Don't access bit fields with too big mode (PR71310)
authorSegher Boessenkool <segher@kernel.crashing.org>
Fri, 10 Jun 2016 23:58:09 +0000 (01:58 +0200)
committerSegher Boessenkool <segher@gcc.gnu.org>
Fri, 10 Jun 2016 23:58:09 +0000 (01:58 +0200)
Currently, optimize_bit_field_compare reads the bitfield in word_mode
if it can.  If the bit field is normally accessed in a smaller mode,
this might be a violation of the memory model, although the "extra"
part of the read is not used.  But also, previous stores to the bit
field will have been done in the smaller mode, and then bigger loads
from it cause a LHS problem.

PR middle-end/71310
* fold-const.c (optimize_bit_field_compare): Don't try to use
word_mode unconditionally for reading the bit field, look at
DECL_BIT_FIELD_REPRESENTATIVE instead.

gcc/testsuite/
PR middle-end/71310
* gcc.target/powerpc/pr71310.c: New testcase.

From-SVN: r237319

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/pr71310.c [new file with mode: 0644]

index 508ff0eb0bca0dd3035ec97087baef1099530104..e463219cdf0fa3a02f74d5d38f4d70cc3f1c4aa8 100644 (file)
@@ -1,3 +1,10 @@
+2016-06-11  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR middle-end/71310
+       * fold-const.c (optimize_bit_field_compare): Don't try to use
+       word_mode unconditionally for reading the bit field, look at
+       DECL_BIT_FIELD_REPRESENTATIVE instead.
+
 2016-06-11  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
        PR middle-end/71478
index 0b7ea82c03422bf3b1d59e764d43748e8787bfcb..7f8803ca57d0982ba8d090720ee652af138faf9c 100644 (file)
@@ -3904,13 +3904,24 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
        return 0;
    }
 
+  /* Don't use a larger mode for reading the bit field than we will
+     use in other places accessing the bit field.  */
+  machine_mode largest_mode = word_mode;
+  if (TREE_CODE (lhs) == COMPONENT_REF)
+    {
+      tree field = TREE_OPERAND (lhs, 1);
+      tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
+      if (repr)
+       largest_mode = DECL_MODE (repr);
+    }
+
   /* See if we can find a mode to refer to this field.  We should be able to,
      but fail if we can't.  */
   nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
                         const_p ? TYPE_ALIGN (TREE_TYPE (linner))
                         : MIN (TYPE_ALIGN (TREE_TYPE (linner)),
                                TYPE_ALIGN (TREE_TYPE (rinner))),
-                        word_mode, false);
+                        largest_mode, false);
   if (nmode == VOIDmode)
     return 0;
 
index deeeff54bb8f68e64d5064e4bfc8f6f4c4c053b8..2b31ceb51917188bf52698e42cc9ab8d44809d22 100644 (file)
@@ -1,3 +1,8 @@
+2016-06-11  Segher Boessenkool  <segher@kernel.crashing.org>
+
+       PR middle-end/71310
+       * gcc.target/powerpc/pr71310.c: New testcase.
+
 2016-06-11  Kugan Vivekanandarajah  <kuganv@linaro.org>
 
        PR middle-end/71478
diff --git a/gcc/testsuite/gcc.target/powerpc/pr71310.c b/gcc/testsuite/gcc.target/powerpc/pr71310.c
new file mode 100644 (file)
index 0000000..6869a50
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-not {\mld} } } */
+/* { dg-final { scan-assembler-not {\mlwz} } } */
+/* { dg-final { scan-assembler-times {\mlbz} 2 } } */
+
+struct mmu_gather {
+        long end;
+        int fullmm : 1;
+};
+
+void __tlb_reset_range(struct mmu_gather *p1)
+{
+        if (p1->fullmm)
+                p1->end = 0;
+}
+
+void tlb_gather_mmu(struct mmu_gather *p1)
+{
+        p1->fullmm = 1;
+        __tlb_reset_range(p1);
+}