public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] h8300: Optimize compare.
@ 2002-12-21  9:43 Kazu Hirata
  0 siblings, 0 replies; only message in thread
From: Kazu Hirata @ 2002-12-21  9:43 UTC (permalink / raw)
  To: gcc-patches

Hi,

Attached is a patch to optimize compare.

A comparison followed by beq or bne like this

	cmp.w	#2,r2
 	beq	.L19

can be converted into

	dec.w	#2,r2
 	beq	.L19

if the register being compared is known to be dead while saving a few
bytes.

The patch implements the above transformation as peepholes.

Tested on h8300 port.  Committed.

Kazu Hirata

2002-12-21  Kazu Hirata  <kazu@cs.umass.edu>

	* config/h8300/h8300-protos.h: Update the prototype for
	split_adds_subs.
	Add prototypes for const_le_2_operand and const_le_6_operand.
	* config/h8300/h8300.c (split_adds_subs): Add an argument to
	specify whether inc/dec should be used when possible.
	(const_le_2_operand): New.
	(const_le_6_operand): Likewise.
	* config/h8300/h8300.md (two peepholes): New.

Index: h8300-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300-protos.h,v
retrieving revision 1.35
diff -c -r1.35 h8300-protos.h
*** h8300-protos.h	20 Dec 2002 20:53:51 -0000	1.35
--- h8300-protos.h	21 Dec 2002 17:34:17 -0000
***************
*** 47,53 ****
  extern int expand_a_rotate PARAMS ((enum rtx_code, rtx[]));
  extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
  extern int h8300_adjust_insn_length PARAMS ((rtx, int));
! extern void split_adds_subs PARAMS ((enum machine_mode, rtx[]));
  
  extern int general_operand_src PARAMS ((rtx, enum machine_mode));
  extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
--- 47,53 ----
  extern int expand_a_rotate PARAMS ((enum rtx_code, rtx[]));
  extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
  extern int h8300_adjust_insn_length PARAMS ((rtx, int));
! extern void split_adds_subs PARAMS ((enum machine_mode, rtx[], int));
  
  extern int general_operand_src PARAMS ((rtx, enum machine_mode));
  extern int general_operand_dst PARAMS ((rtx, enum machine_mode));
***************
*** 59,64 ****
--- 59,66 ----
  extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
  extern int bit_operand PARAMS ((rtx, enum machine_mode));
  extern int bit_memory_operand PARAMS ((rtx, enum machine_mode));
+ extern int const_le_2_operand PARAMS ((rtx, enum machine_mode));
+ extern int const_le_6_operand PARAMS ((rtx, enum machine_mode));
  extern int incdec_operand PARAMS ((rtx, enum machine_mode));
  extern int bit_operator PARAMS ((rtx, enum machine_mode));
  extern int nshift_operator PARAMS ((rtx, enum machine_mode));
Index: h8300.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.c,v
retrieving revision 1.179
diff -c -r1.179 h8300.c
*** h8300.c	20 Dec 2002 20:53:51 -0000	1.179
--- h8300.c	21 Dec 2002 17:34:18 -0000
***************
*** 916,932 ****
    return 0;
  }
  
! /* Split an add of a small constant into two adds/subs insns.  */
  
  void
! split_adds_subs (mode, operands)
       enum machine_mode mode;
       rtx *operands;
  {
    HOST_WIDE_INT val = INTVAL (operands[1]);
    rtx reg = operands[0];
    HOST_WIDE_INT sign = 1;
    HOST_WIDE_INT amount;
  
    /* Force VAL to be positive so that we do not have to consider the
       sign.  */
--- 916,938 ----
    return 0;
  }
  
! /* Split an add of a small constant into two adds/subs insns.
! 
!    If USE_INCDEC_P is nonzero, we generate the last insn using inc/dec
!    instead of adds/subs.  */
  
  void
! split_adds_subs (mode, operands, use_incdec_p)
       enum machine_mode mode;
       rtx *operands;
+      int use_incdec_p;
  {
    HOST_WIDE_INT val = INTVAL (operands[1]);
    rtx reg = operands[0];
    HOST_WIDE_INT sign = 1;
    HOST_WIDE_INT amount;
+   rtx (*gen_last) (rtx, rtx, rtx);
+   rtx (*gen_normal) (rtx, rtx, rtx);
  
    /* Force VAL to be positive so that we do not have to consider the
       sign.  */
***************
*** 936,941 ****
--- 942,963 ----
        sign = -1;
      }
  
+   switch (mode)
+     {
+     case HImode:
+       gen_normal = gen_addhi3;
+       gen_last   = gen_addhi3_incdec;
+       break;
+ 
+     case SImode:
+       gen_normal = gen_addsi3;
+       gen_last   = gen_addsi3_incdec;
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
    /* Try different amounts in descending order.  */
    for (amount = (TARGET_H8300H || TARGET_H8300S) ? 4 : 2;
         amount > 0;
***************
*** 943,950 ****
      {
        for (; val >= amount; val -= amount)
  	{
! 	  rtx tmp = gen_rtx_PLUS (mode, reg, GEN_INT (sign * amount));
! 	  emit_insn (gen_rtx_SET (VOIDmode, reg, tmp));
  	}
      }
  
--- 965,975 ----
      {
        for (; val >= amount; val -= amount)
  	{
! 	  /* If requested, generate the last insn using inc/dec.  */
! 	  if (use_incdec_p && amount <= 2 && val == amount)
! 	    emit_insn (gen_last (reg, reg, GEN_INT (sign * amount)));
! 	  else
! 	    emit_insn (gen_normal (reg, reg, GEN_INT (sign * amount)));
  	}
      }
  
***************
*** 1804,1809 ****
--- 1829,1858 ----
        CC_STATUS_INIT;
        break;
      }
+ }
+ 
+ /* Return nonzero if X is a constant whose absolute value is no
+    greater than 2.  */
+ 
+ int
+ const_le_2_operand (x, mode)
+      rtx x;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+   return (GET_CODE (x) == CONST_INT
+ 	  && abs (INTVAL (x)) <= 2);
+ }
+ 
+ /* Return nonzero if X is a constant whose absolute value is no
+    greater than 6.  */
+ 
+ int
+ const_le_6_operand (x, mode)
+      rtx x;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+ {
+   return (GET_CODE (x) == CONST_INT
+ 	  && abs (INTVAL (x)) <= 6);
  }
  
  /* Return nonzero if X is a constant suitable for inc/dec.  */
Index: h8300.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.md,v
retrieving revision 1.126
diff -c -r1.126 h8300.md
*** h8300.md	20 Dec 2002 20:53:52 -0000	1.126
--- h8300.md	21 Dec 2002 17:34:19 -0000
***************
*** 815,821 ****
  		 (match_operand:HI 1 "two_insn_adds_subs_operand" "")))]
    ""
    [(const_int 0)]
!   "split_adds_subs (HImode, operands); DONE;")
  
  (define_expand "addsi3"
    [(set (match_operand:SI 0 "register_operand" "")
--- 815,821 ----
  		 (match_operand:HI 1 "two_insn_adds_subs_operand" "")))]
    ""
    [(const_int 0)]
!   "split_adds_subs (HImode, operands, 0); DONE;")
  
  (define_expand "addsi3"
    [(set (match_operand:SI 0 "register_operand" "")
***************
*** 867,873 ****
  		 (match_operand:SI 1 "two_insn_adds_subs_operand" "")))]
    "TARGET_H8300H || TARGET_H8300S"
    [(const_int 0)]
!   "split_adds_subs (SImode, operands); DONE;")
  
  ;; ----------------------------------------------------------------------
  ;; SUBTRACT INSTRUCTIONS
--- 867,873 ----
  		 (match_operand:SI 1 "two_insn_adds_subs_operand" "")))]
    "TARGET_H8300H || TARGET_H8300S"
    [(const_int 0)]
!   "split_adds_subs (SImode, operands, 0); DONE;")
  
  ;; ----------------------------------------------------------------------
  ;; SUBTRACT INSTRUCTIONS
***************
*** 2872,2874 ****
--- 2872,2919 ----
  		      (label_ref (match_dup 2))
  		      (pc)))]
    "")
+ 
+ ;; For a small constant, it is cheaper to actually do the subtraction
+ ;; and then test the register.
+ 
+ (define_peephole2
+   [(set (cc0)
+ 	(compare:HI (match_operand:HI 0 "register_operand" "")
+ 		    (match_operand:HI 1 "const_le_2_operand" "")))
+    (set (pc)
+ 	(if_then_else (match_operator 3 "eqne_operator"
+ 			[(cc0) (const_int 0)])
+ 		      (label_ref (match_operand 2 "" ""))
+ 		      (pc)))]
+   "(TARGET_H8300H || TARGET_H8300S)
+    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
+   [(set (cc0)
+ 	(match_dup 0))
+    (set (pc)
+ 	(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ 		      (label_ref (match_operand 2 "" ""))
+ 		      (pc)))]
+   "operands[1] = GEN_INT (- INTVAL (operands[1]));
+    split_adds_subs (HImode, operands, 1);")
+ 
+ ;; The SImode version of the previous pattern.
+ 
+ (define_peephole2
+   [(set (cc0)
+ 	(compare:SI (match_operand:SI 0 "register_operand" "")
+ 		    (match_operand:SI 1 "const_le_6_operand" "")))
+    (set (pc)
+ 	(if_then_else (match_operator 3 "eqne_operator"
+ 			[(cc0) (const_int 0)])
+ 		      (label_ref (match_operand 2 "" ""))
+ 		      (pc)))]
+   "(TARGET_H8300H || TARGET_H8300S)
+    && find_regno_note (insn, REG_DEAD, REGNO (operands[0]))"
+   [(set (cc0)
+ 	(match_dup 0))
+    (set (pc)
+ 	(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+ 		      (label_ref (match_operand 2 "" ""))
+ 		      (pc)))]
+   "operands[1] = GEN_INT (- INTVAL (operands[1]));
+    split_adds_subs (SImode, operands, 1);")

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-12-21 17:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-12-21  9:43 [patch] h8300: Optimize compare Kazu Hirata

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).