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 <ubiz...@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 <ubiz...@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.
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; +}