This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
i386.md splits II
- To: egcs-patches at cygnus dot com
- Subject: i386.md splits II
- From: Jan Hubicka <hubicka at atrey dot karlin dot mff dot cuni dot cz>
- Date: Thu, 1 Oct 1998 15:43:31 +0200
Hi
I've found some more | I've overlooked in last mail, so sending it once
again (and also because I am not sure, that I've sent the previous one :)
I've also fixed the spacing problems I know of and changed | to || and found
a bug in comment :)
Changes:
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")