Hi! If *anddi_2 is used with 64-bit integer constant that matches "Z" constraint, but has bit 31 set, we emit it as andl instead, but that is wrong unless just ZF is tested in the flags, because SF might be different (if operands[1] has bit 31 set, then SF from andl will be set, but for the 64-bit operation it would be clear). If constant doesn't have bit 31 set (nor any other higher bits), then SF will be 0 both when using andl or when using andq, so it is fine to keep using andl in that case.
At -O2 VRP will optimize _3 = ~a_2(D); _4 = (long long int) _3; _5 = _4 & 4102790424; if (_5 > 0) into: _3 = ~a_2(D); _4 = (long long int) _3; _5 = _4 & 4102790424; if (_5 != 0) but at -O1, -Og (or -O2 -fno-tree-vrp) it will not and then we can end up with wrong-code. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.8? 2013-11-13 Jakub Jelinek <ja...@redhat.com> PR target/59101 * config/i386/i386.md (*anddi_2): Only allow CCZmode if operands[2] is positive 64-bit constant that is negative in SImode. * gcc.c-torture/execute/pr59101.c: New test. --- gcc/config/i386/i386.md.jj 2013-11-12 11:31:31.000000000 +0100 +++ gcc/config/i386/i386.md 2013-11-13 10:14:10.981609589 +0100 @@ -7978,7 +7978,12 @@ (define_insn "*anddi_2" (const_int 0))) (set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm") (and:DI (match_dup 1) (match_dup 2)))] - "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) + "TARGET_64BIT + && ix86_match_ccmode (insn, CONST_INT_P (operands[2]) + && INTVAL (operands[2]) > 0 + && (INTVAL (operands[2]) + & (HOST_WIDE_INT_1 << 31)) != 0 + ? CCZmode : CCNOmode) && ix86_binary_operator_ok (AND, DImode, operands)" "@ and{l}\t{%k2, %k0|%k0, %k2} --- gcc/testsuite/gcc.c-torture/execute/pr59101.c.jj 2013-11-13 10:22:08.489154035 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr59101.c 2013-11-13 10:23:01.734870201 +0100 @@ -0,0 +1,15 @@ +/* PR target/59101 */ + +__attribute__((noinline, noclone)) int +foo (int a) +{ + return (~a & 4102790424LL) > 0 | 6; +} + +int +main () +{ + if (foo (0) != 7) + __builtin_abort (); + return 0; +} Jakub