diff options
author | Jakub Jelinek <jakub@redhat.com> | 2013-05-17 15:32:50 +0000 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2013-05-17 15:32:50 +0000 |
commit | 326e59fb0a4d4eb1a5a1ad51faecb75f3400b11b (patch) | |
tree | 2fb4ea4adfb26ac3284ac3d647b485a077682d1d /gcc/config | |
parent | 04d5e4b640eaf877f386a51ecbc947207e8008df (diff) |
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.
* gcc.dg/pr57300.c: New test.
* gcc.c-torture/execute/pr57281.c: New test.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-4_8-branch@199021 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/i386.md | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 2e450e3d526..455fb63f510 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -3647,22 +3647,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"))) @@ -3691,6 +3677,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 |