diff mbox

[i386] : Fix PR 81300, -fpeephole2 breaks __builtin_ia32_sbb_u64, _subborrow_u64 on AMD64

Message ID CAFULd4Yj-b0vef0qzFxwMat_GHuJvuy+BKTfjJ75XfoNrsjscA@mail.gmail.com
State New
Headers show

Commit Message

Uros Bizjak July 4, 2017, 8:58 p.m. UTC
Hello!

Attached patch tightens peephole2 condition to prevent unwanted
flags_reg clobbering by insn patterns, emitted by ix86_expand_clear.

2017-07-04  Uros Bizjak  <ubizjak@gmail.com>

    PR target/81300
    * config/i386/i386.md (setcc + movzbl/and to xor + setcc peepholes):
    Require dead FLAGS_REG at the beginning of a peephole.

testsuite/ChangeLog:

2017-07-04  Uros Bizjak  <ubizjak@gmail.com>

    PR target/81300
    * gcc.target/i386/pr81300.c: New test.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Committed to mainline, will be backported to release branches.

Uros.
diff mbox

Patch

Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 249971)
+++ config/i386/i386.md	(working copy)
@@ -11754,7 +11754,8 @@ 
 	(zero_extend (match_dup 1)))]
   "(peep2_reg_dead_p (3, operands[1])
     || operands_match_p (operands[1], operands[3]))
-   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+   && ! reg_overlap_mentioned_p (operands[3], operands[0])
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(set (match_dup 4) (match_dup 0))
    (set (strict_low_part (match_dup 5))
 	(match_dup 2))]
@@ -11775,7 +11776,8 @@ 
   "(peep2_reg_dead_p (3, operands[1])
     || operands_match_p (operands[1], operands[3]))
    && ! reg_overlap_mentioned_p (operands[3], operands[0])
-   && ! reg_set_p (operands[3], operands[4])"
+   && ! reg_set_p (operands[3], operands[4])
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 5) (match_dup 0))
 	      (match_dup 4)])
    (set (strict_low_part (match_dup 6))
@@ -11797,7 +11799,8 @@ 
 		   (and:SI (match_dup 3) (const_int 255)))
 	      (clobber (reg:CC FLAGS_REG))])]
   "REGNO (operands[1]) == REGNO (operands[3])
-   && ! reg_overlap_mentioned_p (operands[3], operands[0])"
+   && ! reg_overlap_mentioned_p (operands[3], operands[0])
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(set (match_dup 4) (match_dup 0))
    (set (strict_low_part (match_dup 5))
 	(match_dup 2))]
@@ -11819,7 +11822,8 @@ 
   "(peep2_reg_dead_p (3, operands[1])
     || operands_match_p (operands[1], operands[3]))
    && ! reg_overlap_mentioned_p (operands[3], operands[0])
-   && ! reg_set_p (operands[3], operands[4])"
+   && ! reg_set_p (operands[3], operands[4])
+   && peep2_regno_dead_p (0, FLAGS_REG)"
   [(parallel [(set (match_dup 5) (match_dup 0))
 	      (match_dup 4)])
    (set (strict_low_part (match_dup 6))
Index: testsuite/gcc.target/i386/pr81300.c
===================================================================
--- testsuite/gcc.target/i386/pr81300.c	(nonexistent)
+++ testsuite/gcc.target/i386/pr81300.c	(working copy)
@@ -0,0 +1,30 @@ 
+/* PR target/81300 */
+/* { dg-do run { target { ! ia32 } } } */
+/* { dg-options "-O2" } */
+
+int
+__attribute__((noinline, noclone))
+foo (void)
+{
+  unsigned long long _discard = 0, zero = 0, maxull = 0;
+  unsigned char zero1 = __builtin_ia32_addcarryx_u64 (0, 0, 0, &_discard);
+  unsigned char zero2 = __builtin_ia32_addcarryx_u64 (zero1, 0, 0, &zero);
+  __builtin_ia32_sbb_u64 (0x0, 2, -1, &_discard);
+  unsigned char one = __builtin_ia32_sbb_u64 (0, zero, 1, &maxull);
+  unsigned long long x = __builtin_ia32_sbb_u64 (one, zero2, 0, &_discard);
+
+  unsigned long long z1 = 0;
+  __asm__ ("mov{q}\t{%1, %0|%0, %1}" : "+r" (z1) : "r" (x));
+  unsigned long long z2 = 3;
+  __asm__ ("mov{q}\t{%1, %0|%0, %1}" : "+r" (z2) : "r" (x));
+
+  return 1 - (z1 | z2);
+}
+
+int main ()
+{
+  if (foo ())
+    __builtin_abort ();
+
+  return 0;
+}