diff mbox

Fix *anddi_2 (PR target/59101)

Message ID 20131114081537.GZ27813@tucnak.zalov.cz
State New
Headers show

Commit Message

Jakub Jelinek Nov. 14, 2013, 8:15 a.m. UTC
On Wed, Nov 13, 2013 at 08:12:41PM +0100, Uros Bizjak wrote:
> Patch is OK everywhere, with or without the suggested change.

Ok, here is what I've committed, so far to trunk/4.8, after another
round of bootstrap/regtest:

2013-11-14  Jakub Jelinek  <jakub@redhat.com>
	    Uros Bizjak  <ubizjak@gmail.com>

	PR target/59101
	* config/i386/i386.md (*anddi_2): Only allow CCZmode if
	operands[2] satisfies_constraint_Z that might have bit 31 set.

	* gcc.c-torture/execute/pr59101.c: New test.



	Jakub
diff mbox

Patch

--- gcc/config/i386/i386.md.jj	2013-11-13 19:17:58.281733148 +0100
+++ gcc/config/i386/i386.md	2013-11-13 20:41:08.941030127 +0100
@@ -7978,7 +7978,18 @@  (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.  */
+	 (satisfies_constraint_Z (operands[2])
+	  && (!CONST_INT_P (operands[2])
+	      || val_signbit_known_set_p (SImode, INTVAL (operands[2]))))
+	 ? 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 20:37:47.795031458 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr59101.c	2013-11-13 20:37:47.795031458 +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;
+}