The following fixes PR71762 via reverting the transforms of
~X & Y to X < Y and similar because when the bools they apply to
are expanded to RTL undefined values are not reliably zero-extended
and thus the transform is invalid. Ensuring the zero-extension
is too costly IMHO and the proper fix is to move the transform
to RTL where we can check known-zero-bits to validate validity
or to fix GIMPLE not not have operations on types not matching their mode
in precision.
Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk
and branches?
Any takers for the RTL implementation?
Thanks,
Richard.
2016-11-10 Richard Biener
PR middle-end/71762
* match.pd ((~X & Y) -> X < Y, (X & ~Y) -> Y < X,
(~X | Y) -> X <= Y, (X | ~Y) -> Y <= X): Remove.
* gcc.dg/torture/pr71762-1.c: New testcase.
* gcc.dg/torture/pr71762-2.c: Likewise.
* gcc.dg/torture/pr71762-3.c: Likewise.
* gcc.dg/tree-ssa/forwprop-28.c: XFAIL.
Index: gcc/match.pd
===
--- gcc/match.pd(revision 242004)
+++ gcc/match.pd(working copy)
@@ -944,33 +944,6 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(op:c truth_valued_p@0 (logical_inverted_value @0))
{ constant_boolean_node (op == NE_EXPR ? true : false, type); }))
-/* If arg1 and arg2 are booleans (or any single bit type)
- then try to simplify:
-
- (~X & Y) -> X < Y
- (X & ~Y) -> Y < X
- (~X | Y) -> X <= Y
- (X | ~Y) -> Y <= X
-
- But only do this if our result feeds into a comparison as
- this transformation is not always a win, particularly on
- targets with and-not instructions.
- -> simplify_bitwise_binary_boolean */
-(simplify
- (ne (bit_and:c (bit_not @0) @1) integer_zerop)
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
- && TYPE_PRECISION (TREE_TYPE (@1)) == 1)
- (if (TYPE_UNSIGNED (TREE_TYPE (@1)))
-(lt @0 @1)
-(gt @0 @1
-(simplify
- (ne (bit_ior:c (bit_not @0) @1) integer_zerop)
- (if (INTEGRAL_TYPE_P (TREE_TYPE (@1))
- && TYPE_PRECISION (TREE_TYPE (@1)) == 1)
- (if (TYPE_UNSIGNED (TREE_TYPE (@1)))
-(le @0 @1)
-(ge @0 @1
-
/* ~~x -> x */
(simplify
(bit_not (bit_not @0))
Index: gcc/testsuite/gcc.dg/torture/pr71762-1.c
===
--- gcc/testsuite/gcc.dg/torture/pr71762-1.c(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr71762-1.c(working copy)
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fdisable-rtl-init-regs" } */
+
+static _Bool
+foo (_Bool a, _Bool b)
+{
+ int x = a && ! b;
+ return x != 0;
+}
+
+int y = 1;
+int main()
+{
+ _Bool x;
+ if (foo (x, y))
+__builtin_abort ();
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr71762-2.c
===
--- gcc/testsuite/gcc.dg/torture/pr71762-2.c(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr71762-2.c(working copy)
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+
+static _Bool
+foo (_Bool a, _Bool b)
+{
+ int x = a && ! b;
+ return x != 0;
+}
+
+int y = 1;
+int main()
+{
+ _Bool x[32];
+ if (foo (x[1], y))
+__builtin_abort ();
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/torture/pr71762-3.c
===
--- gcc/testsuite/gcc.dg/torture/pr71762-3.c(revision 0)
+++ gcc/testsuite/gcc.dg/torture/pr71762-3.c(working copy)
@@ -0,0 +1,22 @@
+/* { dg-do run } */
+
+static _Bool
+foo (_Bool a, _Bool b)
+{
+ int x = a && ! b;
+ return x != 0;
+}
+
+int y = 1;
+int main()
+{
+ register _Bool x
+ /* Add register spec for the argv parameter to main. */
+#if __i386__ || __x86_64__
+ __asm__("%esi")
+#endif
+;
+ if (foo (x, y))
+__builtin_abort ();
+ return 0;
+}
Index: gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c
===
--- gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c (revision 242032)
+++ gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c (working copy)
@@ -83,6 +83,8 @@ test_8 (int code)
to a ordered compare. But the transform does not trigger if we transform
the negated code == 22 compare to code != 22 first. It turns out if
we do that we even generate better code on x86 at least. */
+/* ??? As PR71762 notices this transform causes wrong-code issues in RTL
+ with one uninitialized operand, thus it has been disabled. */
-/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* \[<>\]" 4
"forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "simplified to if \\\(\[^ ]* \[<>\]" 4
"forwprop1" { xfail *-*-* } } } */