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 <rguent...@suse.de> 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 *-*-* } } } */