diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-03-21 21:20:40 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-03-21 21:20:40 +0100 |
commit | e215422f1d6c69ae23b09de85a97bb3925cc5bfe (patch) | |
tree | 1e258992b30bc6e92a03d29ded42a6af6cd3dde3 /gcc | |
parent | 57e20f74e011f190a29ec0b414c0ee74e62ebdc9 (diff) | |
download | gcc-e215422f1d6c69ae23b09de85a97bb3925cc5bfe.zip gcc-e215422f1d6c69ae23b09de85a97bb3925cc5bfe.tar.gz gcc-e215422f1d6c69ae23b09de85a97bb3925cc5bfe.tar.bz2 |
re PR tree-optimization/84982 (logically inverting bools into local array results in bitwise negation)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/gimple-ssa-store-merging.c | 41 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/pr84982.c | 38 |
4 files changed, 86 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 467df5f..0980eac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index 5955d6e..6f6538b 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -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); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e787c5..f12a383 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..3370a83 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr84982.c @@ -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; +} |