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]

i386.md splits 1


Hi
In order to speedup process I've speparated the movdi extend and zero_extend
patterns. I don't have any chance to test new patch here, but hope I dodn't
made any trivial mistake :). I hope it will serve reviewing purposes, otherwise
just ignore it.

I've also fixed the spacing problems I know of and changed | to || and found
a bug in comment and ChangeLog entry :)

Changes since last letter:
 o Added patterns for (set edx (ashiftrt eax 31)) that is handled
   by cltd
   this constraint is used by sign_extend pattern, should be used
   by divmod patterns and surprisingly it match sometimes :)
 o Simplify extendsidi splits/pattern to use previous pattern
   now uses #, so some code duplication is gone
 o zero_extendsidi pattern now uses # and is handled by splits
 o Split trivial and most common case of movdi patterns
   (it also lets compiler clear register using xor etc.)
 o Added define_split for extendsidi pattern. It now uses combination of
   insn (ctld) and split. Split works just in case, that there is other
   register than eax after reload.
   Also extendsidi works at memory operands to let gcc zero extend value
   directly in stack (probably still faster than swap out registers, swap in
   value, extend value, swap out it and swap in registers)
   Also supports extending from one register/memory to another to avoid
   gcc moving extended value from register to register.
   Same for zero_extendsidi
Sep 29 08:58:58 1998  Jan Hubicka <hubicka@freesoft.cz>

	* i386.md: 
	(movdi): split the trivial (non-overlapping) case
	(zero_extendsidi2): split it, support extending from other
	register and to memory to avoid unnecesary moves of extended value
	Use # in pattern and handle completely by splits.
	(extendsidi2): likewise, don't generate cltd at pentium, added pattern
	for ashiftrt reg 31 from eax to edx that uses cltd instruction.
	extendsidi split uses it.
	(ashiftrt_32): New pattern


*** gcc/config/i386/i386.md.old	Thu Oct  1 13:32:25 1998
--- gcc/config/i386/i386.md	Thu Oct  1 13:36:20 1998
***************
*** 1782,1787 ****
--- 1782,1798 ----
    [(set_attr "type" "integer,memory")
     (set_attr "memory" "*,load")])
  
+ ;; Split the trivial (and common) case of movdi
+ (define_split 
+   [(set (match_operand:DI 0 "general_operand" "or")
+ 	(match_operand:DI 1 "general_operand" "or"))]
+   "!reg_overlap_mentioned_p (operands[0], operands[1])
+    && (reload_completed || reload_in_progress)"
+   [(set (match_dup 3) (match_dup 5))
+    (set (match_dup 4) (match_dup 6))]
+   "split_di (&operands[0], 1, &operands[3], &operands[4]);
+    split_di (&operands[1], 1, &operands[5], &operands[6]);")
+ 
  
  ;;- conversion instructions
  ;;- NONE
***************
*** 2023,2080 ****
  
  (define_insn "zero_extendsidi2"
    [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
! 	(zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))]
    ""
!   "*
!   {
!   rtx high[2], low[2], xops[4];
! 
!   if (REG_P (operands[0]) && REG_P (operands[1])
!       && REGNO (operands[0]) == REGNO (operands[1]))
!     {
!       operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
!       return AS2 (xor%L0,%0,%0);
!     }
! 
!   split_di (operands, 1, low, high);
!   xops[0] = low[0];
!   xops[1] = operands[1];
!   xops[2] = high[0];
!   xops[3] = const0_rtx;
! 
!   output_asm_insn (AS2 (mov%L0,%1,%0), xops);
!   if (GET_CODE (low[0]) == MEM)
!     output_asm_insn (AS2 (mov%L2,%3,%2), xops);
!   else
!     output_asm_insn (AS2 (xor%L2,%2,%2), xops);
  
!   RET;
! }")
  
  ;;- sign extension instructions
  
  (define_insn "extendsidi2"
!   [(set (match_operand:DI 0 "register_operand" "=r")
! 	(sign_extend:DI (match_operand:SI 1 "register_operand" "0")))]
    ""
!   "*
! {
!   if (REGNO (operands[0]) == 0)
!     {
!       /* This used to be cwtl, but that extends HI to SI somehow.  */
! #ifdef INTEL_SYNTAX
!       return \"cdq\";
! #else
!       return \"cltd\";
! #endif
!     }
  
!   operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
!   output_asm_insn (AS2 (mov%L0,%0,%1), operands);
! 
!   operands[0] = GEN_INT (31);
!   return AS2 (sar%L1,%0,%1);
! }")
  
  ;; Note that the i386 programmers' manual says that the opcodes
  ;; are named movsx..., but the assembler on Unix does not accept that.
--- 2034,2097 ----
  
  (define_insn "zero_extendsidi2"
    [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
! 	(zero_extend:DI (match_operand:SI 1 "general_operand" "0,rm,r")))]
    ""
!   "#")
  
! (define_split 
!   [(set (match_operand:DI 0 "nonimmediate_operand" "")
! 	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
!   "reload_completed || reload_in_progress"
!   [(set (match_dup 3) (match_dup 1))
!    (set (match_dup 4) (const_int 0))]
!   "split_di (&operands[0], 1, &operands[3], &operands[4]);")
  
  ;;- sign extension instructions
  
  (define_insn "extendsidi2"
!   [(set (match_operand:DI 0 "nonimmediate_operand" "=A,?r,?Ar,?o")
! 	(sign_extend:DI (match_operand:SI 1 "general_operand" "0,0,mr,r")))]
    ""
!   "#")
  
! ;; When parameter is in register it is better to copy from it to avoid
! ;; dependencies
! (define_split 
!   [(set (match_operand:DI 0 "nonimmediate_operand" "or")
! 	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))]
!   "(reload_completed | reload_in_progress)
!    && (!REG_P (operands[0]) || REGNO (operands[0]) != 0
!    || (!optimize_size && ix86_cpu == PROCESSOR_PENTIUM))"
!   [(set (match_dup 4) (match_dup 1))
!    (set (match_dup 3) (match_dup 1))
!    (set (match_dup 4)
!         (ashiftrt:SI (match_dup 4) (const_int 31)))
!   ]
!   "split_di (&operands[0], 1, &operands[3], &operands[4]);")
! 
! ;; When parameter is in memory, copy it to destination and then again
! (define_split 
!   [(set (match_operand:DI 0 "nonimmediate_operand" "r")
! 	(sign_extend:DI (match_operand:SI 1 "general_operand" "mr")))]
!   "(reload_completed | reload_in_progress) 
!    && (!REG_P (operands[0]) || REGNO (operands[0]) != 0  
!    || (!optimize_size && ix86_cpu==PROCESSOR_PENTIUM))"
!   [(set (match_dup 3) (match_dup 1))
!    (set (match_dup 4) (match_dup 3))
!    (set (match_dup 4)
!         (ashiftrt:SI (match_dup 4) (const_int 31)))
!   ]
!   "split_di (&operands[0], 1, &operands[3], &operands[4]);")
! 
! (define_split 
!   [(set (match_operand:DI 0 "register_operand" "A")
! 	(sign_extend:DI (match_operand:SI 1 "general_operand" "mr")))]
!   "(reload_completed || reload_in_progress)
!    && (optimize_size || ix86_cpu!=PROCESSOR_PENTIUM)"
!   [(set (match_dup 3) (match_dup 1))
!    (set (match_dup 4)
!         (ashiftrt:SI (match_dup 3) (const_int 31)))]
!   "split_di (&operands[0], 1, &operands[3], &operands[4]);")
  
  ;; Note that the i386 programmers' manual says that the opcodes
  ;; are named movsx..., but the assembler on Unix does not accept that.
*************** byte_xor_operation:
*** 4850,4855 ****
--- 4867,4881 ----
  
    RET;
  }")
+ 
+ (define_insn "ashrsi3_31"
+   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,d")
+ 	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,a")
+ 		     (const_int 31)))]
+   "ix86_cpu != PROCESSOR_PENTIUM || optimize_size"
+   "@
+     sar%L0 $31,%0
+     cltd")
  
  (define_insn "ashrsi3"
    [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")


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