From: Jakub Jelinek Date: Wed, 21 Mar 2018 20:20:40 +0000 (+0100) Subject: re PR tree-optimization/84982 (logically inverting bools into local array results... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e215422f1d6c69ae23b09de85a97bb3925cc5bfe;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 467df5f1a49..0980eac591d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2018-03-21 Jakub Jelinek + + 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 * 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 5955d6e1abc..6f6538bf37e 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 4e787c5f8fb..f12a38357bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2018-03-21 Jakub Jelinek + 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 00000000000..3370a8313cb --- /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; +}