re PR tree-optimization/84982 (logically inverting bools into local array results...
authorJakub Jelinek <jakub@redhat.com>
Wed, 21 Mar 2018 20:20:40 +0000 (21:20 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 21 Mar 2018 20:20:40 +0000 (21:20 +0100)
PR tree-optimization/84982
* gimple-ssa-store-merging.c (invert_op): Handle boolean inversion
by flipping the least significant bit rather than all bits from
bitpos to bitpos + bitsize - 1.

* c-c++-common/pr84982.c: New test.

From-SVN: r258742

gcc/ChangeLog
gcc/gimple-ssa-store-merging.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/pr84982.c [new file with mode: 0644]

index 467df5f1a49d900f58740239df4af1910b6e9024..0980eac591de1d8f7a871b9e55dd8bb8cab9fa51 100644 (file)
@@ -1,3 +1,10 @@
+2018-03-21  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/84982
+       * gimple-ssa-store-merging.c (invert_op): Handle boolean inversion
+       by flipping the least significant bit rather than all bits from
+       bitpos to bitpos + bitsize - 1.
+
 2018-03-21  Nathan Sidwell  <nathan@acm.org>
 
        * doc/extend.texi (Deprecated Features): Remove mention of
index 5955d6e1abc0efe449955d138677a387e153ff53..6f6538bf37eaa72b45a4bd0a32a53668a7648a9c 100644 (file)
@@ -3248,16 +3248,23 @@ invert_op (split_store *split_store, int idx, tree int_type, tree &mask)
   unsigned int i;
   store_immediate_info *info;
   unsigned int cnt = 0;
+  bool any_paddings = false;
   FOR_EACH_VEC_ELT (split_store->orig_stores, i, info)
     {
       bool bit_not_p = idx < 2 ? info->ops[idx].bit_not_p : info->bit_not_p;
       if (bit_not_p)
-       ++cnt;
+       {
+         ++cnt;
+         tree lhs = gimple_assign_lhs (info->stmt);
+         if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+             && TYPE_PRECISION (TREE_TYPE (lhs)) < info->bitsize)
+           any_paddings = true;
+       }
     }
   mask = NULL_TREE;
   if (cnt == 0)
     return NOP_EXPR;
-  if (cnt == split_store->orig_stores.length ())
+  if (cnt == split_store->orig_stores.length () && !any_paddings)
     return BIT_NOT_EXPR;
 
   unsigned HOST_WIDE_INT try_bitpos = split_store->bytepos * BITS_PER_UNIT;
@@ -3274,14 +3281,42 @@ invert_op (split_store *split_store, int idx, tree int_type, tree &mask)
         clear regions with !bit_not_p, so that gaps in between stores aren't
         set in the mask.  */
       unsigned HOST_WIDE_INT bitsize = info->bitsize;
+      unsigned HOST_WIDE_INT prec = bitsize;
       unsigned int pos_in_buffer = 0;
+      if (any_paddings)
+       {
+         tree lhs = gimple_assign_lhs (info->stmt);
+         if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+             && TYPE_PRECISION (TREE_TYPE (lhs)) < bitsize)
+           prec = TYPE_PRECISION (TREE_TYPE (lhs));
+       }
       if (info->bitpos < try_bitpos)
        {
          gcc_assert (info->bitpos + bitsize > try_bitpos);
-         bitsize -= (try_bitpos - info->bitpos);
+         if (!BYTES_BIG_ENDIAN)
+           {
+             if (prec <= try_bitpos - info->bitpos)
+               continue;
+             prec -= try_bitpos - info->bitpos;
+           }
+         bitsize -= try_bitpos - info->bitpos;
+         if (BYTES_BIG_ENDIAN && prec > bitsize)
+           prec = bitsize;
        }
       else
        pos_in_buffer = info->bitpos - try_bitpos;
+      if (prec < bitsize)
+       {
+         /* If this is a bool inversion, invert just the least significant
+            prec bits rather than all bits of it.  */
+         if (BYTES_BIG_ENDIAN)
+           {
+             pos_in_buffer += bitsize - prec;
+             if (pos_in_buffer >= split_store->size)
+               continue;
+           }
+         bitsize = prec;
+       }
       if (pos_in_buffer + bitsize > split_store->size)
        bitsize = split_store->size - pos_in_buffer;
       unsigned char *p = buf + (pos_in_buffer / BITS_PER_UNIT);
index 4e787c5f8fb86daa5f74597c8d4b79ab244958bb..f12a38357bbaff3b31f807cea953d2f4652f13a4 100644 (file)
@@ -1,5 +1,8 @@
 2018-03-21  Jakub Jelinek  <jakub@redhat.com>
 
+       PR tree-optimization/84982
+       * c-c++-common/pr84982.c: New test.
+
        PR c++/84961
        * c-c++-common/pr43690.c: Don't expect errors on "m" (--x) and
        "m" (++x) in C++.
diff --git a/gcc/testsuite/c-c++-common/pr84982.c b/gcc/testsuite/c-c++-common/pr84982.c
new file mode 100644 (file)
index 0000000..3370a83
--- /dev/null
@@ -0,0 +1,38 @@
+/* PR tree-optimization/84982 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#ifndef __cplusplus
+#define bool _Bool
+#define true 1
+#define false 0
+#endif
+
+struct S { bool a, b, c, d; };
+
+__attribute__((noipa)) void
+bar (bool *x)
+{
+  if (x[0] || !x[1] || !x[2] || x[3])
+    __builtin_abort ();
+}
+
+__attribute__((noipa)) void
+foo (struct S *x)
+{
+  bool a[4];
+  a[0] = !x->a;
+  a[1] = !x->b;
+  a[2] = x->c;
+  a[3] = !x->d;
+  bar (a);
+} 
+
+int
+main ()
+{
+  struct S s;
+  s.a = true; s.b = false; s.c = true; s.d = true;
+  foo (&s);
+  return 0;
+}