Commit f90800f8 by Jan Hubicka Committed by Jan Hubicka

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
parent 1e7a71c1
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> 2000-01-11 Clinton Popetz <cpopetz@cygnus.com>
* config/mips/mips.c (mips_va_arg): For EABI, emit the queued * config/mips/mips.c (mips_va_arg): For EABI, emit the queued
......
...@@ -206,6 +206,7 @@ const int x86_read_modify_write = ~m_PENT; ...@@ -206,6 +206,7 @@ const int x86_read_modify_write = ~m_PENT;
const int x86_read_modify = ~(m_PENT | m_PPRO); const int x86_read_modify = ~(m_PENT | m_PPRO);
const int x86_split_long_moves = 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_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)) #define AT_BP(mode) (gen_rtx_MEM ((mode), frame_pointer_rtx))
......
...@@ -161,7 +161,7 @@ extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx; ...@@ -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_loop, x86_use_fiop, x86_use_mov0;
extern const int x86_use_cltd, x86_read_modify_write; extern const int x86_use_cltd, x86_read_modify_write;
extern const int x86_read_modify, x86_split_long_moves; 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_USE_LEAVE (x86_use_leave & CPUMASK)
#define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK) #define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
...@@ -184,6 +184,7 @@ extern const int x86_promote_QImode; ...@@ -184,6 +184,7 @@ extern const int x86_promote_QImode;
#define TARGET_READ_MODIFY_WRITE (x86_read_modify_write & CPUMASK) #define TARGET_READ_MODIFY_WRITE (x86_read_modify_write & CPUMASK)
#define TARGET_READ_MODIFY (x86_read_modify & CPUMASK) #define TARGET_READ_MODIFY (x86_read_modify & CPUMASK)
#define TARGET_PROMOTE_QImode (x86_promote_QImode & 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) #define TARGET_STACK_PROBE (target_flags & MASK_STACK_PROBE)
......
...@@ -7825,71 +7825,162 @@ ...@@ -7825,71 +7825,162 @@
[(set_attr "type" "cld")]) [(set_attr "type" "cld")])
(define_expand "movstrsi" (define_expand "movstrsi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "") [(use (match_operand:BLK 0 "memory_operand" ""))
(match_operand:BLK 1 "memory_operand" "")) (use (match_operand:BLK 1 "memory_operand" ""))
(use (match_operand:SI 2 "const_int_operand" "")) (use (match_operand:SI 2 "const_int_operand" ""))
(use (match_operand:SI 3 "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))])]
"" ""
" "
{ {
rtx addr0, addr1; rtx srcreg, destreg, countreg;
if (GET_CODE (operands[2]) != CONST_INT) if (GET_CODE (operands[2]) != CONST_INT)
FAIL; FAIL;
addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); srcreg = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
operands[5] = addr0; emit_insn (gen_cld());
operands[6] = addr1; /* When optimizing for size emit simple rep ; movsb instruction. */
if (!optimize || optimize_size)
operands[0] = change_address (operands[0], VOIDmode, addr0); {
operands[1] = change_address (operands[1], VOIDmode, addr1); countreg = copy_to_mode_reg (SImode, operands[2]);
emit_insn (gen_cld ()); 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. ;; Most CPUs don't like single string operations
;; But strength reduction might offset the MEM expression. So we let ;; Handle this case here to simplify previous expander.
;; reload put the address into %edi & %esi.
(define_insn "*movstrsi_1" (define_expand "strmovhi"
[(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) [(set (match_dup 2)
(mem:BLK (match_operand:SI 1 "address_operand" "S"))) (mem:HI (match_operand:SI 1 "register_operand" "")))
(use (match_operand:SI 2 "const_int_operand" "n")) (set (mem:HI (match_operand:SI 0 "register_operand" ""))
(use (match_operand:SI 3 "immediate_operand" "i")) (match_dup 2))
(use (reg:SI 19)) (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 2)))
(clobber (match_scratch:SI 4 "=&c")) (clobber (reg:CC 17))])
(clobber (match_dup 0)) (parallel [(set (match_dup 1) (plus:SI (match_dup 1) (const_int 2)))
(clobber (match_dup 1))] (clobber (reg:CC 17))])]
"" ""
"* "
{ {
rtx xops[2]; if (TARGET_SINGLE_STRINGOP || optimize_size)
if (GET_CODE (operands[2]) == CONST_INT)
{ {
if (INTVAL (operands[2]) & ~0x03) emit_insn (gen_strmovhi_1 (operands[0], operands[1], operands[0],
{ operands[1]));
xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff); DONE;
xops[1] = operands[4]; }
else
operands[2] = gen_reg_rtx (HImode);
}")
output_asm_insn (\"mov{l}\\t{%0, %1|%1,%0}\", xops); (define_expand "strmovqi"
output_asm_insn (\"{rep\;movsl|rep movsd}\", xops); [(set (match_dup 2)
} (mem:QI (match_operand:SI 1 "register_operand" "")))
if (INTVAL (operands[2]) & 0x02) (set (mem:QI (match_operand:SI 0 "register_operand" ""))
output_asm_insn (\"movsw\", operands); (match_dup 2))
if (INTVAL (operands[2]) & 0x01) (parallel [(set (match_dup 0) (plus:SI (match_dup 0) (const_int 1)))
output_asm_insn (\"movsb\", operands); (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 else
abort (); operands[2] = gen_reg_rtx (QImode);
RET; }")
}"
[(set_attr "type" "multi")]) (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" (define_expand "clrstrsi"
[(set (reg:SI 19) (const_int 0)) [(set (reg:SI 19) (const_int 0))
...@@ -7916,8 +8007,6 @@ ...@@ -7916,8 +8007,6 @@
operands[5] = addr0; operands[5] = addr0;
operands[0] = gen_rtx_MEM (BLKmode, addr0); operands[0] = gen_rtx_MEM (BLKmode, addr0);
emit_insn (gen_cld ());
}") }")
;; It might seem that operand 0 could use predicate register_operand. ;; It might seem that operand 0 could use predicate register_operand.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment