This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
i386.md splits 1
- To: egcs-patches at cygnus dot com
- Subject: i386.md splits 1
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Thu, 1 Oct 1998 13:47:29 +0200
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")