Re: [PATCH, i386]: Fix PR78626, wrong code with -fschedule-insns
On Wed, Nov 9, 2016 at 8:25 PM, Uros Bizjak wrote: > Hello! > > We need earlyclobber on output operand of doubleword shift insns, > since we have to prevent (partial) output matching %ecx as count > argument. > > 2016-11-09 Uros Bizjak > > PR target/78262 > * config/i386/i386.md (*3_doubleword): Mark > operand 0 as earlyclobber. > > testsuite/ChangeLog: > > 2016-11-09 Uros Bizjak > > PR target/78262 > * gcc.target/i386/pr78262.c: New test. > > Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. > > Committed to mainline, will be backported to release branches. Actually, we have also to add earlyclobber to all operand 0 alternatives of *ashl3_doubleword pattern to prevent similar issue. PR target/78262 * config/i386/i386.md (*3_doubleword): Mark operand 0 as earlyclobber. (*ashl3_doubleword): Ditto for all operand 0 alternatives. I have amended the patch with attached part. Uros. Index: config/i386/i386.md === --- config/i386/i386.md (revision 242076) +++ config/i386/i386.md (working copy) @@ -9704,7 +9704,7 @@ "ix86_expand_binary_operator (ASHIFT, mode, operands); DONE;") (define_insn "*ashl3_doubleword" - [(set (match_operand:DWI 0 "register_operand" "=&r,r") + [(set (match_operand:DWI 0 "register_operand" "=&r,&r") (ashift:DWI (match_operand:DWI 1 "reg_or_pm1_operand" "n,0") (match_operand:QI 2 "nonmemory_operand" "c,c"))) (clobber (reg:CC FLAGS_REG))]
[PATCH, i386]: Fix PR78626, wrong code with -fschedule-insns
Hello! We need earlyclobber on output operand of doubleword shift insns, since we have to prevent (partial) output matching %ecx as count argument. 2016-11-09 Uros Bizjak PR target/78262 * config/i386/i386.md (*3_doubleword): Mark operand 0 as earlyclobber. testsuite/ChangeLog: 2016-11-09 Uros Bizjak PR target/78262 * gcc.target/i386/pr78262.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 242004) +++ config/i386/i386.md (working copy) @@ -10339,7 +10339,7 @@ "operands[2] = gen_lowpart (QImode, operands[2]);") (define_insn_and_split "*3_doubleword" - [(set (match_operand:DWI 0 "register_operand" "=r") + [(set (match_operand:DWI 0 "register_operand" "=&r") (any_shiftrt:DWI (match_operand:DWI 1 "register_operand" "0") (match_operand:QI 2 "nonmemory_operand" "c"))) (clobber (reg:CC FLAGS_REG))] Index: testsuite/gcc.target/i386/pr78262.c === --- testsuite/gcc.target/i386/pr78262.c (nonexistent) +++ testsuite/gcc.target/i386/pr78262.c (working copy) @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int128 } */ +/* { dg-options "-O -fschedule-insns" } */ + +typedef unsigned char u8; +typedef unsigned __int128 u128; + +static u128 u128_0; +static u128 *p128; + +u128 __attribute__ ((noinline, noclone)) +foo(u8 u8_0) +{ + p128 = &u128_0; + u128_0 = u8_0; + u128_0 = u128_0 << 127 | u128_0 >> 1; + u128_0 >>= (u8)u128_0; + return 2 + u128_0; +} + +int +main() +{ + u128 x = foo(5); + if (p128 != &u128_0) +__builtin_abort(); + if (u128_0 != ((u128)2 << 124)) +__builtin_abort(); + if (x != ((u128)2 << 124) + 2) +__builtin_abort(); + return 0; +}