diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4caa40276120fa16d5b96ab0b3504560f597e600..4c406123b5fcfe44b6a0503eb327352f494d723f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2013-05-17 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/57281 + PR rtl-optimization/57300 + * config/i386/i386.md (extendsidi2_1 dead reg splitter): Remove. + (extendsidi2_1 peephole2s): Add instead 2 new peephole2s, that undo + what the other splitter did if the registers are dead. + 2013-05-17 Richard Biener <rguenther@suse.de> * tree-ssa-alias.c (stmt_kills_ref_p_1): Properly compare diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 6361649208769ba8632f27e0da1493b7f52bb94a..ce77f15f00923af1863b78fe5e33035c5e65a25f 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3332,22 +3332,8 @@ "!TARGET_64BIT" "#") -;; Extend to memory case when source register does die. -(define_split - [(set (match_operand:DI 0 "memory_operand") - (sign_extend:DI (match_operand:SI 1 "register_operand"))) - (clobber (reg:CC FLAGS_REG)) - (clobber (match_operand:SI 2 "register_operand"))] - "(reload_completed - && dead_or_set_p (insn, operands[1]) - && !reg_mentioned_p (operands[1], operands[0]))" - [(set (match_dup 3) (match_dup 1)) - (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) - (clobber (reg:CC FLAGS_REG))]) - (set (match_dup 4) (match_dup 1))] - "split_double_mode (DImode, &operands[0], 1, &operands[3], &operands[4]);") - -;; Extend to memory case when source register does not die. +;; Split the memory case. If the source register doesn't die, it will stay +;; this way, if it does die, following peephole2s take care of it. (define_split [(set (match_operand:DI 0 "memory_operand") (sign_extend:DI (match_operand:SI 1 "register_operand"))) @@ -3376,6 +3362,44 @@ DONE; }) +;; Peepholes for the case where the source register does die, after +;; being split with the above splitter. +(define_peephole2 + [(set (match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "register_operand")) + (set (match_operand:SI 2 "register_operand") (match_dup 1)) + (parallel [(set (match_dup 2) + (ashiftrt:SI (match_dup 2) (const_int 31))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_operand:SI 3 "memory_operand") (match_dup 2))] + "REGNO (operands[1]) != REGNO (operands[2]) + && peep2_reg_dead_p (2, operands[1]) + && peep2_reg_dead_p (4, operands[2]) + && !reg_mentioned_p (operands[2], operands[3])" + [(set (match_dup 0) (match_dup 1)) + (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_dup 3) (match_dup 1))]) + +(define_peephole2 + [(set (match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "register_operand")) + (parallel [(set (match_operand:SI 2 "register_operand") + (ashiftrt:SI (match_dup 1) (const_int 31))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_operand:SI 3 "memory_operand") (match_dup 2))] + "/* cltd is shorter than sarl $31, %eax */ + !optimize_function_for_size_p (cfun) + && true_regnum (operands[1]) == AX_REG + && true_regnum (operands[2]) == DX_REG + && peep2_reg_dead_p (2, operands[1]) + && peep2_reg_dead_p (3, operands[2]) + && !reg_mentioned_p (operands[2], operands[3])" + [(set (match_dup 0) (match_dup 1)) + (parallel [(set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) + (clobber (reg:CC FLAGS_REG))]) + (set (match_dup 3) (match_dup 1))]) + ;; Extend to register case. Optimize case where source and destination ;; registers match and cases where we can use cltd. (define_split diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b2ec2636c7a5c0e3fb042f88175adbf815820564..599bcd159a63211ef22d6de681c132be89517936 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2013-05-17 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/57281 + PR rtl-optimization/57300 + * gcc.dg/pr57300.c: New test. + * gcc.c-torture/execute/pr57281.c: New test. + 2013-05-17 Paolo Carlini <paolo.carlini@oracle.com> PR c++/18126 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr57281.c b/gcc/testsuite/gcc.c-torture/execute/pr57281.c new file mode 100644 index 0000000000000000000000000000000000000000..db3db10d9e75074069df3dd3710608cb58be7253 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr57281.c @@ -0,0 +1,25 @@ +/* PR rtl-optimization/57281 */ + +int a = 1, b, d, *e = &d; +long long c, *g = &c; +volatile long long f; + +int +foo (int h) +{ + int j = *g = b; + return h == 0 ? j : 0; +} + +int +main () +{ + int h = a; + for (; b != -20; b--) + { + (int) f; + *e = 0; + *e = foo (h); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr57300.c b/gcc/testsuite/gcc.dg/pr57300.c new file mode 100644 index 0000000000000000000000000000000000000000..13a272de59fe32ce2e8f8ee6b275468e986b4529 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr57300.c @@ -0,0 +1,21 @@ +/* PR rtl-optimization/57300 */ +/* { dg-do run } */ +/* { dg-options "-O3" } */ +/* { dg-additional-options "-msse2" { target sse2_runtime } } */ + +extern void abort (void); +int a, b, d[10]; +long long c; + +int +main () +{ + int e; + for (e = 0; e < 10; e++) + d[e] = 1; + if (d[0]) + c = a = (b == 0 || 1 % b); + if (a != 1) + abort (); + return 0; +}