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

Reply via email to