[committed] Make mips.md use seb/seh where available

Richard Sandiford rsandifo@redhat.com
Sat Sep 4 08:03:00 GMT 2004


At the moment, mips.md provides three define_insns for sign-extension:

  - one for register source operands (split after reload)
  - one for memory source operands
  - one for register source operands if ISA_HAS_SEB_SEH ({QI,HI}->SI only)

Unfortunately, the seb/seh version came after the non-seb/seh version
(and its define_split), so was never actually used.  Fixed with the
patch below.

I was also never too happy with having separate register and memory
patterns.  My understanding is that reload and post-reload passes are
more likely to do a good job if the alternatives are described by a
single define_insn.  For example, a register source operand that gets
spilled to the stack can then be replaced by its stack slot (rather
than being reloaded into another register).  I didn't find any examples
in gcc.c-torture or gcc.dg at -O2 for this particular patch, but I did
for the follow-on patch for zero_extend.

The patch also takes the opportunity to macroise the patterns.  As a
side-effect, this gives us {QI,HI}->DI seb/seh patterns "for free",
and although they aren't used yet, they should just work once
ISA_HAS_SEB_SEH is extended to include 64-bit archs.  (I don't
normally like adding patterns that aren't used yet, but in this case,
it's easier to define them than not.)

Bootstrapped & regression tested on mips-sgi-irix6.5.  I compared the
before and after output of gcc.c-torture and gcc.dg for:

    {-mips16,-mips64,-mips3}{-mabi=32,-mabi=eabi}

using a mipsisa64-elf configuration.  There were no changes.  I also did
the same for -mips32r2/-mabi=32, and as expected, there were lots of new
uses of seb and seh.  Applied to mainline.

Richard


	* config/mips/mips.md (SHORT): New mode macro.
	(size): New mode attribute.
	(extend[qh]i[sd]i2): Redefine using :GPR and :SHORT.
	(*extend[qh]i[sd]i2): New define_insn_and_split, combining previous
	*extend[qh]i[sd]i2 and *extend[qh]i[sd]i2_mem patterns.  Use only if
	!ISA_HAS_SEB_SEH.
	(*extend[qh]i[sd]i2_se[bh]): New pattern, combining previous
	*extend[qh]isi2_hw patterns and extending them to di.
	(extendqihi2): Implement as define_insn_and_split that produces
	extendqisi2 after reload.

Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.302
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.302 mips.md
*** config/mips/mips.md	3 Sep 2004 20:12:28 -0000	1.302
--- config/mips/mips.md	4 Sep 2004 07:24:42 -0000
*************** (define_mode_macro P [(SI "Pmode == SImo
*** 324,329 ****
--- 324,333 ----
  ;; conditional-move-type condition is needed.
  (define_mode_macro MOVECC [SI (DI "TARGET_64BIT") (CC "TARGET_HARD_FLOAT")])
  
+ ;; This mode macro allows the QI and HI extension patterns to be defined from
+ ;; the same template.
+ (define_mode_macro SHORT [QI HI])
+ 
  ;; This mode macro allows :ANYF to be used wherever a scalar or vector
  ;; floating-point mode is allowed.
  (define_mode_macro ANYF [(SF "TARGET_HARD_FLOAT")
*************** (define_mode_macro SCALARF [(SF "TARGET_
*** 338,343 ****
--- 342,351 ----
  ;; 32-bit version and "dsubu" in the 64-bit version.
  (define_mode_attr d [(SI "") (DI "d")])
  
+ ;; This attribute gives the length suffix for a sign- or zero-extension
+ ;; instruction.
+ (define_mode_attr size [(QI "b") (HI "h")])
+ 
  ;; Mode attributes for GPR loads and stores.
  (define_mode_attr load [(SI "lw") (DI "ld")])
  (define_mode_attr store [(SI "sw") (DI "sd")])
*************** (define_insn_and_split "extendsidi2"
*** 2479,2672 ****
    [(set_attr "type" "arith,load")
     (set_attr "mode" "DI")])
  
! ;; These patterns originally accepted general_operands, however, slightly
! ;; better code is generated by only accepting register_operands, and then
! ;; letting combine generate the lh and lb insns.
! 
! ;; These expanders originally put values in registers first. We split
! ;; all non-mem patterns after reload.
! 
! (define_expand "extendhidi2"
!   [(set (match_operand:DI 0 "register_operand")
!         (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand")))]
!   "TARGET_64BIT"
    "")
  
! (define_insn "*extendhidi2"
!   [(set (match_operand:DI 0 "register_operand" "=d")
!         (sign_extend:DI (match_operand:HI 1 "register_operand" "d")))]
!   "TARGET_64BIT"
!   "#")
! 
! (define_split
!   [(set (match_operand:DI 0 "register_operand")
!         (sign_extend:DI (match_operand:HI 1 "register_operand")))]
!   "TARGET_64BIT && reload_completed"
!   [(set (match_dup 0)
!         (ashift:DI (match_dup 1) (const_int 48)))
!    (set (match_dup 0)
!         (ashiftrt:DI (match_dup 0) (const_int 48)))]
!   "operands[1] = gen_lowpart (DImode, operands[1]);")
! 
! (define_insn "*extendhidi2_mem"
!   [(set (match_operand:DI 0 "register_operand" "=d")
!         (sign_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
!   "TARGET_64BIT"
!   "lh\t%0,%1"
!   [(set_attr "type"     "load")
!    (set_attr "mode"     "DI")])
! 
! (define_expand "extendhisi2"
!   [(set (match_operand:SI 0 "register_operand")
!         (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand")))]
!   ""
! {
!   if (ISA_HAS_SEB_SEH)
!     {
!       emit_insn (gen_extendhisi2_hw (operands[0],
! 				     force_reg (HImode, operands[1])));
!       DONE;
!     }
! })
! 
! (define_insn "*extendhisi2"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (sign_extend:SI (match_operand:HI 1 "register_operand" "d")))]
!   ""
!   "#")
! 
! (define_split
!   [(set (match_operand:SI 0 "register_operand")
!         (sign_extend:SI (match_operand:HI 1 "register_operand")))]
!   "reload_completed"
!   [(set (match_dup 0)
!         (ashift:SI (match_dup 1) (const_int 16)))
!    (set (match_dup 0)
!         (ashiftrt:SI (match_dup 0) (const_int 16)))]
!   "operands[1] = gen_lowpart (SImode, operands[1]);")
! 
! (define_insn "extendhisi2_mem"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
!   ""
!   "lh\t%0,%1"
!   [(set_attr "type"     "load")
!    (set_attr "mode"     "SI")])
  
! (define_insn "extendhisi2_hw"
!   [(set (match_operand:SI 0 "register_operand" "=r")
! 	(sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
    "ISA_HAS_SEB_SEH"
!   "seh\t%0,%1"
!   [(set_attr "type" "arith")
!    (set_attr "mode" "SI")])
! 
! (define_expand "extendqihi2"
!   [(set (match_operand:HI 0 "register_operand")
!         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
!   ""
!   "")
! 
! (define_insn "*extendqihi2"
!   [(set (match_operand:HI 0 "register_operand" "=d")
!         (sign_extend:HI (match_operand:QI 1 "register_operand" "d")))]
!   ""
!   "#")
! 
! (define_split
!   [(set (match_operand:HI 0 "register_operand")
!         (sign_extend:HI (match_operand:QI 1 "register_operand")))]
!   "reload_completed"
!   [(set (match_dup 0)
!         (ashift:SI (match_dup 1) (const_int 24)))
!    (set (match_dup 0)
!         (ashiftrt:SI (match_dup 0) (const_int 24)))]
!   "operands[0] = gen_lowpart (SImode, operands[0]);
!    operands[1] = gen_lowpart (SImode, operands[1]);")
! 
! (define_insn "*extendqihi2_internal_mem"
!   [(set (match_operand:HI 0 "register_operand" "=d")
!         (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
!   ""
!   "lb\t%0,%1"
!   [(set_attr "type"     "load")
!    (set_attr "mode"     "SI")])
! 
! 
! (define_expand "extendqisi2"
!   [(set (match_operand:SI 0 "register_operand")
!         (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand")))]
!   ""
! {
!   if (ISA_HAS_SEB_SEH)
!     {
!       emit_insn (gen_extendqisi2_hw (operands[0],
! 				     force_reg (QImode, operands[1])));
!       DONE;
!     }
! })
  
! (define_insn "*extendqisi2"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (sign_extend:SI (match_operand:QI 1 "register_operand" "d")))]
    ""
!   "#")
! 
! (define_split
!   [(set (match_operand:SI 0 "register_operand")
!         (sign_extend:SI (match_operand:QI 1 "register_operand")))]
    "reload_completed"
!   [(set (match_dup 0)
!         (ashift:SI (match_dup 1) (const_int 24)))
!    (set (match_dup 0)
!         (ashiftrt:SI (match_dup 0) (const_int 24)))]
!   "operands[1] = gen_lowpart (SImode, operands[1]);")
! 
! (define_insn "*extendqisi2_mem"
!   [(set (match_operand:SI 0 "register_operand" "=d")
!         (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
!   ""
!   "lb\t%0,%1"
!   [(set_attr "type"     "load")
!    (set_attr "mode"     "SI")])
! 
! (define_insn "extendqisi2_hw"
!   [(set (match_operand:SI 0 "register_operand" "=r")
! 	(sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
!   "ISA_HAS_SEB_SEH"
!   "seb\t%0,%1"
!   [(set_attr "type" "arith")
!    (set_attr "mode" "SI")])
! 
! (define_expand "extendqidi2"
!   [(set (match_operand:DI 0 "register_operand")
!         (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand")))]
!   "TARGET_64BIT"
!   "")
! 
! (define_insn "*extendqidi2"
!   [(set (match_operand:DI 0 "register_operand" "=d")
!         (sign_extend:DI (match_operand:QI 1 "register_operand" "d")))]
!   "TARGET_64BIT"
!   "#")
! 
! (define_split
!   [(set (match_operand:DI 0 "register_operand")
!         (sign_extend:DI (match_operand:QI 1 "register_operand")))]
!   "TARGET_64BIT && reload_completed"
!   [(set (match_dup 0)
!         (ashift:DI (match_dup 1) (const_int 56)))
!    (set (match_dup 0)
!         (ashiftrt:DI (match_dup 0) (const_int 56)))]
!   "operands[1] = gen_lowpart (DImode, operands[1]);")
! 
! (define_insn "*extendqidi2_mem"
!   [(set (match_operand:DI 0 "register_operand" "=d")
!         (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
!   "TARGET_64BIT"
!   "lb\t%0,%1"
!   [(set_attr "type"     "load")
!    (set_attr "mode"     "DI")])
  
  (define_insn "extendsfdf2"
    [(set (match_operand:DF 0 "register_operand" "=f")
--- 2487,2541 ----
    [(set_attr "type" "arith,load")
     (set_attr "mode" "DI")])
  
! (define_expand "extend<SHORT:mode><GPR:mode>2"
!   [(set (match_operand:GPR 0 "register_operand")
!         (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
    "")
  
! (define_insn_and_split "*extend<SHORT:mode><GPR:mode>2"
!   [(set (match_operand:GPR 0 "register_operand" "=d,d")
!         (sign_extend:GPR
! 	     (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
!   "!ISA_HAS_SEB_SEH"
!   "@
!    #
!    l<SHORT:size>\t%0,%1"
!   "&& reload_completed && REG_P (operands[1])"
!   [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2)))
!    (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))]
! {
!   operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
!   operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode)
! 			 - GET_MODE_BITSIZE (<SHORT:MODE>mode));
! }
!   [(set_attr "type" "arith,load")
!    (set_attr "mode" "<GPR:MODE>")
!    (set_attr "length" "8,*")])
  
! (define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>"
!   [(set (match_operand:GPR 0 "register_operand" "=d,d")
!         (sign_extend:GPR
! 	     (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
    "ISA_HAS_SEB_SEH"
!   "@
!    se<SHORT:size>\t%0,%1
!    l<SHORT:size>\t%0,%1"
!   [(set_attr "type" "arith,load")
!    (set_attr "mode" "<GPR:MODE>")])
  
! ;; This pattern generates the same code as extendqisi2; split it into
! ;; that form after reload.
! (define_insn_and_split "extendqihi2"
!   [(set (match_operand:HI 0 "register_operand" "=d,d")
!         (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
    ""
!   "#"
    "reload_completed"
!   [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
!   { operands[0] = gen_lowpart (SImode, operands[0]); }
!   [(set_attr "type" "arith,load")
!    (set_attr "mode" "SI")
!    (set_attr "length" "8,*")])
  
  (define_insn "extendsfdf2"
    [(set (match_operand:DF 0 "register_operand" "=f")



More information about the Gcc-patches mailing list