@@ -7978,7 +7978,20 @@ (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,
+ /* If we are going to emit andl instead of andq,
+ and the operands[2] constant might have the
+ SImode sign bit set, make sure the sign flag isn't
+ tested, because the instruction will set the sign
+ flag based on bit 31 rather than bit 63.
+ If it isn't CONST_INT, conservatively assume
+ it might have bit 31 set. */
+ (x86_64_zext_immediate_operand (operands[2], VOIDmode)
+ && (!CONST_INT_P (operands[2])
+ || (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}
@@ -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;
+}