This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch for i386 string operations



Hi
This patch rewrites movstrsi expander to expand into real instructions
and adds several patterns for rep ; movsb, rep ; movsl, movsw and movwb
instructions.

Unlike my patch from August it don't attempt to handle more cases than
the old expander, so it is quite simple.
Unlike the old expander I am now using simple rep ; movsb for optimize_size
and !optimize.
I've also added simple code to avoid single string operations (movsb, movsw
instructions) controled by the TARGET_SINGLE_STRINGOP macro.

Once we agree on the scheme, I will rewrite other string operations and
add new optimizations (inlining of variable size stringops, alignment
handling etc. ) later.

San Jan  9 05:14:37 CET 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.
	
*** i386.md.nomemcpy	Sun Jan  9 05:14:05 2000
--- i386.md	Sun Jan  9 05:14:09 2000
***************
*** 7822,7892 ****
    [(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))])]
    ""
    "
  {
!   rtx addr0, addr1;
  
    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));
  
!   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 ());
  }")
  
  ;; 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.
  
! (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))]
!   ""
!   "*
! {
!   rtx xops[2];
  
!   if (GET_CODE (operands[2]) == CONST_INT)
!     {
!       if (INTVAL (operands[2]) & ~0x03)
! 	{
! 	  xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
! 	  xops[1] = operands[4];
  
! 	  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);
!     }
!   else
!     abort ();
!   RET;
! }"
!   [(set_attr "type" "multi")])
  
  (define_expand "clrstrsi"
    [(set (reg:SI 19) (const_int 0))
--- 7822,7987 ----
    [(set_attr "type" "cld")])
  
  (define_expand "movstrsi"
!   [(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 srcreg, destreg, countreg;
  
    if (GET_CODE (operands[2]) != CONST_INT)
      FAIL;
  
!   destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
!   srcreg = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
  
!   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;
! }")
! 
! ;; Most CPUs don't like single string operations
! ;; Handle this case here to simplify previous expander.
! 
! (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))])]
!   ""
!   "
! {
!   if (TARGET_SINGLE_STRINGOP || optimize_size)
!     {
!       emit_insn (gen_strmovhi_1 (operands[0], operands[1], operands[0],
! 				operands[1]));
!       DONE;
!     }
!   else 
!     operands[2] = gen_reg_rtx (HImode);
! }")
  
! (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 
!     operands[2] = gen_reg_rtx (QImode);
  }")
  
  ;; 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.
  
! (define_insn "strmovhi_1"
!   [(set (mem:HI (match_operand:SI 0 "address_operand" "D"))
! 	(mem:HI (match_operand:SI 1 "address_operand" "S")))
!    (set (match_operand:SI 2 "register_operand" "=0")
! 	(plus:SI (match_dup 0)
! 		 (const_int 1)))
!    (set (match_operand:SI 3 "register_operand" "=1")
! 	(plus:SI (match_dup 1)
! 		 (const_int 1)))
!    (use (reg:SI 19))]
!   "TARGET_SINGLE_STRINGOP"
!   "movsw"
!   [(set_attr "type" "str")
!    (set_attr "memory" "both")
!    (set_attr "length_prefix" "1")])
! 
! (define_insn "strmovqi_1"
!   [(set (mem:QI (match_operand:SI 0 "address_operand" "D"))
! 	(mem:QI (match_operand:SI 1 "address_operand" "S")))
!    (set (match_operand:SI 2 "register_operand" "=0")
! 	(plus:SI (match_dup 0)
! 		 (const_int 1)))
!    (set (match_operand:SI 3 "register_operand" "=1")
! 	(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 5))))
!    (set (match_operand:SI 1 "register_operand" "=S") 
!         (plus:SI (match_operand:SI 4 "address_operand" "1")
! 	         (ashift:SI (match_dup 5) (const_int 5))))
!    (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))
*** ../i386.old/i386.h	Sun Jan  9 03:14:53 2000
--- i386.h	Sun Jan  9 03:35:21 2000
*************** extern const int x86_double_with_add, x8
*** 161,167 ****
  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;
  
  #define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
  #define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
--- 161,167 ----
  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, x86_single_stringop;
  
  #define TARGET_USE_LEAVE (x86_use_leave & CPUMASK)
  #define TARGET_PUSH_MEMORY (x86_push_memory & CPUMASK)
*************** extern const int x86_promote_QImode;
*** 184,189 ****
--- 184,190 ----
  #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)
  
*** ../i386.old/i386.c	Sun Jan  9 03:14:53 2000
--- i386.c	Sun Jan  9 03:36:05 2000
*************** const int x86_read_modify_write = ~m_PEN
*** 206,211 ****
--- 206,212 ----
  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))
  

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]