i386.md splits II

Robert Lipe robertl@dgii.com
Thu Oct 1 08:47:00 GMT 1998


Since Jan has told me in private mail that he didn't have access to the
testsuite, I thought I'd run it through the normal (no PIC)  GCC-only
testsuite for him.

i686-pc-sco3.2v5.0.5 shows no regressions with this patch.

gcc.c-torture/compile/930217-1.c hangs during the compile, but it did
that before this patch was applied.

RJL


Jan Hubicka wrote:
> 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")



More information about the Gcc-patches mailing list