diff options
author | Jan Hubicka <jh@suse.cz> | 2000-01-11 19:01:35 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2000-01-11 18:01:35 +0000 |
commit | f90800f836965874b1025412cd1690638edfce07 (patch) | |
tree | c2b4db48b098c107384d99fe3760bbd090cd10b7 | |
parent | 1e7a71c15355d9e092bd76ec5eb4317a114587f5 (diff) | |
download | gcc-f90800f836965874b1025412cd1690638edfce07.zip gcc-f90800f836965874b1025412cd1690638edfce07.tar.gz gcc-f90800f836965874b1025412cd1690638edfce07.tar.bz2 |
i386.md (movstrsi expander): Rewrite.
* i386.md (movstrsi expander): Rewrite.
(movstrsi_1 insn): Deleted.
(strmovhi, strmovqi expander): New expanders.
(movshi_1, movsqi_1, rep_movsi, rep_movqi): New patterns.
* i386.c (x86_single_stringop): New global variable.
* i386.h (x86_single_stringop): Declare.
(TARGET_SINGLE_STRINGOP): New macro.
From-SVN: r31329
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 3 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 191 |
4 files changed, 153 insertions, 52 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb6600a..0640895 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +Tue Jan 11 18:59:35 MET 2000 Jan Hubicka <jh@suse.cz> + + * i386.md (movstrsi expander): Rewrite. + (movstrsi_1 insn): Deleted. + (strmovhi, strmovqi expander): New expanders. + (movshi_1, movsqi_1, rep_movsi, rep_movqi): New patterns. + * i386.c (x86_single_stringop): New global variable. + * i386.h (x86_single_stringop): Declare. + (TARGET_SINGLE_STRINGOP): New macro. + 2000-01-11 Clinton Popetz <cpopetz@cygnus.com> * config/mips/mips.c (mips_va_arg): For EABI, emit the queued diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index d35bafb..f2d98a4 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -206,6 +206,7 @@ const int x86_read_modify_write = ~m_PENT; const int x86_read_modify = ~(m_PENT | m_PPRO); const int x86_split_long_moves = m_PPRO; const int x86_promote_QImode = m_K6 | m_PENT | m_386 | m_486; +const int x86_single_stringop = m_386; #define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx)) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index ed7f849..62883d7 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -161,7 +161,7 @@ extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx; extern const int x86_use_loop, x86_use_fiop, x86_use_mov0; extern const int x86_use_cltd, x86_read_modify_write; extern const int x86_read_modify, x86_split_long_moves; -extern const int x86_promote_QImode; +extern const int x86_promote_QImode, x86_single_stringop; #define TARGET_USE_LEAVE (x86_use_leave & CPUMASK) #define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK) @@ -184,6 +184,7 @@ extern const int x86_promote_QImode; #define TARGET_READ_MODIFY_WRITE (x86_read_modify_write & CPUMASK) #define TARGET_READ_MODIFY (x86_read_modify & CPUMASK) #define TARGET_PROMOTE_QImode (x86_promote_QImode & CPUMASK) +#define TARGET_SINGLE_STRINGOP (x86_single_stringop & CPUMASK) #define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 6fd7c8e..2f7aa6a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -7825,71 +7825,162 @@ [(set_attr "type" "cld")]) (define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:SI 2 "const_int_operand" "")) - (use (match_operand:SI 3 "const_int_operand" "")) - (use (reg:SI 19)) - (clobber (match_scratch:SI 4 "")) - (clobber (match_dup 5)) - (clobber (match_dup 6))])] + [(use (match_operand:BLK 0 "memory_operand" "")) + (use (match_operand:BLK 1 "memory_operand" "")) + (use (match_operand:SI 2 "const_int_operand" "")) + (use (match_operand:SI 3 "const_int_operand" ""))] "" " { - rtx addr0, addr1; + rtx srcreg, destreg, countreg; if (GET_CODE (operands[2]) != CONST_INT) FAIL; - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); + destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); + srcreg = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - operands[5] = addr0; - operands[6] = addr1; - - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); - emit_insn (gen_cld ()); + emit_insn (gen_cld()); + /* When optimizing for size emit simple rep ; movsb instruction. */ + if (!optimize || optimize_size) + { + countreg = copy_to_mode_reg (SImode, operands[2]); + emit_insn (gen_rep_movqi (destreg, srcreg, countreg, + destreg, srcreg, countreg)); + } + else + { + if (INTVAL (operands[2]) & ~0x03) + { + countreg = copy_to_mode_reg (SImode, + GEN_INT ((INTVAL (operands[2]) >> 2) + & 0x3fffffff)); + emit_insn (gen_rep_movsi (destreg, srcreg, countreg, + destreg, srcreg, countreg)); + } + if (INTVAL (operands[2]) & 0x02) + emit_insn (gen_strmovhi (destreg, srcreg)); + if (INTVAL (operands[2]) & 0x01) + emit_insn (gen_strmovqi (destreg, srcreg)); + } + DONE; }") -;; It might seem that operands 0 & 1 could use predicate register_operand. -;; But strength reduction might offset the MEM expression. So we let -;; reload put the address into %edi & %esi. +;; Most CPUs don't like single string operations +;; Handle this case here to simplify previous expander. -(define_insn "*movstrsi_1" - [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) - (mem:BLK (match_operand:SI 1 "address_operand" "S"))) - (use (match_operand:SI 2 "const_int_operand" "n")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (use (reg:SI 19)) - (clobber (match_scratch:SI 4 "=&c")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] +(define_expand "strmovhi" + [(set (match_dup 2) + (mem:HI (match_operand:SI 1 "register_operand" ""))) + (set (mem:HI (match_operand:SI 0 "register_operand" "")) + (match_dup 2)) + (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2))) + (clobber (reg:CC 17))]) + (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 2))) + (clobber (reg:CC 17))])] "" - "* + " { - rtx xops[2]; - - if (GET_CODE (operands[2]) == CONST_INT) + if (TARGET_SINGLE_STRINGOP || optimize_size) { - if (INTVAL (operands[2]) & ~0x03) - { - xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff); - xops[1] = operands[4]; + emit_insn (gen_strmovhi_1 (operands[0], operands[1], operands[0], + operands[1])); + DONE; + } + else + operands[2] = gen_reg_rtx (HImode); +}") - output_asm_insn (\"mov{l}\\t{%0, %1|%1,%0}\", xops); - output_asm_insn (\"{rep\;movsl|rep movsd}\", xops); - } - if (INTVAL (operands[2]) & 0x02) - output_asm_insn (\"movsw\", operands); - if (INTVAL (operands[2]) & 0x01) - output_asm_insn (\"movsb\", operands); +(define_expand "strmovqi" + [(set (match_dup 2) + (mem:QI (match_operand:SI 1 "register_operand" ""))) + (set (mem:QI (match_operand:SI 0 "register_operand" "")) + (match_dup 2)) + (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1))) + (clobber (reg:CC 17))]) + (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 1))) + (clobber (reg:CC 17))])] + "" + " +{ + if (TARGET_SINGLE_STRINGOP || optimize_size) + { + emit_insn (gen_strmovqi_1 (operands[0], operands[1], operands[0], + operands[1])); + DONE; } - else - abort (); - RET; -}" - [(set_attr "type" "multi")]) + else + operands[2] = gen_reg_rtx (QImode); +}") + +(define_insn "strmovhi_1" + [(set (mem:HI (match_operand:SI 2 "register_operand" "0")) + (mem:HI (match_operand:SI 3 "register_operand" "1"))) + (set (match_operand:SI 0 "register_operand" "=D") + (plus:SI (match_dup 0) + (const_int 2))) + (set (match_operand:SI 1 "register_operand" "=S") + (plus:SI (match_dup 1) + (const_int 2))) + (use (reg:SI 19))] + "TARGET_SINGLE_STRINGOP || optimize_size" + "movsw" + [(set_attr "type" "str") + (set_attr "memory" "both") + (set_attr "length_prefix" "1")]) + +(define_insn "strmovqi_1" + [(set (mem:QI (match_operand:SI 2 "register_operand" "0")) + (mem:QI (match_operand:SI 3 "register_operand" "1"))) + (set (match_operand:SI 0 "register_operand" "=D") + (plus:SI (match_dup 0) + (const_int 1))) + (set (match_operand:SI 1 "register_operand" "=S") + (plus:SI (match_dup 1) + (const_int 1))) + (use (reg:SI 19))] + "TARGET_SINGLE_STRINGOP || optimize_size" + "movsb" + [(set_attr "type" "str") + (set_attr "memory" "both")]) + +;; It might seem that operands 3 & 4 could use predicate register_operand. +;; But strength reduction might offset the MEM expression. So we let +;; reload put the address into %edi & %esi. + +(define_insn "rep_movsi" + [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0)) + (use (match_operand:SI 5 "register_operand" "2")) + (set (match_operand:SI 0 "register_operand" "=D") + (plus:SI (match_operand:SI 3 "address_operand" "0") + (ashift:SI (match_dup 5) (const_int 2)))) + (set (match_operand:SI 1 "register_operand" "=S") + (plus:SI (match_operand:SI 4 "address_operand" "1") + (ashift:SI (match_dup 5) (const_int 2)))) + (set (mem:BLK (match_dup 3)) + (mem:BLK (match_dup 4))) + (use (reg:SI 19))] + "" + "rep\;movsl|rep movsd" + [(set_attr "type" "str") + (set_attr "length_prefix" "1") + (set_attr "memory" "both")]) + +(define_insn "rep_movqi" + [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0)) + (use (match_operand:SI 5 "register_operand" "2")) + (set (match_operand:SI 0 "register_operand" "=D") + (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 5))) + (set (match_operand:SI 1 "register_operand" "=S") + (plus:SI (match_operand:SI 4 "address_operand" "1") (match_dup 5))) + (set (mem:BLK (match_dup 3)) + (mem:BLK (match_dup 4))) + (use (reg:SI 19))] + "" + "rep\;movsb|rep movsb" + [(set_attr "type" "str") + (set_attr "length_prefix" "1") + (set_attr "memory" "both")]) (define_expand "clrstrsi" [(set (reg:SI 19) (const_int 0)) @@ -7916,8 +8007,6 @@ operands[5] = addr0; operands[0] = gen_rtx_MEM (BLKmode, addr0); - - emit_insn (gen_cld ()); }") ;; It might seem that operand 0 could use predicate register_operand. |